deepspace 0.3.11 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/env/index.ts","../src/shared/roles.ts","../src/shared/protocol/yjs.ts","../src/shared/protocol/constants.ts","../src/shared/protocol/messages.ts","../src/client/auth/DeepSpaceAuthProvider.tsx","../src/client/auth/client.ts","../src/client/auth/token.ts","../src/client/auth/hooks.ts","../src/client/auth/AuthOverlay.tsx","../src/client/auth/helpers.tsx","../src/client/auth/GuestBanner.tsx","../src/client/storage/context.tsx","../src/client/storage/store.ts","../src/client/storage/ScopeRegistry.tsx","../src/client/storage/serverErrors.ts","../src/client/storage/RecordScope.tsx","../src/client/storage/ws-log.ts","../src/client/storage/hooks/useUser.ts","../src/client/storage/hooks/useQuery.ts","../src/client/storage/hooks/useMutations.ts","../src/client/storage/hooks/useUsers.ts","../src/client/storage/hooks/useYjs.ts","../src/client/storage/hooks/useUserLookup.ts","../src/client/storage/hooks/usePresence.ts","../src/client/storage/hooks/useYjsRoom.ts","../src/client/storage/hooks/useGameRoom.ts","../src/client/storage/hooks/useCanvas.ts","../src/client/storage/hooks/useCronMonitor.ts","../src/client/storage/hooks/useJobs.ts","../src/client/storage/hooks/usePresenceRoom.ts","../src/client/storage/connection-status.ts","../src/client/storage/useR2Files.ts","../src/client/storage/file-attachment-utils.ts","../src/client/storage/user-color.ts","../src/client/messaging/useMessages.ts","../src/client/messaging/useChannels.ts","../src/client/messaging/useReactions.ts","../src/client/messaging/useChannelMembers.ts","../src/client/messaging/useReadReceipts.ts","../src/client/messaging/useConversation.ts","../src/client/messaging/utils.ts","../src/client/messaging/conversation-utils.ts","../src/client/messaging/message-utils.ts","../src/client/directory/useConversations.ts","../src/client/directory/useCommunities.ts","../src/client/directory/usePosts.ts","../src/client/theme/DeepSpaceThemeProvider.tsx","../src/client/theme/applyTheme.ts","../src/client/theme/useIsDarkTheme.ts","../src/client/platform/PlatformProvider.tsx","../src/client/platform/usePlatformWS.ts","../src/client/integration/index.ts","../src/client/ai-stream.ts","../src/client/subscriptions/useSubscription.ts","../src/shared/subscription.ts","../src/client/subscriptions/PricingTable.tsx","../src/client/charges/useCheckout.ts","../src/ui/utils.ts","../src/ui/Card.tsx","../src/ui/Separator.tsx","../src/ui/Table.tsx","../src/ui/Tabs.tsx","../src/ui/Button.tsx","../src/ui/Input.tsx","../src/ui/Textarea.tsx","../src/ui/Select.tsx","../src/ui/Checkbox.tsx","../src/ui/Switch.tsx","../src/ui/Label.tsx","../src/ui/Badge.tsx","../src/ui/Avatar.tsx","../src/ui/Progress.tsx","../src/ui/Skeleton.tsx","../src/ui/CardGrid.tsx","../src/ui/Alert.tsx","../src/ui/Toast.tsx","../src/ui/EmptyState.tsx","../src/ui/Dialog.tsx","../src/ui/DropdownMenu.tsx","../src/ui/Tooltip.tsx","../src/ui/Modal.tsx","../src/ui/SearchInput.tsx"],"sourcesContent":["/**\n * Environment detection and URL configuration\n *\n * Determines environment and provides URLs for DeepSpace services.\n *\n * Environment detection priority:\n * 1. Build-time __DEEPSPACE_ENV__ define (set via esbuild/Vite)\n * 2. Runtime window.__DEEPSPACE_ENV__\n * 3. Server-side process.env.DEEPSPACE_ENV\n * 4. Hostname detection (fallback)\n */\n\nexport type Environment = 'dev' | 'prod'\n\ndeclare const __DEEPSPACE_ENV__: string | undefined\n\n// ============================================================================\n// Environment Configuration\n// ============================================================================\n\ninterface EnvironmentConfig {\n name: Environment\n /** Platform API worker URL */\n apiUrl: string\n /** Platform worker URL (RecordRoom, schema registry) */\n platformWorkerUrl: string\n /** Auth worker URL (Better Auth) */\n authUrl: string\n /** Auth sign-in page URL */\n authSignInUrl: string\n /** Auth sign-up page URL */\n authSignUpUrl: string\n /** Main DeepSpace app URL */\n mainAppUrl: string\n /** Builder dashboard URL */\n dashboardUrl: string\n}\n\nconst DEV_CONFIG: EnvironmentConfig = {\n name: 'dev',\n apiUrl: 'http://localhost:8795',\n platformWorkerUrl: 'http://localhost:8792',\n authUrl: 'http://localhost:8794',\n authSignInUrl: 'http://localhost:5173/sign-in',\n authSignUpUrl: 'http://localhost:5173/sign-up',\n mainAppUrl: 'http://localhost:5173',\n dashboardUrl: 'http://localhost:5174',\n}\n\nconst PROD_CONFIG: EnvironmentConfig = {\n name: 'prod',\n apiUrl: 'https://api-worker.deep.space',\n platformWorkerUrl: 'https://platform-worker.deep.space',\n authUrl: 'https://auth.deep.space',\n authSignInUrl: 'https://auth.deep.space/login/social',\n authSignUpUrl: 'https://auth.deep.space/login/social',\n mainAppUrl: 'https://deep.space',\n dashboardUrl: 'https://dashboard.deep.space',\n}\n\n// ============================================================================\n// Environment Detection\n// ============================================================================\n\nlet cachedEnvironment: Environment | null = null\n\nfunction parseEnv(value: string | undefined): Environment | null {\n if (!value) return null\n const v = value.toLowerCase()\n if (v === 'dev' || v === 'development') return 'dev'\n if (v === 'prod' || v === 'production') return 'prod'\n return null\n}\n\nexport function detectEnvironment(): Environment {\n if (cachedEnvironment) return cachedEnvironment\n\n // 1. Build-time define\n if (typeof __DEEPSPACE_ENV__ !== 'undefined') {\n const env = parseEnv(__DEEPSPACE_ENV__)\n if (env) {\n cachedEnvironment = env\n return env\n }\n }\n\n // 2. Runtime window variable\n if (typeof window !== 'undefined') {\n const windowEnv = (window as { __DEEPSPACE_ENV__?: string }).__DEEPSPACE_ENV__\n const env = parseEnv(windowEnv)\n if (env) {\n cachedEnvironment = env\n return env\n }\n }\n\n // 3. Server-side env var\n if (typeof window === 'undefined') {\n try {\n const env = parseEnv(process.env.DEEPSPACE_ENV)\n if (env) {\n cachedEnvironment = env\n return env\n }\n if (process.env.NODE_ENV !== 'production') {\n cachedEnvironment = 'dev'\n return 'dev'\n }\n } catch {\n // process may not exist in Workers\n }\n }\n\n // 4. Hostname detection\n if (typeof window !== 'undefined') {\n const hostname = window.location.hostname\n\n if (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname.startsWith('192.168.')\n ) {\n cachedEnvironment = 'dev'\n return 'dev'\n }\n\n // Production: app.space, *.app.space, deep.space, *.deep.space\n if (\n hostname === 'app.space' ||\n hostname.endsWith('.app.space') ||\n hostname === 'deep.space' ||\n hostname.endsWith('.deep.space')\n ) {\n cachedEnvironment = 'prod'\n return 'prod'\n }\n }\n\n // Default to prod for unknown domains\n cachedEnvironment = 'prod'\n return 'prod'\n}\n\nexport function getEnvironmentConfig(): EnvironmentConfig {\n const env = detectEnvironment()\n return env === 'dev' ? DEV_CONFIG : PROD_CONFIG\n}\n\n// ============================================================================\n// Convenience Getters\n// ============================================================================\n\nexport function getApiUrl(): string {\n return getEnvironmentConfig().apiUrl\n}\n\nexport function getPlatformWorkerUrl(): string {\n return getEnvironmentConfig().platformWorkerUrl\n}\n\nexport function getAuthUrl(): string {\n return getEnvironmentConfig().authUrl\n}\n\nexport function isLocalDev(): boolean {\n return detectEnvironment() === 'dev'\n}\n\nexport function isProduction(): boolean {\n return detectEnvironment() === 'prod'\n}\n\n/** Reset cached environment (useful for testing) */\nexport function resetEnvironmentCache(): void {\n cachedEnvironment = null\n}\n\n// ============================================================================\n// Convenience Object\n// ============================================================================\n\nexport const ENV = {\n get current() {\n return detectEnvironment()\n },\n get config() {\n return getEnvironmentConfig()\n },\n get apiUrl() {\n return getApiUrl()\n },\n get platformWorkerUrl() {\n return getPlatformWorkerUrl()\n },\n get authUrl() {\n return getAuthUrl()\n },\n get isLocal() {\n return isLocalDev()\n },\n get isProd() {\n return isProduction()\n },\n} as const\n","/**\n * Standard DeepSpace role constants.\n *\n * Every DeepSpace app uses the same three roles.\n * Apps can import these instead of defining them locally.\n */\n\nexport const ROLES = {\n VIEWER: 'viewer',\n MEMBER: 'member',\n ADMIN: 'admin',\n} as const\n\nexport type Role = (typeof ROLES)[keyof typeof ROLES]\n\nexport const ROLE_CONFIG: Record<Role, { title: string; badgeVariant: string; description: string }> = {\n viewer: { title: 'Viewer', badgeVariant: 'secondary', description: 'Read-only access' },\n member: { title: 'Member', badgeVariant: 'default', description: 'Can create and edit own content' },\n admin: { title: 'Admin', badgeVariant: 'warning', description: 'Full access to all features' },\n}\n","/**\n * Yjs Sync Protocol Implementation\n * \n * This implements the y-protocols sync and awareness protocols without\n * depending on y-websocket internal paths. Makes it easier to bundle\n * and template.\n * \n * Protocol spec: https://github.com/yjs/y-protocols\n */\n\nimport * as Y from 'yjs'\n\n// Message type constants\nexport const MSG_SYNC = 0\nexport const MSG_AWARENESS = 1\n\n// Sync message subtypes\nexport const MSG_SYNC_STEP1 = 0 // Send state vector\nexport const MSG_SYNC_STEP2 = 1 // Send diff based on received state vector\nexport const MSG_SYNC_UPDATE = 2 // Send incremental update\n\n// ============================================================================\n// Binary Encoding Utilities (lib0 compatible)\n// ============================================================================\n\nexport function createEncoder(): { data: number[] } {\n return { data: [] }\n}\n\nexport function toUint8Array(encoder: { data: number[] }): Uint8Array {\n return new Uint8Array(encoder.data)\n}\n\nexport function writeVarUint(encoder: { data: number[] }, num: number): void {\n while (num > 0x7f) {\n encoder.data.push((num & 0x7f) | 0x80)\n num = Math.floor(num / 128)\n }\n encoder.data.push(num & 0x7f)\n}\n\nexport function writeVarUint8Array(encoder: { data: number[] }, arr: Uint8Array): void {\n writeVarUint(encoder, arr.length)\n for (let i = 0; i < arr.length; i++) {\n encoder.data.push(arr[i])\n }\n}\n\nexport function createDecoder(data: Uint8Array): { data: Uint8Array; pos: number } {\n return { data, pos: 0 }\n}\n\nexport function readVarUint(decoder: { data: Uint8Array; pos: number }): number {\n let num = 0\n let mult = 1\n const len = decoder.data.length\n while (decoder.pos < len) {\n const byte = decoder.data[decoder.pos++]\n num += (byte & 0x7f) * mult\n mult *= 128\n if (byte < 0x80) {\n return num\n }\n }\n throw new Error('Unexpected end of buffer')\n}\n\nexport function readVarUint8Array(decoder: { data: Uint8Array; pos: number }): Uint8Array {\n const len = readVarUint(decoder)\n const arr = decoder.data.subarray(decoder.pos, decoder.pos + len)\n decoder.pos += len\n return arr\n}\n\nexport function hasContent(decoder: { data: Uint8Array; pos: number }): boolean {\n return decoder.pos < decoder.data.length\n}\n\n// ============================================================================\n// Sync Protocol\n// ============================================================================\n\n/**\n * Encode sync step 1: our state vector\n */\nexport function encodeSyncStep1(doc: Y.Doc): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_STEP1)\n writeVarUint8Array(encoder, Y.encodeStateVector(doc))\n return toUint8Array(encoder)\n}\n\n/**\n * Encode sync step 2: diff based on received state vector\n */\nexport function encodeSyncStep2(doc: Y.Doc, stateVector: Uint8Array): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_STEP2)\n writeVarUint8Array(encoder, Y.encodeStateAsUpdate(doc, stateVector))\n return toUint8Array(encoder)\n}\n\n/**\n * Encode an incremental update\n */\nexport function encodeUpdate(update: Uint8Array): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_UPDATE)\n writeVarUint8Array(encoder, update)\n return toUint8Array(encoder)\n}\n\nexport interface SyncResult {\n type: 'step1' | 'step2' | 'update'\n response?: Uint8Array\n stateVector?: Uint8Array\n update?: Uint8Array\n}\n\n/**\n * Handle an incoming sync message\n * Returns response to send (if any) and whether this was an update\n */\nexport function handleSyncMessage(doc: Y.Doc, data: Uint8Array): SyncResult {\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n \n if (messageType !== MSG_SYNC) {\n throw new Error(`Expected sync message (${MSG_SYNC}), got ${messageType}`)\n }\n \n const syncType = readVarUint(decoder)\n \n switch (syncType) {\n case MSG_SYNC_STEP1: {\n // Received state vector, send our diff\n const stateVector = readVarUint8Array(decoder)\n const response = encodeSyncStep2(doc, stateVector)\n return { type: 'step1', response, stateVector }\n }\n \n case MSG_SYNC_STEP2: {\n // Received diff, apply it\n const update = readVarUint8Array(decoder)\n Y.applyUpdate(doc, update)\n return { type: 'step2', update }\n }\n \n case MSG_SYNC_UPDATE: {\n // Received incremental update, apply it\n const update = readVarUint8Array(decoder)\n Y.applyUpdate(doc, update)\n return { type: 'update', update }\n }\n \n default:\n throw new Error(`Unknown sync type: ${syncType}`)\n }\n}\n\n// ============================================================================\n// Awareness Protocol\n// ============================================================================\n\nexport interface AwarenessState {\n [key: string]: unknown\n}\n\nexport interface AwarenessStates {\n [clientId: number]: AwarenessState\n}\n\n/**\n * Simple awareness implementation for presence/cursors\n */\nexport class Awareness {\n doc: Y.Doc\n clientID: number\n states: Map<number, AwarenessState> = new Map()\n private meta: Map<number, { clock: number; lastUpdated: number }> = new Map()\n private updateListeners: Set<(changes: { added: number[]; updated: number[]; removed: number[] }) => void> = new Set()\n private changeListeners: Set<(changes: { added: number[]; updated: number[]; removed: number[] }) => void> = new Set()\n\n constructor(doc: Y.Doc) {\n this.doc = doc\n this.clientID = doc.clientID\n }\n \n getStates(): Map<number, AwarenessState> {\n return this.states\n }\n \n getLocalState(): AwarenessState | null {\n return this.states.get(this.clientID) || null\n }\n \n setLocalState(state: AwarenessState | null): void {\n const clientID = this.clientID\n const prevState = this.states.get(clientID)\n \n if (state === null) {\n this.states.delete(clientID)\n this.meta.delete(clientID)\n if (prevState) {\n this.emit({ added: [], updated: [], removed: [clientID] })\n }\n } else {\n const meta = this.meta.get(clientID) || { clock: 0, lastUpdated: Date.now() }\n meta.clock++\n meta.lastUpdated = Date.now()\n this.meta.set(clientID, meta)\n this.states.set(clientID, state)\n this.emit({\n added: prevState ? [] : [clientID],\n updated: prevState ? [clientID] : [],\n removed: [],\n })\n }\n }\n \n setLocalStateField(field: string, value: unknown): void {\n const state = this.getLocalState() || {}\n state[field] = value\n this.setLocalState(state)\n }\n \n on(event: 'update' | 'change', handler: (changes: { added: number[]; updated: number[]; removed: number[] }) => void): void {\n if (event === 'update') {\n this.updateListeners.add(handler)\n } else if (event === 'change') {\n this.changeListeners.add(handler)\n }\n }\n\n off(event: 'update' | 'change', handler: (changes: { added: number[]; updated: number[]; removed: number[] }) => void): void {\n if (event === 'update') {\n this.updateListeners.delete(handler)\n } else if (event === 'change') {\n this.changeListeners.delete(handler)\n }\n }\n\n private emit(changes: { added: number[]; updated: number[]; removed: number[] }): void {\n for (const handler of this.updateListeners) {\n handler(changes)\n }\n if (changes.added.length > 0 || changes.updated.length > 0 || changes.removed.length > 0) {\n for (const handler of this.changeListeners) {\n handler(changes)\n }\n }\n }\n \n /**\n * Encode awareness update for specific clients\n */\n encodeUpdate(clientIds?: number[]): Uint8Array {\n const ids = clientIds || Array.from(this.states.keys())\n const encoder = createEncoder()\n writeVarUint(encoder, ids.length)\n \n for (const clientId of ids) {\n const state = this.states.get(clientId)\n const meta = this.meta.get(clientId) || { clock: 0, lastUpdated: Date.now() }\n \n writeVarUint(encoder, clientId)\n writeVarUint(encoder, meta.clock)\n \n const stateStr = state ? JSON.stringify(state) : 'null'\n const stateBytes = new TextEncoder().encode(stateStr)\n writeVarUint8Array(encoder, stateBytes)\n }\n \n return toUint8Array(encoder)\n }\n \n /**\n * Apply awareness update from another client\n */\n applyUpdate(data: Uint8Array): { added: number[]; updated: number[]; removed: number[] } {\n const decoder = createDecoder(data)\n const len = readVarUint(decoder)\n \n const added: number[] = []\n const updated: number[] = []\n const removed: number[] = []\n \n for (let i = 0; i < len; i++) {\n const clientId = readVarUint(decoder)\n const clock = readVarUint(decoder)\n const stateBytes = readVarUint8Array(decoder)\n const stateStr = new TextDecoder().decode(stateBytes)\n const state = stateStr === 'null' ? null : JSON.parse(stateStr) as AwarenessState\n \n const prevMeta = this.meta.get(clientId)\n const prevState = this.states.get(clientId)\n \n // Only apply if this is a newer update\n if (!prevMeta || prevMeta.clock < clock) {\n this.meta.set(clientId, { clock, lastUpdated: Date.now() })\n \n if (state === null) {\n this.states.delete(clientId)\n if (prevState) {\n removed.push(clientId)\n }\n } else {\n this.states.set(clientId, state)\n if (prevState) {\n updated.push(clientId)\n } else {\n added.push(clientId)\n }\n }\n }\n }\n \n if (added.length > 0 || updated.length > 0 || removed.length > 0) {\n this.emit({ added, updated, removed })\n }\n \n return { added, updated, removed }\n }\n \n /**\n * Remove awareness states for disconnected clients\n */\n removeStates(clientIds: number[]): void {\n const removed: number[] = []\n for (const clientId of clientIds) {\n if (this.states.has(clientId)) {\n this.states.delete(clientId)\n this.meta.delete(clientId)\n removed.push(clientId)\n }\n }\n if (removed.length > 0) {\n this.emit({ added: [], updated: [], removed })\n }\n }\n}\n\n/**\n * Encode a full awareness message\n */\nexport function encodeAwarenessMessage(awareness: Awareness, clientIds?: number[]): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_AWARENESS)\n writeVarUint8Array(encoder, awareness.encodeUpdate(clientIds))\n return toUint8Array(encoder)\n}\n\n/**\n * Decode and apply awareness message\n */\nexport function handleAwarenessMessage(\n awareness: Awareness, \n data: Uint8Array\n): { added: number[]; updated: number[]; removed: number[] } {\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n \n if (messageType !== MSG_AWARENESS) {\n throw new Error(`Expected awareness message (${MSG_AWARENESS}), got ${messageType}`)\n }\n \n const update = readVarUint8Array(decoder)\n return awareness.applyUpdate(update)\n}\n\n/**\n * Get message type from raw data\n */\nexport function getMessageType(data: Uint8Array): number {\n const decoder = createDecoder(data)\n return readVarUint(decoder)\n}\n\n","/**\n * Wire protocol constants.\n *\n * The JSON WebSocket protocol uses dotted string identifiers (e.g.\n * `\"game.input\"`) as the `type` discriminator. All message types are\n * grouped under a single `MSG` object so imports stay tidy:\n *\n * import { MSG, dispatch, clientBuild } from 'deepspace'\n *\n * dispatch<ServerMessage>(raw, {\n * [MSG.GAME_STATE]: (p) => { ... },\n * [MSG.GAME_TICK]: (p) => { ... },\n * })\n *\n * Each key's value is the on-wire string — grep-friendly, self-\n * documenting, and infinite per namespace. Adding a new message is one\n * line here plus one arm in the discriminated union in `./messages.ts`.\n *\n * Yjs binary protocol constants (`MSG_YJS_SYNC`, `MSG_YJS_AWARENESS`) are\n * intentionally kept numeric and separate from `MSG` — they ride a\n * binary WebSocket frame format and aren't part of the JSON dispatcher.\n */\n\nexport const MSG = {\n // ---- Records / CRUD --------------------------------------------------\n SUBSCRIBE: 'core.subscribe',\n UNSUBSCRIBE: 'core.unsubscribe',\n QUERY_RESULT: 'core.query_result',\n RECORD_CHANGE: 'core.record_change',\n PUT: 'core.put',\n DELETE: 'core.delete',\n ERROR: 'core.error',\n\n // ---- Users -----------------------------------------------------------\n USER_INFO: 'user.info',\n USER_LIST: 'user.list',\n SET_ROLE: 'user.set_role',\n USER_UPDATE: 'user.update',\n\n // ---- Yjs JSON control frames (binary sync lives in ./yjs.ts) ---------\n YJS_JOIN: 'yjs.join',\n YJS_LEAVE: 'yjs.leave',\n\n // ---- Records room misc -----------------------------------------------\n ACK: 'records.ack',\n LIST_SCHEMAS: 'records.list_schemas',\n RESUBSCRIBE: 'records.resubscribe',\n\n // ---- GameRoom --------------------------------------------------------\n GAME_STATE: 'game.state',\n GAME_INPUT: 'game.input',\n GAME_PLAYER_JOIN: 'game.player_join',\n GAME_PLAYER_LEAVE: 'game.player_leave',\n GAME_PLAYER_READY: 'game.player_ready',\n GAME_START: 'game.start',\n GAME_END: 'game.end',\n GAME_TICK: 'game.tick',\n\n // ---- CanvasRoom ------------------------------------------------------\n CANVAS_SHAPES: 'canvas.shapes',\n CANVAS_ADD: 'canvas.add',\n CANVAS_MOVE: 'canvas.move',\n CANVAS_RESIZE: 'canvas.resize',\n CANVAS_DELETE: 'canvas.delete',\n CANVAS_UPDATE: 'canvas.update',\n CANVAS_VIEWPORT: 'canvas.viewport',\n CANVAS_UNDO: 'canvas.undo',\n CANVAS_REDO: 'canvas.redo',\n\n // ---- CronRoom --------------------------------------------------------\n CRON_TASKS: 'cron.tasks',\n CRON_HISTORY: 'cron.history',\n CRON_TRIGGER: 'cron.trigger',\n CRON_PAUSE: 'cron.pause',\n CRON_RESUME: 'cron.resume',\n CRON_STATUS: 'cron.status',\n\n // ---- JobRoom ---------------------------------------------------------\n // Background-job queue with durable, alarm-driven execution. See\n // server/rooms/job-room.ts. Clients enqueue and subscribe to updates;\n // the room broadcasts JOB_UPDATE for every status transition.\n JOB_ENQUEUE: 'job.enqueue',\n JOB_CANCEL: 'job.cancel',\n JOB_RETRY: 'job.retry',\n JOB_UPDATE: 'job.update',\n\n // ---- PresenceRoom ----------------------------------------------------\n PRESENCE_SYNC: 'presence.sync',\n PRESENCE_JOIN: 'presence.join',\n PRESENCE_LEAVE: 'presence.leave',\n PRESENCE_UPDATE: 'presence.update',\n\n // ---- Gateway multiplexing --------------------------------------------\n GW_SCOPE_CONNECT: 'gateway.scope_connect',\n GW_SCOPE_DISCONNECT: 'gateway.scope_disconnect',\n GW_SCOPE_ERROR: 'gateway.scope_error',\n GW_TOKEN_REFRESH: 'gateway.token_refresh',\n GW_USER_UPDATE: 'gateway.user_update',\n} as const\n\n/**\n * Type of any message type constant — the union of every string literal\n * stored in `MSG`. Useful when declaring functions that accept \"any known\n * message type\" without enumerating all 54 strings by hand.\n */\nexport type MsgType = (typeof MSG)[keyof typeof MSG]\n\n// ---------------------------------------------------------------------------\n// Yjs binary protocol (NOT part of MSG — see header comment)\n// ---------------------------------------------------------------------------\n\n/** Outer envelope id for binary-framed yjs sync messages. Varuint-encoded. */\nexport const MSG_YJS_SYNC = 22\n/** Outer envelope id for binary-framed yjs awareness messages. Varuint-encoded. */\nexport const MSG_YJS_AWARENESS = 23\n\n// ---------------------------------------------------------------------------\n// Role names — not wire messages, just the string values the auth layer uses\n// as role identifiers.\n// ---------------------------------------------------------------------------\n\n/** Role assigned to unauthenticated WebSocket connections */\nexport const ROLE_ANONYMOUS = 'viewer'\n/** Default role for newly registered authenticated users */\nexport const ROLE_DEFAULT = 'member'\n/** Admin role */\nexport const ROLE_ADMIN = 'admin'\n","/**\n * Typed wire-protocol layer — discriminated unions, typed builders, and a\n * type-safe dispatcher for every `MSG.*` the SDK understands.\n *\n * Why this exists\n * ---------------\n *\n * The string `MSG.*` constants in `./constants.ts` are the authoritative\n * wire protocol, but using them directly is error-prone: a typo picks the\n * wrong message with the wrong payload shape and fails silently at\n * runtime. This module pairs every constant with its payload type, so\n * that:\n *\n * 1. Building a message with `clientBuild.gameInput(...)` is payload-\n * checked at the call site — the compiler refuses to ship a wrong\n * shape.\n *\n * 2. Parsing an inbound message via `dispatch(raw, handlers)` narrows the\n * payload type inside each handler automatically, replacing the\n * unsafe `switch (msg.type) { case MSG.X: (payload as any).foo }`\n * pattern.\n *\n * 3. Tightening `BaseRoom.sendTo` / `BaseRoom.broadcast` /\n * `HandlerContext.send` / `SubscriptionContext.send` to accept\n * `ServerMessage` turns the type layer into enforcement: any room\n * that ships a payload inconsistent with its declared arm fails to\n * compile. Without that, the discriminated union is documentation,\n * not contract.\n *\n * 4. Adding a new `MSG.*` is localized: one entry in the discriminated\n * union, one builder function, one handler key in every dispatcher\n * that cares. No grep-and-fix across the codebase.\n *\n * 5. Apps can extend the SDK protocol without forking: `dispatch<M>` is\n * generic over any `M extends ProtocolMessage`, and builders are\n * plain objects so apps compose via spread (`{ ...clientBuild,\n * myMessage: ... }`).\n *\n * Direction split\n * ---------------\n *\n * Some message types carry different payloads depending on who's sending.\n * `MSG.GAME_START`, for example, is `{}` when the client requests a start\n * but `{ state, tick }` when the server broadcasts the start event.\n * `MSG.CANVAS_ADD` is a flat shape dict on the way in and a `{ shape }`\n * wrapper on the way out. Modelling these with one union would force\n * handlers to juggle a union payload — clunky and error-prone. Instead we\n * split by direction:\n *\n * - `ClientMessage` — what the client sends to the server\n * - `ServerMessage` — what the server sends to the client\n * - `ProtocolMessage = ClientMessage | ServerMessage` (for code that\n * really doesn't care — avoid when possible)\n *\n * Each side gets its own builder (`clientBuild` / `serverBuild`) and each\n * side's dispatcher is parameterised with the union it expects.\n *\n * Payload strictness\n * ------------------\n *\n * Where payload shapes are stable + narrow (ids, flags), we type them\n * precisely. Where they're opaque or escape the protocol layer (record\n * data blobs, Yjs binary frames, game-engine state), we use `unknown` and\n * defer narrowing to the caller. This is intentional: over-typing opaque\n * payloads would require the protocol layer to import application types\n * and defeat the \"thin wire contract\" goal.\n */\n\nimport { MSG } from './constants'\n\n// =============================================================================\n// Envelope + helpers\n// =============================================================================\n\n/**\n * The outer shape of every wire message. `T` is the string discriminator\n * (e.g. `\"game.input\"`) — keeping it as a generic literal type lets the\n * discriminated-union narrowing in `dispatch()` pick the right payload.\n *\n * Callers extending the protocol should pass a string-literal type for\n * `T`, not the widened `string`. `BaseMessage<string, P>` collapses the\n * discriminated union and handler-map key inference falls back to a\n * single untyped `string` key, losing all narrowing.\n */\nexport interface BaseMessage<T extends string, P> {\n type: T\n payload: P\n}\n\n/** Matches when a payload is intentionally empty — `{}` on the wire. */\ntype EmptyPayload = Record<string, never>\n\n/**\n * Frozen empty payload reused by every \"no args\" builder. Frozen so a\n * runaway consumer mutating `.payload` can't corrupt the shared instance\n * that every other call site sees.\n */\nconst EMPTY: EmptyPayload = Object.freeze({}) as EmptyPayload\n\n// =============================================================================\n// Client → Server messages\n// =============================================================================\n\n/**\n * Every message the client can legitimately send. Extend in app code with\n * a string-literal union arm:\n *\n * type MyClientMessage = ClientMessage | BaseMessage<'myapp.foo', { x: number }>\n */\nexport type ClientMessage =\n // ---- Records / CRUD ---------------------------------------------------\n | BaseMessage<typeof MSG.SUBSCRIBE, { subscriptionId: string; query: unknown }>\n | BaseMessage<typeof MSG.UNSUBSCRIBE, { subscriptionId: string }>\n | BaseMessage<\n typeof MSG.PUT,\n { collection: string; recordId: string; data: Record<string, unknown>; requestId?: string }\n >\n | BaseMessage<\n typeof MSG.DELETE,\n { collection: string; recordId: string; requestId?: string }\n >\n // ---- Users ------------------------------------------------------------\n | BaseMessage<typeof MSG.USER_LIST, EmptyPayload>\n | BaseMessage<typeof MSG.SET_ROLE, { userId: string; role: string }>\n | BaseMessage<typeof MSG.USER_UPDATE, EmptyPayload>\n | BaseMessage<typeof MSG.LIST_SCHEMAS, EmptyPayload>\n // ---- Yjs --------------------------------------------------------------\n | BaseMessage<typeof MSG.YJS_JOIN, { collection: string; recordId: string; fieldName: string }>\n | BaseMessage<typeof MSG.YJS_LEAVE, { collection: string; recordId: string; fieldName: string }>\n // Binary yjs sync/awareness frames use numeric `MSG_YJS_SYNC` /\n // `MSG_YJS_AWARENESS` envelope ids from `./constants.ts` and ride the\n // binary WebSocket channel. They bypass this typed layer entirely.\n // ---- Game -------------------------------------------------------------\n | BaseMessage<typeof MSG.GAME_INPUT, { action: string; data: Record<string, unknown> }>\n | BaseMessage<typeof MSG.GAME_PLAYER_READY, EmptyPayload>\n | BaseMessage<typeof MSG.GAME_START, EmptyPayload>\n | BaseMessage<typeof MSG.GAME_END, EmptyPayload>\n // ---- Canvas -----------------------------------------------------------\n // `CANVAS_ADD` sends a flat shape dict as the payload (not `{ shape }`);\n // the server wraps it in `{ shape }` on its rebroadcast. Keep the types\n // aligned with the real wire or `clientBuild` lies. See\n // server/rooms/canvas-room.ts for the server side of this asymmetry.\n // `unknown` here (rather than `Record<string, unknown>`) so closed\n // concrete shape types pass assignability without index signatures.\n | BaseMessage<typeof MSG.CANVAS_ADD, unknown>\n | BaseMessage<typeof MSG.CANVAS_MOVE, { shapeId: string; x: number; y: number }>\n | BaseMessage<\n typeof MSG.CANVAS_RESIZE,\n { shapeId: string; width: number; height: number; x?: number; y?: number }\n >\n | BaseMessage<typeof MSG.CANVAS_DELETE, { shapeId: string }>\n | BaseMessage<\n typeof MSG.CANVAS_UPDATE,\n { shapeId: string; props: Record<string, unknown> }\n >\n // Flat payload in the client→server direction, matching `CANVAS_ADD`.\n | BaseMessage<typeof MSG.CANVAS_VIEWPORT, unknown>\n | BaseMessage<typeof MSG.CANVAS_UNDO, EmptyPayload>\n | BaseMessage<typeof MSG.CANVAS_REDO, EmptyPayload>\n // ---- Cron -------------------------------------------------------------\n | BaseMessage<typeof MSG.CRON_TRIGGER, { taskName: string }>\n | BaseMessage<typeof MSG.CRON_PAUSE, { taskName: string }>\n | BaseMessage<typeof MSG.CRON_RESUME, { taskName: string }>\n // ---- Jobs -------------------------------------------------------------\n // `JOB_ENQUEUE` uses requestId/JOB_UPDATE-ack so the caller learns the\n // newly-assigned jobId.\n | BaseMessage<\n typeof MSG.JOB_ENQUEUE,\n {\n requestId: string\n type: string\n payload?: unknown\n maxAttempts?: number\n }\n >\n | BaseMessage<typeof MSG.JOB_CANCEL, { jobId: string }>\n | BaseMessage<typeof MSG.JOB_RETRY, { jobId: string }>\n // ---- Presence ---------------------------------------------------------\n // Flat state object — the server merges incoming fields into the peer's\n // stored state; there's no `{ state }` wrapper in the client direction.\n | BaseMessage<typeof MSG.PRESENCE_UPDATE, Record<string, unknown>>\n // ---- Gateway ----------------------------------------------------------\n | BaseMessage<typeof MSG.GW_SCOPE_CONNECT, { scopeType: string; scopeId: string }>\n | BaseMessage<typeof MSG.GW_SCOPE_DISCONNECT, { scopeType: string; scopeId: string }>\n | BaseMessage<typeof MSG.GW_TOKEN_REFRESH, { token: string }>\n\n// =============================================================================\n// Server → Client messages\n// =============================================================================\n\n/**\n * Every message the server can send. Room and handler `send` / `broadcast`\n * signatures are tightened to this union so outbound payloads are\n * compile-checked against the wire contract. As with `ClientMessage`,\n * extend via a string-literal union arm in app code when adding new\n * server-side broadcasts.\n */\nexport type ServerMessage =\n // ---- Records / CRUD ---------------------------------------------------\n | BaseMessage<\n typeof MSG.QUERY_RESULT,\n { subscriptionId: string; records: unknown[] }\n >\n | BaseMessage<\n typeof MSG.RECORD_CHANGE,\n {\n collection: string\n record: unknown\n // Real wire values are `create`/`update`/`delete`, not the\n // underlying storage op name. See `server/handlers/subscriptions.ts`.\n changeType: 'create' | 'update' | 'delete'\n }\n >\n // `subscriptionId` is optional because generic transport errors (bad\n // envelope, missing connection) have no subscription context. Specific\n // query failures include the id so the client can correlate.\n | BaseMessage<typeof MSG.ERROR, { error: string; subscriptionId?: string }>\n // ACK is a mutation ack — it carries the correlation `requestId` from\n // the inbound PUT/DELETE plus a success flag. Server/handlers/records.ts\n // is the authoritative send site.\n | BaseMessage<\n typeof MSG.ACK,\n | { requestId: string; success: true; recordId?: string }\n | { requestId: string; success: false; error: string }\n >\n | BaseMessage<typeof MSG.RESUBSCRIBE, EmptyPayload>\n | BaseMessage<typeof MSG.LIST_SCHEMAS, { schemas: unknown }>\n // ---- Users ------------------------------------------------------------\n // `USER_INFO` carries an app-specific user object (column-shape varies\n // per deployment), so the wire type is opaque. Narrow at the consumer.\n | BaseMessage<typeof MSG.USER_INFO, unknown>\n | BaseMessage<typeof MSG.USER_LIST, { users: unknown[] }>\n // ---- Yjs (JSON frames; binary sync/awareness bypass this layer) -------\n | BaseMessage<\n typeof MSG.YJS_JOIN,\n { collection: string; recordId: string; fieldName: string; canWrite: boolean }\n >\n // ---- Game -------------------------------------------------------------\n | BaseMessage<\n typeof MSG.GAME_STATE,\n { state: unknown; tick: number; players: unknown[]; running: boolean }\n >\n | BaseMessage<typeof MSG.GAME_TICK, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_START, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_END, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_PLAYER_JOIN, { player: unknown }>\n | BaseMessage<typeof MSG.GAME_PLAYER_LEAVE, { userId: string }>\n | BaseMessage<typeof MSG.GAME_PLAYER_READY, { userId: string }>\n // ---- Canvas -----------------------------------------------------------\n // `CANVAS_SHAPES` carries both the shape list and the viewports snapshot\n // so new connections can restore a multi-user view in one message. See\n // server/rooms/canvas-room.ts:onConnect.\n | BaseMessage<\n typeof MSG.CANVAS_SHAPES,\n { shapes: unknown[]; viewports: unknown[] }\n >\n | BaseMessage<typeof MSG.CANVAS_ADD, { shape: unknown }>\n | BaseMessage<typeof MSG.CANVAS_MOVE, { shapeId: string; x: number; y: number }>\n | BaseMessage<\n typeof MSG.CANVAS_RESIZE,\n { shapeId: string; width: number; height: number; x?: number; y?: number }\n >\n | BaseMessage<typeof MSG.CANVAS_DELETE, { shapeId: string }>\n | BaseMessage<\n typeof MSG.CANVAS_UPDATE,\n { shapeId: string; props: Record<string, unknown> }\n >\n | BaseMessage<\n typeof MSG.CANVAS_VIEWPORT,\n { viewport: unknown } | { userId: string; removed: true }\n >\n // ---- Cron -------------------------------------------------------------\n // `CRON_STATUS` server broadcasts carry both tasks and recent history;\n // see server/rooms/cron-room.ts.\n | BaseMessage<typeof MSG.CRON_TASKS, { tasks: unknown }>\n | BaseMessage<typeof MSG.CRON_HISTORY, { history: unknown }>\n | BaseMessage<typeof MSG.CRON_STATUS, { tasks: unknown; recentHistory: unknown }>\n // ---- Jobs -------------------------------------------------------------\n // `JOB_UPDATE` is the single push channel — same payload shape carries\n // initial-snapshot, enqueue, progress, success, failure, cancel, and\n // retry events. `kind` discriminates client-side. See useJobs.\n | BaseMessage<\n typeof MSG.JOB_UPDATE,\n {\n kind: 'snapshot' | 'enqueued' | 'progress' | 'succeeded' | 'failed' | 'canceled' | 'retried'\n job?: unknown\n jobs?: unknown[]\n /** Echoes the enqueue requestId when the update is the enqueue ack. */\n requestId?: string\n }\n >\n // ---- Presence ---------------------------------------------------------\n | BaseMessage<typeof MSG.PRESENCE_SYNC, { peers: unknown[] }>\n | BaseMessage<typeof MSG.PRESENCE_JOIN, { peer: unknown }>\n | BaseMessage<typeof MSG.PRESENCE_LEAVE, { userId: string }>\n | BaseMessage<\n typeof MSG.PRESENCE_UPDATE,\n { userId: string; state: Record<string, unknown> }\n >\n // ---- Gateway ----------------------------------------------------------\n | BaseMessage<\n typeof MSG.GW_SCOPE_ERROR,\n { scopeType: string; scopeId: string; error: string }\n >\n | BaseMessage<typeof MSG.GW_USER_UPDATE, unknown>\n\n/**\n * Any wire message, regardless of direction. Use this only when the code\n * path genuinely doesn't care — otherwise pick `ClientMessage` or\n * `ServerMessage` so the handler's payload type is narrower.\n */\nexport type ProtocolMessage = ClientMessage | ServerMessage\n\n// =============================================================================\n// Typed builders\n// =============================================================================\n//\n// Each builder returns a `{ type, payload }` object typed as a specific arm\n// of `ClientMessage` / `ServerMessage`. Call sites that hand the result to\n// `JSON.stringify` ship exactly what the wire protocol expects.\n//\n// `as const` on every return preserves the literal string `type` value\n// (e.g. `\"game.input\"`), which is what the discriminated-union narrowing\n// in `dispatch` keys on. Without it TS widens to `string` and the handler\n// map collapses to a single untyped key.\n// =============================================================================\n\n/** Factories for every client → server message. */\nexport const clientBuild = {\n // Records / CRUD\n subscribe: (subscriptionId: string, query: unknown) =>\n ({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }) as const,\n unsubscribe: (subscriptionId: string) =>\n ({ type: MSG.UNSUBSCRIBE, payload: { subscriptionId } }) as const,\n put: (\n collection: string,\n recordId: string,\n data: Record<string, unknown>,\n requestId?: string,\n ) =>\n ({\n type: MSG.PUT,\n payload: { collection, recordId, data, requestId },\n }) as const,\n remove: (collection: string, recordId: string, requestId?: string) =>\n ({ type: MSG.DELETE, payload: { collection, recordId, requestId } }) as const,\n // Users\n userList: () => ({ type: MSG.USER_LIST, payload: EMPTY }) as const,\n setRole: (userId: string, role: string) =>\n ({ type: MSG.SET_ROLE, payload: { userId, role } }) as const,\n userUpdate: () => ({ type: MSG.USER_UPDATE, payload: EMPTY }) as const,\n listSchemas: () => ({ type: MSG.LIST_SCHEMAS, payload: EMPTY }) as const,\n // Yjs\n yjsJoin: (collection: string, recordId: string, fieldName: string) =>\n ({ type: MSG.YJS_JOIN, payload: { collection, recordId, fieldName } }) as const,\n yjsLeave: (collection: string, recordId: string, fieldName: string) =>\n ({ type: MSG.YJS_LEAVE, payload: { collection, recordId, fieldName } }) as const,\n // Game\n gameInput: (action: string, data: Record<string, unknown> = {}) =>\n ({ type: MSG.GAME_INPUT, payload: { action, data } }) as const,\n gamePlayerReady: () => ({ type: MSG.GAME_PLAYER_READY, payload: EMPTY }) as const,\n gameStart: () => ({ type: MSG.GAME_START, payload: EMPTY }) as const,\n gameEnd: () => ({ type: MSG.GAME_END, payload: EMPTY }) as const,\n // Canvas — `CANVAS_ADD` / `CANVAS_VIEWPORT` payloads are flat (the shape\n // or viewport object is the whole payload).\n canvasAdd: (shape: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_ADD, payload: shape }) as const,\n canvasMove: (shapeId: string, x: number, y: number) =>\n ({ type: MSG.CANVAS_MOVE, payload: { shapeId, x, y } }) as const,\n canvasResize: (\n shapeId: string,\n width: number,\n height: number,\n x?: number,\n y?: number,\n ) =>\n ({ type: MSG.CANVAS_RESIZE, payload: { shapeId, width, height, x, y } }) as const,\n canvasDelete: (shapeId: string) =>\n ({ type: MSG.CANVAS_DELETE, payload: { shapeId } }) as const,\n canvasUpdate: (shapeId: string, props: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_UPDATE, payload: { shapeId, props } }) as const,\n canvasViewport: (viewport: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_VIEWPORT, payload: viewport }) as const,\n canvasUndo: () => ({ type: MSG.CANVAS_UNDO, payload: EMPTY }) as const,\n canvasRedo: () => ({ type: MSG.CANVAS_REDO, payload: EMPTY }) as const,\n // Cron\n cronTrigger: (taskName: string) =>\n ({ type: MSG.CRON_TRIGGER, payload: { taskName } }) as const,\n cronPause: (taskName: string) =>\n ({ type: MSG.CRON_PAUSE, payload: { taskName } }) as const,\n cronResume: (taskName: string) =>\n ({ type: MSG.CRON_RESUME, payload: { taskName } }) as const,\n // Jobs\n jobEnqueue: (\n requestId: string,\n type: string,\n payload?: unknown,\n maxAttempts?: number,\n ) =>\n ({\n type: MSG.JOB_ENQUEUE,\n payload: { requestId, type, payload, maxAttempts },\n }) as const,\n jobCancel: (jobId: string) =>\n ({ type: MSG.JOB_CANCEL, payload: { jobId } }) as const,\n jobRetry: (jobId: string) =>\n ({ type: MSG.JOB_RETRY, payload: { jobId } }) as const,\n // Presence\n presenceUpdate: (state: Record<string, unknown>) =>\n ({ type: MSG.PRESENCE_UPDATE, payload: state }) as const,\n // Gateway\n gwScopeConnect: (scopeType: string, scopeId: string) =>\n ({ type: MSG.GW_SCOPE_CONNECT, payload: { scopeType, scopeId } }) as const,\n gwScopeDisconnect: (scopeType: string, scopeId: string) =>\n ({ type: MSG.GW_SCOPE_DISCONNECT, payload: { scopeType, scopeId } }) as const,\n gwTokenRefresh: (token: string) =>\n ({ type: MSG.GW_TOKEN_REFRESH, payload: { token } }) as const,\n}\n\n/** Factories for every server → client message. Used by room DOs and\n * handler modules so server broadcasts are payload-checked too. Opaque\n * slots (`record`, `shape`, `peer`, etc.) take `unknown` so concrete\n * domain types — `RecordResult`, `CanvasShape`, `MediaPeer` — can be\n * passed without casts. */\nexport const serverBuild = {\n // Records / CRUD\n queryResult: (subscriptionId: string, records: unknown[]) =>\n ({ type: MSG.QUERY_RESULT, payload: { subscriptionId, records } }) as const,\n recordChange: (\n collection: string,\n record: unknown,\n changeType: 'create' | 'update' | 'delete',\n ) =>\n ({ type: MSG.RECORD_CHANGE, payload: { collection, record, changeType } }) as const,\n error: (error: string, subscriptionId?: string) =>\n ({ type: MSG.ERROR, payload: { error, subscriptionId } }) as const,\n ackSuccess: (requestId: string, recordId?: string) =>\n ({\n type: MSG.ACK,\n payload: { requestId, success: true as const, recordId },\n }) as const,\n ackFailure: (requestId: string, error: string) =>\n ({\n type: MSG.ACK,\n payload: { requestId, success: false as const, error },\n }) as const,\n resubscribe: () => ({ type: MSG.RESUBSCRIBE, payload: EMPTY }) as const,\n schemas: (schemas: unknown) =>\n ({ type: MSG.LIST_SCHEMAS, payload: { schemas } }) as const,\n // Users\n userInfo: (user: unknown) =>\n ({ type: MSG.USER_INFO, payload: user }) as const,\n userList: (users: unknown[]) =>\n ({ type: MSG.USER_LIST, payload: { users } }) as const,\n // Yjs\n yjsJoin: (collection: string, recordId: string, fieldName: string, canWrite: boolean) =>\n ({\n type: MSG.YJS_JOIN,\n payload: { collection, recordId, fieldName, canWrite },\n }) as const,\n // Game\n gameState: (state: unknown, tick: number, players: unknown[], running: boolean) =>\n ({ type: MSG.GAME_STATE, payload: { state, tick, players, running } }) as const,\n gameTick: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_TICK, payload: { state, tick } }) as const,\n gameStart: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_START, payload: { state, tick } }) as const,\n gameEnd: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_END, payload: { state, tick } }) as const,\n gamePlayerJoin: (player: unknown) =>\n ({ type: MSG.GAME_PLAYER_JOIN, payload: { player } }) as const,\n gamePlayerLeave: (userId: string) =>\n ({ type: MSG.GAME_PLAYER_LEAVE, payload: { userId } }) as const,\n gamePlayerReady: (userId: string) =>\n ({ type: MSG.GAME_PLAYER_READY, payload: { userId } }) as const,\n // Canvas\n canvasShapes: (shapes: unknown[], viewports: unknown[]) =>\n ({ type: MSG.CANVAS_SHAPES, payload: { shapes, viewports } }) as const,\n canvasAdd: (shape: unknown) =>\n ({ type: MSG.CANVAS_ADD, payload: { shape } }) as const,\n canvasMove: (shapeId: string, x: number, y: number) =>\n ({ type: MSG.CANVAS_MOVE, payload: { shapeId, x, y } }) as const,\n canvasResize: (\n shapeId: string,\n width: number,\n height: number,\n x?: number,\n y?: number,\n ) =>\n ({ type: MSG.CANVAS_RESIZE, payload: { shapeId, width, height, x, y } }) as const,\n canvasDelete: (shapeId: string) =>\n ({ type: MSG.CANVAS_DELETE, payload: { shapeId } }) as const,\n canvasUpdate: (shapeId: string, props: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_UPDATE, payload: { shapeId, props } }) as const,\n canvasViewport: (viewport: unknown) =>\n ({ type: MSG.CANVAS_VIEWPORT, payload: { viewport } }) as const,\n canvasViewportRemoved: (userId: string) =>\n ({\n type: MSG.CANVAS_VIEWPORT,\n payload: { userId, removed: true as const },\n }) as const,\n // Cron\n cronTasks: (tasks: unknown) =>\n ({ type: MSG.CRON_TASKS, payload: { tasks } }) as const,\n cronHistory: (history: unknown) =>\n ({ type: MSG.CRON_HISTORY, payload: { history } }) as const,\n cronStatus: (tasks: unknown, recentHistory: unknown) =>\n ({ type: MSG.CRON_STATUS, payload: { tasks, recentHistory } }) as const,\n // Jobs\n jobSnapshot: (jobs: unknown[]) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'snapshot' as const, jobs } }) as const,\n jobEnqueued: (job: unknown, requestId?: string) =>\n ({\n type: MSG.JOB_UPDATE,\n payload: { kind: 'enqueued' as const, job, requestId },\n }) as const,\n jobProgress: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'progress' as const, job } }) as const,\n jobSucceeded: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'succeeded' as const, job } }) as const,\n jobFailed: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'failed' as const, job } }) as const,\n jobCanceled: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'canceled' as const, job } }) as const,\n jobRetried: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'retried' as const, job } }) as const,\n // Presence\n presenceSync: (peers: unknown[]) =>\n ({ type: MSG.PRESENCE_SYNC, payload: { peers } }) as const,\n presenceJoin: (peer: unknown) =>\n ({ type: MSG.PRESENCE_JOIN, payload: { peer } }) as const,\n presenceLeave: (userId: string) =>\n ({ type: MSG.PRESENCE_LEAVE, payload: { userId } }) as const,\n presenceUpdate: (userId: string, state: Record<string, unknown>) =>\n ({ type: MSG.PRESENCE_UPDATE, payload: { userId, state } }) as const,\n // Gateway\n gwScopeError: (scopeType: string, scopeId: string, error: string) =>\n ({\n type: MSG.GW_SCOPE_ERROR,\n payload: { scopeType, scopeId, error },\n }) as const,\n gwUserUpdate: (user: unknown) =>\n ({ type: MSG.GW_USER_UPDATE, payload: user }) as const,\n}\n\n// =============================================================================\n// Typed dispatch\n// =============================================================================\n//\n// `dispatch` parses a raw WebSocket frame (or takes an already-parsed\n// object) and routes it to the right handler. Handlers are indexed by the\n// message's string `type`, and TS narrows the `payload` argument to the\n// correct arm of the message union automatically thanks to the\n// discriminated-union lookup.\n//\n// The generic `M` defaults to `ProtocolMessage` so ad-hoc uses get the\n// full SDK vocabulary for free, but apps can pass a narrower (or extended)\n// union:\n//\n// dispatch<ServerMessage>(raw, {\n// [MSG.GAME_STATE]: (p) => { /* p is narrowed */ },\n// [MSG.GAME_TICK]: (p) => { /* p is narrowed */ },\n// })\n//\n// // With an app-defined message (use a STRING LITERAL for the type\n// // parameter — `string` widens the union and kills narrowing):\n// type MyMsg =\n// | ServerMessage\n// | BaseMessage<'myapp.boss_spawn', { hp: number }>\n// dispatch<MyMsg>(raw, {\n// 'myapp.boss_spawn': (p) => { console.log(p.hp) },\n// })\n//\n// =============================================================================\n\n/**\n * Handler map keyed by a message's string `type`. Every key maps to the\n * payload type of the matching arm in `M`, so handlers get automatic\n * payload narrowing with no runtime checks.\n *\n * Narrowing requires each `M` arm to use a string-literal `T`; widening\n * `M` to `BaseMessage<string, unknown>` collapses all keys to a single\n * untyped `string` and the map becomes a plain `Record<string, (p: unknown)\n * => void>`.\n */\nexport type MessageHandlers<M extends BaseMessage<string, unknown> = ProtocolMessage> = {\n [K in M as K['type']]?: (payload: K['payload']) => void\n}\n\n/**\n * Parse and route an incoming wire message. Accepts either the raw JSON\n * string (directly from `ws.onmessage`'s `event.data`) or an already-\n * parsed object. Returns `true` if a handler ran, `false` otherwise\n * (unrecognised type, parse failure, or malformed envelope).\n *\n * Defaults `M` to `ProtocolMessage` so callers who don't care about\n * direction can just do `dispatch(raw, handlers)`; narrow with\n * `dispatch<ClientMessage>` / `dispatch<ServerMessage>` to restrict which\n * arms the handler map is allowed to cover.\n */\nexport function dispatch<M extends BaseMessage<string, unknown> = ProtocolMessage>(\n raw: unknown,\n handlers: MessageHandlers<M>,\n): boolean {\n let msg: { type?: unknown; payload?: unknown }\n if (typeof raw === 'string') {\n try {\n msg = JSON.parse(raw) as { type?: unknown; payload?: unknown }\n } catch {\n return false\n }\n } else if (raw && typeof raw === 'object') {\n msg = raw as { type?: unknown; payload?: unknown }\n } else {\n return false\n }\n if (typeof msg.type !== 'string') return false\n const handler = (handlers as Record<string, ((payload: unknown) => void) | undefined>)[\n msg.type\n ]\n if (!handler) return false\n handler(msg.payload)\n return true\n}\n\n/**\n * Serialise a typed-built message for `ws.send`. A tiny wrapper around\n * `JSON.stringify` kept around so call sites read as\n * `ws.send(encode(clientBuild.gameInput(...)))` rather than paying\n * attention to stringify arguments.\n */\nexport function encode<M extends BaseMessage<string, unknown>>(message: M): string {\n return JSON.stringify(message)\n}\n","/**\n * DeepSpace Auth Provider.\n *\n * Wraps the app with the Better Auth session hook so children can read\n * the current user via `useAuth` / `useAuthUser`. Sessions ride a\n * same-origin cookie so there's no satellite-domain configuration.\n */\n\nimport React, { useEffect, useRef } from 'react'\nimport { useSession } from './client'\n\ninterface DeepSpaceAuthProviderProps {\n children: React.ReactNode\n}\n\n/** Logs auth state transitions once. */\nfunction AuthLogger() {\n const session = useSession()\n const isSignedIn = !!session.data?.user\n const prevSignedIn = useRef<boolean | null>(null)\n\n useEffect(() => {\n if (session.isPending) return\n if (prevSignedIn.current !== isSignedIn) {\n if (isSignedIn) {\n console.log(`[ds:auth] signed in as ${session.data?.user?.name ?? session.data?.user?.id}`)\n } else if (prevSignedIn.current !== null) {\n console.log('[ds:auth] signed out')\n }\n prevSignedIn.current = isSignedIn\n }\n }, [isSignedIn, session.isPending, session.data?.user?.name, session.data?.user?.id])\n\n return null\n}\n\n/**\n * Auth provider for DeepSpace apps.\n *\n * Better Auth uses cookie-based sessions, so there's no provider\n * state to manage. This component exists for API compatibility\n * and as a place to add auth-related context in the future.\n */\nexport function DeepSpaceAuthProvider({ children }: DeepSpaceAuthProviderProps) {\n return (\n <>\n <AuthLogger />\n {children}\n </>\n )\n}\n","/**\n * Better Auth Client for DeepSpace\n *\n * Creates a typed Better Auth client that communicates via the app's\n * own /api/auth/* proxy (same-origin cookies, no CORS issues).\n * The app's worker proxies these requests to the auth-worker.\n */\n\nimport { createAuthClient } from 'better-auth/react'\nimport { organizationClient, twoFactorClient } from 'better-auth/client/plugins'\nimport { clearAuthToken } from './token'\n\n/**\n * Auth base URL — always same-origin.\n * The app's worker.ts proxies /api/auth/* to the auth-worker.\n */\nfunction getBaseURL(): string {\n if (typeof window !== 'undefined') {\n return window.location.origin\n }\n return ''\n}\n\nexport const authClient = createAuthClient({\n baseURL: getBaseURL(),\n plugins: [organizationClient(), twoFactorClient()],\n})\n\nexport const {\n useSession,\n signIn,\n useActiveOrganization,\n useListOrganizations,\n} = authClient\n\nexport async function signOut(\n ...args: Parameters<typeof authClient.signOut>\n): Promise<Awaited<ReturnType<typeof authClient.signOut>>> {\n try {\n return await authClient.signOut(...args)\n } finally {\n clearAuthToken()\n }\n}\n","/**\n * Short-lived JWT provider for WebSocket and API authentication.\n *\n * Fetches an ES256 token from the same-origin `/api/auth/token` endpoint\n * (routed through to the auth-worker), caches it in module scope, and\n * refreshes ~30s before expiry by reading `exp` out of the payload.\n */\n\n// Token is fetched via same-origin /api/auth/token — the app's worker (or Vite proxy)\n// routes this to the auth-worker. No cross-origin requests needed.\n\nlet cachedToken: string | null = null\nlet tokenExpiry = 0\n\nfunction extractExpiry(token: string): number {\n try {\n const parts = token.split('.')\n if (parts.length < 2) return 0\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n return (payload.exp ?? 0) * 1000\n } catch {\n return 0\n }\n}\n\n/**\n * Get a short-lived JWT for WebSocket and API calls.\n *\n * The token is obtained from the auth-worker's /api/auth/token endpoint,\n * authenticated via the Better Auth session cookie. Tokens are cached\n * and refreshed 30s before expiry.\n */\nexport async function getAuthToken(): Promise<string | null> {\n if (typeof window === 'undefined') return null\n\n // Return cached token if still valid (30s buffer)\n if (cachedToken && Date.now() < tokenExpiry - 30_000) {\n return cachedToken\n }\n\n try {\n const res = await fetch('/api/auth/token', {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n })\n\n if (!res.ok) {\n cachedToken = null\n tokenExpiry = 0\n return null\n }\n\n const data = (await res.json()) as { token?: string | null }\n if (!data.token) {\n cachedToken = null\n tokenExpiry = 0\n return null\n }\n\n cachedToken = data.token\n tokenExpiry = extractExpiry(data.token)\n return data.token\n } catch {\n return null\n }\n}\n\n/** Clear cached token (call on sign-out). */\nexport function clearAuthToken(): void {\n cachedToken = null\n tokenExpiry = 0\n}\n","/**\n * Auth hooks for the DeepSpace SDK.\n *\n * Thin wrappers over Better Auth's `useSession` that expose the loaded /\n * signed-in / userId / user-profile shape the storage layer reads.\n */\n\nimport { useSession } from './client'\n\n/**\n * Returns auth state compatible with what storage/context.tsx expects.\n */\nexport function useAuth() {\n const session = useSession()\n\n const isSignedIn = !!session.data?.user\n const userId = session.data?.user?.id ?? null\n\n return {\n isLoaded: !session.isPending,\n isSignedIn,\n userId,\n sessionId: session.data?.session?.id ?? null,\n }\n}\n\n/**\n * Returns user data compatible with what storage/context.tsx expects.\n */\nexport function useAuthUser() {\n const session = useSession()\n const user = session.data?.user ?? null\n\n return {\n isLoaded: !session.isPending,\n isSignedIn: !!user,\n user: user\n ? {\n id: user.id,\n fullName: user.name ?? null,\n firstName: user.name?.split(' ')[0] ?? null,\n lastName: user.name?.split(' ').slice(1).join(' ') || null,\n emailAddresses: user.email\n ? [{ emailAddress: user.email }]\n : [],\n imageUrl: user.image ?? null,\n primaryEmailAddress: user.email\n ? { emailAddress: user.email }\n : null,\n }\n : null,\n }\n}\n","/**\n * Full-page frosted-glass auth overlay for deployed DeepSpace apps.\n *\n * Primary: OAuth (GitHub, Google).\n * Secondary: Email/password sign-in (for test accounts created via CLI/API).\n * Styled with shadcn semantic tokens so it themes along with the host app.\n */\n\nimport React, { useState } from 'react'\nimport { useAuth } from './hooks'\nimport { signIn } from './client'\n\ninterface AuthOverlayProps {\n /** Called when the user clicks the close button. If omitted, overlay is not closeable. */\n onClose?: () => void\n /** Which OAuth providers to show. Defaults to both. */\n providers?: Array<'github' | 'google'>\n}\n\nexport function AuthOverlay({\n onClose,\n providers = ['github', 'google'],\n}: AuthOverlayProps = {}): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const [showEmailForm, setShowEmailForm] = useState(false)\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [error, setError] = useState('')\n const [loading, setLoading] = useState(false)\n\n if (!isLoaded || isSignedIn) return null\n\n const handleSocial = (provider: 'github' | 'google') => {\n setLoading(true)\n window.location.href = `/api/auth/social-redirect?provider=${provider}`\n }\n\n const handleEmailSignIn = async (e: React.FormEvent) => {\n e.preventDefault()\n setError('')\n setLoading(true)\n\n try {\n const result = await signIn.email({ email, password })\n if (result.error) {\n setError(result.error.message ?? 'Sign in failed')\n setLoading(false)\n }\n } catch (err: any) {\n setError(err.message ?? 'Something went wrong')\n setLoading(false)\n }\n }\n\n return (\n <>\n <style>{`\n @keyframes ds-auth-overlay-in {\n from { opacity: 0 }\n to { opacity: 1 }\n }\n @keyframes ds-auth-card-in {\n from { opacity: 0; transform: translateY(16px) scale(0.97) }\n to { opacity: 1; transform: translateY(0) scale(1) }\n }\n `}</style>\n\n <div\n data-testid=\"auth-overlay\"\n onClick={onClose ? (e) => { if (e.target === e.currentTarget) onClose() } : undefined}\n className=\"fixed inset-0 z-[99999] flex items-center justify-center bg-black/55 backdrop-blur-2xl\"\n style={{\n opacity: 0,\n animation: 'ds-auth-overlay-in 0.4s ease forwards',\n }}\n >\n <div\n className=\"relative mx-6 w-full max-w-[380px] rounded-2xl border border-border bg-card p-8 text-center shadow-card-hover sm:p-9\"\n style={{\n opacity: 0,\n animation: 'ds-auth-card-in 0.45s cubic-bezier(0.25, 1, 0.5, 1) 0.08s forwards',\n }}\n >\n {onClose && (\n <button\n data-testid=\"auth-overlay-close\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"absolute right-3 top-3 inline-flex h-7 w-7 items-center justify-center rounded-full bg-secondary text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n ✕\n </button>\n )}\n\n <h2 className=\"mb-2 text-[22px] font-bold leading-snug text-foreground\">\n Sign in to DeepSpace\n </h2>\n\n <p className=\"mb-6 text-sm leading-snug text-muted-foreground\">\n Sync your data across devices\n </p>\n\n {/* OAuth buttons */}\n <div className=\"flex flex-col gap-2\">\n {providers.includes('github') && (\n <OAuthButton onClick={() => handleSocial('github')} disabled={loading} icon={<GitHubIcon />}>\n Continue with GitHub\n </OAuthButton>\n )}\n {providers.includes('google') && (\n <OAuthButton onClick={() => handleSocial('google')} disabled={loading} icon={<GoogleIcon />}>\n Continue with Google\n </OAuthButton>\n )}\n </div>\n\n <Divider />\n\n {!showEmailForm ? (\n <button\n type=\"button\"\n data-testid=\"auth-email-toggle\"\n onClick={() => setShowEmailForm(true)}\n className=\"flex w-full items-center justify-center gap-2.5 rounded-lg border border-border bg-transparent px-4 py-2.5 text-sm font-semibold text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n Sign in with email\n </button>\n ) : (\n <form onSubmit={handleEmailSignIn} className=\"text-left\">\n <input\n type=\"email\"\n placeholder=\"Email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n required\n autoComplete=\"email\"\n className=\"mb-3 block w-full rounded-lg border border-border bg-secondary px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none\"\n />\n <input\n type=\"password\"\n placeholder=\"Password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n required\n minLength={8}\n autoComplete=\"current-password\"\n className={`block w-full rounded-lg border border-border bg-secondary px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none ${error ? 'mb-3' : 'mb-5'}`}\n />\n\n {error && (\n <div className=\"mb-4 text-center text-sm text-destructive\">{error}</div>\n )}\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"block w-full rounded-lg bg-primary px-5 py-3 text-[15px] font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:cursor-wait disabled:opacity-70\"\n >\n {loading ? 'Please wait…' : 'Sign in'}\n </button>\n </form>\n )}\n\n <div className=\"mt-5 flex items-center justify-center gap-1.5 text-[11px] text-muted-foreground\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" opacity=\"0.5\" aria-hidden>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n </svg>\n Powered by DeepSpace\n </div>\n </div>\n </div>\n </>\n )\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Local components\n// ────────────────────────────────────────────────────────────────────\n\nfunction OAuthButton({\n onClick,\n disabled,\n icon,\n children,\n}: {\n onClick: () => void\n disabled: boolean\n icon: React.ReactNode\n children: React.ReactNode\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className=\"flex w-full items-center justify-center gap-2.5 rounded-lg border border-border bg-secondary px-4 py-2.5 text-sm font-semibold text-foreground transition-colors hover:bg-accent disabled:cursor-wait disabled:opacity-60\"\n >\n {icon}\n {children}\n </button>\n )\n}\n\nfunction Divider() {\n return (\n <div className=\"my-5 flex items-center gap-3 text-xs text-muted-foreground\">\n <div className=\"h-px flex-1 bg-border\" />\n or\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction GitHubIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden>\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0016 8c0-4.42-3.58-8-8-8z\" />\n </svg>\n )\n}\n\n// Google logo uses Google's brand colors — these are required by Google's\n// brand guidelines and intentionally not theme-reactive.\nfunction GoogleIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden>\n <path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" />\n <path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n","/** Conditional renderers, the route gate, and a display-name hook. */\n\nimport { useEffect, useRef, type ReactNode } from 'react'\nimport { useAuth, useAuthUser } from './hooks'\nimport { AuthOverlay } from './AuthOverlay'\n\n/**\n * Renders children only when the user is signed in.\n */\nexport function SignedIn({ children }: { children: ReactNode }): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n if (!isLoaded || !isSignedIn) return null\n return <>{children}</>\n}\n\n/**\n * Renders children only when the user is signed out.\n */\nexport function SignedOut({ children }: { children: ReactNode }): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n if (!isLoaded || isSignedIn) return null\n return <>{children}</>\n}\n\nexport interface AuthGateProps {\n /** Content to show when signed in */\n children: ReactNode\n /**\n * UI for first-visit signed-out users. If omitted, the SDK's sign-in\n * overlay is shown non-closeably. Not used on mid-session sign-out —\n * see `redirectOnSignOut`.\n */\n fallback?: ReactNode\n /** Where to send the user when they sign out from inside the gate. Defaults to '/'. */\n redirectOnSignOut?: string\n}\n\n/**\n * Gates a subtree behind sign-in. Children mount only when signed in (no flash).\n * If the user signs out from inside the gate, redirects out instead of trapping\n * them on the overlay.\n */\nexport function AuthGate({\n children,\n fallback,\n redirectOnSignOut = '/',\n}: AuthGateProps): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const wasSignedIn = useRef(false)\n if (isSignedIn) wasSignedIn.current = true\n\n if (!isLoaded) return null\n if (isSignedIn) return <>{children}</>\n if (wasSignedIn.current) return <RedirectAway to={redirectOnSignOut} />\n if (fallback) return <>{fallback}</>\n return <AuthOverlay />\n}\n\n// Full page load (not a router navigation) so the SDK stays router-agnostic\n// and the signed-out teardown is clean.\nfunction RedirectAway({ to }: { to: string }): null {\n useEffect(() => {\n if (typeof window !== 'undefined') window.location.replace(to)\n }, [to])\n return null\n}\n\n/**\n * Returns the current user's display name.\n *\n * Resolution order: fullName -> firstName -> email prefix -> 'User'.\n * Returns null when no user is signed in.\n */\nexport function useDisplayName(): string | null {\n const { user } = useAuthUser()\n if (!user) return null\n return (\n user.fullName ||\n user.firstName ||\n user.primaryEmailAddress?.emailAddress?.split('@')[0] ||\n 'User'\n )\n}\n","/**\n * Floating dismissible guest banner for DeepSpace apps.\n *\n * Shows a non-intrusive prompt for signed-out users to sign in or sign up.\n * Dismiss state is persisted in sessionStorage so it stays hidden for the\n * duration of the browsing session.\n *\n * Styled with shadcn semantic tokens (bg-card, text-foreground, etc.) so it\n * themes along with the host app.\n */\n\nimport React, { useEffect, useState } from 'react'\nimport { useAuth } from './hooks'\n\nconst DEFAULT_STORAGE_KEY = 'deepspace-guest-banner-dismissed'\nconst DEFAULT_MESSAGE = \"You're browsing as a guest. Sign in to unlock all features.\"\n\nexport interface GuestBannerProps {\n message?: string\n storageKey?: string\n /** Called when the user clicks \"Sign in\". */\n onSignIn?: () => void\n}\n\nexport function GuestBanner({\n message = DEFAULT_MESSAGE,\n storageKey = DEFAULT_STORAGE_KEY,\n onSignIn,\n}: GuestBannerProps): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const [mounted, setMounted] = useState(false)\n\n const [dismissed, setDismissed] = useState(() => {\n if (typeof window === 'undefined') return false\n try {\n return sessionStorage.getItem(storageKey) === '1'\n } catch {\n return false\n }\n })\n\n useEffect(() => {\n if (isLoaded && !isSignedIn && !dismissed) {\n requestAnimationFrame(() => setMounted(true))\n }\n }, [dismissed, isLoaded, isSignedIn])\n\n if (!isLoaded || isSignedIn || dismissed) return null\n\n const handleDismiss = (): void => {\n try {\n sessionStorage.setItem(storageKey, '1')\n } catch {\n // best effort\n }\n setDismissed(true)\n }\n\n return (\n <>\n <style>{`\n @keyframes ds-guest-banner-in {\n from { opacity: 0; transform: translateY(-12px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}</style>\n <div\n role=\"banner\"\n data-testid=\"guest-banner\"\n className=\"fixed top-3 inset-x-3 z-[99998] mx-auto flex max-w-[700px] items-center gap-3.5 rounded-2xl border border-border bg-card/95 px-4 py-3 text-sm leading-snug text-foreground shadow-card-hover backdrop-blur-xl sm:gap-4\"\n style={{\n opacity: mounted ? 1 : 0,\n animation: mounted\n ? 'ds-guest-banner-in 0.35s cubic-bezier(0.25, 1, 0.5, 1) forwards'\n : 'none',\n pointerEvents: mounted ? 'auto' : 'none',\n }}\n >\n <span\n aria-hidden\n className=\"hidden h-2 w-2 shrink-0 rounded-full bg-primary shadow-[0_0_8px_var(--color-primary)] sm:inline-block\"\n />\n\n <span className=\"min-w-0 flex-1 font-medium text-muted-foreground\">\n {message}\n </span>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <button\n type=\"button\"\n data-testid=\"guest-banner-signin\"\n onClick={onSignIn}\n className=\"inline-flex items-center justify-center whitespace-nowrap rounded-lg bg-primary px-4 py-1.5 text-xs font-semibold text-primary-foreground transition-opacity hover:opacity-90 sm:text-sm\"\n >\n Sign in\n </button>\n\n <button\n type=\"button\"\n data-testid=\"guest-banner-dismiss\"\n onClick={handleDismiss}\n aria-label=\"Dismiss banner\"\n className=\"flex shrink-0 items-center justify-center rounded-md p-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n </div>\n </>\n )\n}\n","/**\n * RecordProvider Context\n *\n * Provides WebSocket connection and state management for RecordRoom.\n *\n * Multi-scope mode: RecordProvider can be used without roomId\n * to provide only auth context + ScopeRegistry. RecordScope components\n * handle individual WebSocket connections.\n */\n\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react'\nimport type { CollectionSchema } from '../../shared/types'\nimport { useAuth, getAuthToken } from '../auth'\nimport { RecordStore } from './store'\nimport { ScopeRegistryProvider } from './ScopeRegistry'\nimport { parseServerError } from './serverErrors'\nimport type {\n UserProfile,\n RoomUser,\n RoomConnectionState,\n FetchUserProfile,\n RecordData,\n} from './types'\nimport { MSG } from '@/shared/protocol/constants'\n\n// ============================================================================\n// RecordContext (per-scope connection state)\n// ============================================================================\n\nexport interface RecordContextValue {\n store: RecordStore\n roomId: string\n /** Collection names registered by this scope's schemas (used for scope resolution priority). */\n registeredCollections?: Set<string>\n userProfile: UserProfile | null\n userProfileLoading: boolean\n refetchUserProfile: () => Promise<void>\n roomRole: string | null\n allUsers: RoomUser[]\n /** True once the first MSG.USER_LIST response has been received. */\n usersLoaded: boolean\n status: RoomConnectionState\n ready: boolean\n /** Schemas discovered via MSG.LIST_SCHEMAS from the server. Available after ready. */\n discoveredSchemas?: CollectionSchema[]\n setUserRole: (userId: string, role: string) => void\n requestUserList: () => void\n registerSubscription: (subscriptionId: string, queryKey: string) => void\n unregisterSubscription: (subscriptionId: string) => void\n sendMessage: (message: { type: string; payload: unknown }) => void\n sendBinary: (data: Uint8Array) => void\n onBinaryMessage: (handler: (data: ArrayBuffer) => void) => () => void\n registerYjsJoinHandler: (docKey: string, handler: (canWrite: boolean) => void) => () => void\n sendConfirmed: (message: { type: string; payload: Record<string, unknown> }, timeoutMs?: number) => Promise<unknown>\n}\n\nexport const RecordContext = createContext<RecordContextValue | null>(null)\n\nexport function useRecordContext(): RecordContextValue {\n const ctx = useContext(RecordContext)\n if (!ctx) {\n throw new Error('useRecordContext must be used within a RecordProvider')\n }\n return ctx\n}\n\n// ============================================================================\n// RecordAuthContext (shared auth state for RecordScope)\n// ============================================================================\n\nexport interface RecordAuthContextValue {\n userProfile: UserProfile | null\n userProfileLoading: boolean\n refetchUserProfile: () => Promise<void>\n allowAnonymous: boolean\n /** Called by RecordScope when it receives an RBAC permission error */\n onPermissionError?: (title: string, detail: string) => void\n /** Called by RecordScope when it receives a validation/other error */\n onValidationError?: (title: string, detail: string) => void\n /** Get auth token for WebSocket connections. */\n getAuthToken?: () => Promise<string | null>\n}\n\nconst RecordAuthContext = createContext<RecordAuthContextValue | null>(null)\n\nexport function useRecordAuth(): RecordAuthContextValue | null {\n return useContext(RecordAuthContext)\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction recordMatchesWhere(record: RecordData, where?: Record<string, unknown>): boolean {\n if (!where) return true\n const r = record as RecordData & { data?: Record<string, unknown> }\n const data = r.data\n if (!data) return false\n // Schema columns take precedence over envelope fields — mirrors the\n // server-side where-builder in executeTableQuery so initial load and\n // live updates stay in sync when a schema defines a column named\n // 'createdBy' (e.g. the messaging `channels` collection).\n return Object.entries(where).every(([key, value]) => {\n if (key in data) return data[key] === value\n if (key === 'recordId') return r.recordId === value\n if (key === 'createdBy') return r.createdBy === value\n return false\n })\n}\n\n// ============================================================================\n// Core Provider (handles WebSocket connection — backward compat mode)\n// ============================================================================\n\ninterface RecordProviderCoreProps {\n roomId: string\n schemas: CollectionSchema[]\n wsUrl?: string\n children: ReactNode\n fetchUser: FetchUserProfile\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}\n\nfunction RecordProviderCore({\n roomId,\n schemas,\n wsUrl,\n children,\n fetchUser,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: RecordProviderCoreProps): React.ReactElement {\n\n const [userProfile, setUserProfile] = useState<UserProfile | null>(null)\n const [userProfileLoading, setUserProfileLoading] = useState(true)\n\n const [roomRole, setRoomRole] = useState<string | null>(null)\n const [allUsers, setAllUsers] = useState<RoomUser[]>([])\n const [usersLoaded, setUsersLoaded] = useState(false)\n const [status, setStatus] = useState<RoomConnectionState>('connecting')\n const [ready, setReady] = useState(false)\n\n // Callback refs for error handling — used by handleMessage (which has [] deps)\n // so it can invoke the latest callbacks without re-creating on every render.\n const onPermissionErrorRef = useRef<((title: string, detail: string) => void) | undefined>(undefined)\n const onValidationErrorRef = useRef<((title: string, detail: string) => void) | undefined>(undefined)\n\n const storeRef = useRef<RecordStore>(new RecordStore())\n const wsRef = useRef<WebSocket | null>(null)\n const subscriptionMapRef = useRef<Map<string, string>>(new Map())\n const binaryHandlersRef = useRef<Set<(data: ArrayBuffer) => void>>(new Set())\n const yjsJoinHandlersRef = useRef<Map<string, Set<(canWrite: boolean) => void>>>(new Map())\n const pendingRequestsRef = useRef<Map<string, {\n resolve: (data?: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n }>>(new Map())\n const reconnectAttemptRef = useRef(0)\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const connectedWithProfileRef = useRef(false)\n const userProfileRef = useRef<UserProfile | null>(null)\n\n userProfileRef.current = userProfile\n\n const refetchUserProfile = useCallback(async () => {\n try {\n const profile = await fetchUser()\n setUserProfile(profile)\n } catch (err) {\n console.error('[RecordProvider] Failed to refetch user profile:', err)\n }\n }, [fetchUser])\n\n // Fetch user profile on mount and refresh periodically.\n // fetchUser returns null when not signed in — that's fine.\n useEffect(() => {\n let mounted = true\n setUserProfileLoading(true)\n fetchUser()\n .then(profile => { if (mounted) setUserProfile(profile) })\n .finally(() => { if (mounted) setUserProfileLoading(false) })\n\n const interval = setInterval(() => {\n if (mounted) fetchUser().then(p => { if (mounted) setUserProfile(p) })\n }, 30000)\n\n return () => { mounted = false; clearInterval(interval) }\n }, [fetchUser])\n\n const handleMessage = useCallback((event: MessageEvent) => {\n if (event.data instanceof ArrayBuffer) {\n binaryHandlersRef.current.forEach(handler => handler(event.data as ArrayBuffer))\n return\n }\n\n try {\n const msg = JSON.parse(event.data as string) as { type: string; payload: unknown }\n const { type, payload } = msg\n\n switch (type) {\n case MSG.USER_INFO: {\n const serverUser = payload as { role: string }\n console.log('[WS] Ready:', { roomId, role: serverUser.role })\n setRoomRole(serverUser.role)\n setReady(true)\n reconnectAttemptRef.current = 0\n // Auto-request user list as part of connection handshake\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: MSG.USER_LIST, payload: {} }))\n }\n break\n }\n case MSG.USER_LIST:\n setAllUsers((payload as { users: RoomUser[] }).users)\n setUsersLoaded(true)\n break\n case MSG.QUERY_RESULT: {\n const { subscriptionId, records } = payload as { subscriptionId: string; records: RecordData[] }\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setQueryResult(queryKey, records)\n break\n }\n }\n break\n }\n case MSG.RECORD_CHANGE: {\n const { collection, record, changeType } = payload as {\n collection: string; record: RecordData; changeType: 'create' | 'update' | 'delete'\n }\n for (const [_subId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey) as { collection: string; where?: Record<string, unknown> }\n if (query.collection !== collection) continue\n const matches = recordMatchesWhere(record, query.where)\n const exists = storeRef.current.hasRecord(queryKey, record.recordId)\n if (changeType === 'delete') {\n if (exists) storeRef.current.applyChange(queryKey, record, 'delete')\n } else if (changeType === 'create') {\n if (matches) storeRef.current.applyChange(queryKey, record, 'create')\n } else {\n if (matches && exists) storeRef.current.applyChange(queryKey, record, 'update')\n else if (matches && !exists) storeRef.current.applyChange(queryKey, record, 'create')\n else if (!matches && exists) storeRef.current.applyChange(queryKey, record, 'delete')\n }\n } catch { /* Skip invalid query keys */ }\n }\n break\n }\n case MSG.ERROR: {\n const { subscriptionId, error } = payload as { subscriptionId?: string; error: string }\n if (subscriptionId) {\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) { storeRef.current.setError(queryKey, error); break }\n }\n } else {\n const parsed = parseServerError(error)\n console.error('[RecordProvider] Error:', error)\n // Errors are surfaced via callback refs — the consuming app\n // is responsible for displaying them (no built-in overlays/toasts).\n if (parsed.isPermissionError) {\n onPermissionErrorRef.current?.(parsed.title, parsed.detail)\n } else {\n onValidationErrorRef.current?.(parsed.title, parsed.detail)\n }\n }\n break\n }\n case MSG.YJS_JOIN: {\n const { collection, recordId, fieldName, canWrite } = payload as {\n collection: string; recordId: string; fieldName: string; canWrite: boolean\n }\n const docKey = `${collection}:${recordId}:${fieldName}`\n yjsJoinHandlersRef.current.get(docKey)?.forEach(handler => handler(canWrite))\n break\n }\n case MSG.ACK: {\n const { requestId, success, error, ...rest } = payload as {\n requestId: string; success: boolean; error?: string; [key: string]: unknown\n }\n const pending = pendingRequestsRef.current.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequestsRef.current.delete(requestId)\n if (success) pending.resolve(rest)\n else pending.reject(new Error(error || 'Mutation rejected'))\n }\n break\n }\n case MSG.RESUBSCRIBE: {\n // Team membership changed — re-subscribe all active queries\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) {\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip invalid */ }\n }\n }\n break\n }\n }\n } catch (e) {\n console.error('[RecordProvider] Failed to parse message:', e)\n }\n }, [])\n\n const connect = useCallback(async () => {\n const profile = userProfileRef.current\n if (!profile && !allowAnonymous) return\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n // We started anonymously; profile arriving means a token is now\n // available. Reconnect so the WS carries it and the DO sees the\n // authenticated identity (read from JWT claims).\n if (profile && !connectedWithProfileRef.current) {\n console.log(`[WS] Reconnecting with profile data`, { roomId })\n wsRef.current.onclose = null\n wsRef.current.close()\n wsRef.current = null\n } else {\n return\n }\n }\n if (wsRef.current?.readyState === WebSocket.CONNECTING) return\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n\n let baseUrl: string\n if (wsUrl) {\n baseUrl = wsUrl.replace(/^http/, 'ws')\n } else {\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n baseUrl = `${protocol}//${window.location.host}`\n }\n\n const params = new URLSearchParams()\n\n // Identity (userId, name, email, imageUrl, role) is derived server-side\n // from the verified JWT — any client-supplied identity params would be\n // stripped at the worker edge, so we don't send them.\n try {\n const tokenFn = getAuthTokenProp ?? getAuthToken\n const token = await tokenFn()\n if (token) params.set('token', token)\n } catch { /* Token fetch failed */ }\n\n connectedWithProfileRef.current = !!profile\n\n const wsPath = `/ws/${roomId}`\n const url = `${baseUrl}${wsPath}?${params.toString()}`\n console.log('[WS] Connecting:', { roomId, attempt: reconnectAttemptRef.current })\n const ws = new WebSocket(url)\n ws.binaryType = 'arraybuffer'\n\n ws.onopen = () => {\n console.log('[WS] Connected:', { roomId })\n setStatus('connected')\n }\n ws.onmessage = handleMessage\n ws.onclose = (event) => {\n console.log('[WS] Closed:', { roomId, code: event.code, reason: event.reason, wasClean: event.wasClean })\n setStatus('disconnected')\n setReady(false)\n wsRef.current = null\n for (const [_id, pending] of pendingRequestsRef.current) {\n clearTimeout(pending.timer)\n pending.reject(new Error('WebSocket disconnected'))\n }\n pendingRequestsRef.current.clear()\n const attempt = reconnectAttemptRef.current\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000)\n console.log('[WS] Scheduling reconnect:', { roomId, attempt, delayMs: delay })\n reconnectAttemptRef.current = attempt + 1\n reconnectTimeoutRef.current = setTimeout(connect, delay)\n }\n ws.onerror = (e) => { console.error('[WS] Error:', { roomId, error: e }) }\n wsRef.current = ws\n }, [roomId, wsUrl, handleMessage, allowAnonymous, getAuthTokenProp])\n\n useEffect(() => {\n if (userProfile?.id) connect()\n else if (allowAnonymous && !userProfileLoading) connect()\n }, [userProfile?.id, userProfileLoading, allowAnonymous, connect])\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible') {\n const ws = wsRef.current\n if (ws?.readyState !== WebSocket.OPEN && (userProfileRef.current || allowAnonymous)) {\n console.log('[WS] Reconnecting after visibility change')\n reconnectAttemptRef.current = 0\n connect()\n }\n }\n }\n document.addEventListener('visibilitychange', handleVisibilityChange)\n return () => document.removeEventListener('visibilitychange', handleVisibilityChange)\n }, [roomId, connect])\n\n useEffect(() => {\n return () => {\n console.log('[WS] Unmounting provider:', { roomId })\n if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current)\n wsRef.current?.close()\n }\n }, [roomId])\n\n const sendMessage = useCallback((message: { type: string; payload: unknown }) => {\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message))\n else console.warn('[RecordProvider] Cannot send message, WebSocket not connected')\n }, [])\n\n const setUserRole = useCallback((userId: string, role: string) => {\n sendMessage({ type: MSG.SET_ROLE, payload: { userId, role } })\n }, [sendMessage])\n\n const requestUserList = useCallback(() => {\n sendMessage({ type: MSG.USER_LIST, payload: {} })\n }, [sendMessage])\n\n const registerSubscription = useCallback((subscriptionId: string, queryKey: string) => {\n subscriptionMapRef.current.set(subscriptionId, queryKey)\n }, [])\n\n const unregisterSubscription = useCallback((subscriptionId: string) => {\n subscriptionMapRef.current.delete(subscriptionId)\n }, [])\n\n const sendBinary = useCallback((data: Uint8Array) => {\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) ws.send(data)\n }, [])\n\n const onBinaryMessage = useCallback((handler: (data: ArrayBuffer) => void) => {\n binaryHandlersRef.current.add(handler)\n return () => { binaryHandlersRef.current.delete(handler) }\n }, [])\n\n const registerYjsJoinHandler = useCallback((docKey: string, handler: (canWrite: boolean) => void) => {\n if (!yjsJoinHandlersRef.current.has(docKey)) {\n yjsJoinHandlersRef.current.set(docKey, new Set())\n }\n yjsJoinHandlersRef.current.get(docKey)!.add(handler)\n return () => {\n const handlers = yjsJoinHandlersRef.current.get(docKey)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) yjsJoinHandlersRef.current.delete(docKey)\n }\n }\n }, [])\n\n const sendConfirmed = useCallback((\n message: { type: string; payload: Record<string, unknown> },\n timeoutMs = 10000\n ): Promise<unknown> => {\n const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error('WebSocket not connected'))\n }\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequestsRef.current.delete(requestId)\n reject(new Error('Mutation confirmation timed out'))\n }, timeoutMs)\n pendingRequestsRef.current.set(requestId, { resolve, reject, timer })\n ws.send(JSON.stringify({ ...message, payload: { ...message.payload, requestId } }))\n })\n }, [])\n\n const value: RecordContextValue = useMemo(() => ({\n store: storeRef.current, roomId, userProfile, userProfileLoading, refetchUserProfile,\n roomRole, allUsers, usersLoaded, status, ready,\n setUserRole, requestUserList,\n registerSubscription, unregisterSubscription, sendMessage, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, sendConfirmed,\n }), [roomId, userProfile, userProfileLoading, refetchUserProfile, roomRole, allUsers, usersLoaded, status, ready, setUserRole, requestUserList, registerSubscription, unregisterSubscription, sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, sendConfirmed])\n\n const onPermissionError = useCallback((title: string, detail: string) => {\n onPermissionErrorRef.current?.(title, detail)\n }, [])\n\n const onValidationError = useCallback((title: string, detail: string) => {\n onValidationErrorRef.current?.(title, detail)\n }, [])\n\n const authValue: RecordAuthContextValue = useMemo(() => ({\n userProfile,\n userProfileLoading,\n refetchUserProfile,\n allowAnonymous,\n getAuthToken: getAuthTokenProp,\n onPermissionError,\n onValidationError,\n }), [userProfile, userProfileLoading, refetchUserProfile, allowAnonymous, getAuthTokenProp, onPermissionError, onValidationError])\n\n return (\n <RecordAuthContext.Provider value={authValue}>\n <ScopeRegistryProvider>\n <RecordContext.Provider value={value}>\n {children}\n </RecordContext.Provider>\n </ScopeRegistryProvider>\n </RecordAuthContext.Provider>\n )\n}\n\n// ============================================================================\n// Auth-Only Provider (multi-scope mode — no roomId, no WS)\n// ============================================================================\n\ninterface RecordProviderAuthOnlyProps {\n children: ReactNode\n fetchUser: FetchUserProfile\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}\n\nfunction RecordProviderAuthOnly({\n children,\n fetchUser,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: RecordProviderAuthOnlyProps): React.ReactElement {\n const [userProfile, setUserProfile] = useState<UserProfile | null>(null)\n const [userProfileLoading, setUserProfileLoading] = useState(true)\n\n const refetchUserProfile = useCallback(async () => {\n try {\n const profile = await fetchUser()\n setUserProfile(profile)\n } catch (err) {\n console.error('[RecordProvider] Failed to refetch user profile:', err)\n }\n }, [fetchUser])\n\n // Fetch user profile on mount and refresh periodically.\n // fetchUser returns null when not signed in — that's fine, no retry needed.\n useEffect(() => {\n let mounted = true\n setUserProfileLoading(true)\n fetchUser()\n .then(profile => { if (mounted) setUserProfile(profile) })\n .finally(() => { if (mounted) setUserProfileLoading(false) })\n\n const interval = setInterval(() => {\n if (mounted) {\n fetchUser().then(p => { if (mounted) setUserProfile(p) })\n }\n }, 30000)\n\n return () => { mounted = false; clearInterval(interval) }\n }, [fetchUser])\n\n const authValue: RecordAuthContextValue = useMemo(() => ({\n userProfile,\n userProfileLoading,\n refetchUserProfile,\n allowAnonymous,\n getAuthToken: getAuthTokenProp,\n }), [userProfile, userProfileLoading, refetchUserProfile, allowAnonymous, getAuthTokenProp])\n\n return (\n <RecordAuthContext.Provider value={authValue}>\n <ScopeRegistryProvider>\n {children}\n </ScopeRegistryProvider>\n </RecordAuthContext.Provider>\n )\n}\n\n// ============================================================================\n// Main Entry Point\n// ============================================================================\n\n/**\n * RecordProvider - Main entry point for storage.\n *\n * Two modes:\n * 1. **Single-scope (backward compat):** Pass `roomId` + `schemas`. Opens one WS connection.\n * 2. **Multi-scope:** Omit `roomId`. Only provides auth + ScopeRegistry.\n * Use `<RecordScope>` components for individual WS connections.\n *\n * @example\n * ```tsx\n * // Single-scope (backward compat)\n * <RecordProvider roomId=\"my-app\" schemas={schemas}>\n * <App />\n * </RecordProvider>\n *\n * // Multi-scope\n * <RecordProvider>\n * <RecordScope roomId=\"app:slack-clone\" schemas={appSchemas}>\n * <RecordScope roomId={`conv:${channelId}`} schemas={convSchemas}>\n * <ChannelView />\n * </RecordScope>\n * </RecordScope>\n * </RecordProvider>\n * ```\n */\nexport function RecordProvider({\n roomId,\n schemas = [],\n wsUrl,\n children,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: {\n roomId?: string\n schemas?: CollectionSchema[]\n wsUrl?: string\n children: ReactNode\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}): React.ReactElement {\n const { isLoaded, isSignedIn } = useAuth()\n\n // Derive user profile from the JWT — no API call needed.\n // Returns null when not signed in (no error, no console spam).\n const fetchUser = useCallback(async (): Promise<UserProfile | null> => {\n if (!isSignedIn) return null\n const token = await getAuthToken()\n if (!token) return null\n try {\n const parts = token.split('.')\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n return {\n id: payload.sub,\n name: payload.name ?? '',\n email: payload.email ?? '',\n imageUrl: payload.image ?? undefined,\n }\n } catch {\n return null\n }\n }, [isSignedIn])\n\n // Build getAuthToken function — use prop override or default to auth module\n const getAuthTokenFn = useCallback(async (): Promise<string | null> => {\n if (getAuthTokenProp) return getAuthTokenProp()\n if (!isSignedIn) return null\n return getAuthToken()\n }, [getAuthTokenProp, isSignedIn])\n\n // Not loaded yet — render nothing (no loading screens — that's the app's job)\n if (!isLoaded) {\n return <>{null}</>\n }\n\n // Not signed in and not allowing anonymous — render nothing\n if (!isSignedIn && !allowAnonymous) {\n return <>{null}</>\n }\n\n if (roomId) {\n return (\n <RecordProviderCore\n roomId={roomId}\n schemas={schemas}\n wsUrl={wsUrl}\n fetchUser={fetchUser}\n allowAnonymous={allowAnonymous}\n getAuthToken={getAuthTokenFn}\n >\n {children}\n </RecordProviderCore>\n )\n }\n\n return (\n <RecordProviderAuthOnly\n fetchUser={fetchUser}\n allowAnonymous={allowAnonymous}\n getAuthToken={getAuthTokenFn}\n >\n {children}\n </RecordProviderAuthOnly>\n )\n}\n","/**\n * RecordStore\n * \n * Manages query subscriptions with version-tracked caching.\n * Uses external store pattern for React integration.\n */\n\nimport type { RecordData } from './types'\n\ninterface QueryState {\n status: 'loading' | 'ready' | 'error'\n records: RecordData[] // Cached array - stable reference until data changes\n version: number // Incremented on every change\n error?: string\n}\n\n// Stable empty array - never changes reference\nconst EMPTY_RECORDS: RecordData[] = []\n\nexport class RecordStore {\n private queries = new Map<string, QueryState>()\n private listeners = new Map<string, Set<() => void>>()\n /** Reference count for each query - only send SUBSCRIBE on first, UNSUBSCRIBE on last */\n private refCounts = new Map<string, number>()\n /** Track the single subscriptionId per queryKey (for deduplication) */\n private activeSubscriptions = new Map<string, string>()\n\n subscribe(queryKey: string, listener: () => void): () => void {\n const set = this.listeners.get(queryKey) ?? new Set()\n set.add(listener)\n this.listeners.set(queryKey, set)\n return () => {\n set.delete(listener)\n if (set.size === 0) {\n this.listeners.delete(queryKey)\n }\n }\n }\n\n getSnapshot(queryKey: string): RecordData[] {\n // Return stable empty array if query doesn't exist\n const state = this.queries.get(queryKey)\n if (!state) return EMPTY_RECORDS\n return state.records\n }\n\n getStatus(queryKey: string): 'loading' | 'ready' | 'error' {\n return this.queries.get(queryKey)?.status ?? 'loading'\n }\n\n getError(queryKey: string): string | undefined {\n return this.queries.get(queryKey)?.error\n }\n\n /**\n * Initialize a query subscription.\n * Returns true if this is the FIRST subscriber (should send SUBSCRIBE).\n */\n initQuery(queryKey: string): boolean {\n const prevCount = this.refCounts.get(queryKey) ?? 0\n this.refCounts.set(queryKey, prevCount + 1)\n \n if (!this.queries.has(queryKey)) {\n this.queries.set(queryKey, { status: 'loading', records: [], version: 0 })\n }\n \n // Return true if this is the first subscriber\n return prevCount === 0\n }\n \n /**\n * Release a query subscription.\n * Returns true if this was the LAST subscriber (should send UNSUBSCRIBE).\n */\n releaseQuery(queryKey: string): boolean {\n const count = (this.refCounts.get(queryKey) ?? 1) - 1\n \n if (count <= 0) {\n this.refCounts.delete(queryKey)\n this.activeSubscriptions.delete(queryKey)\n return true // Last subscriber\n }\n \n this.refCounts.set(queryKey, count)\n return false // Still has subscribers\n }\n \n /** Store the subscriptionId for a queryKey (for routing server responses) */\n setSubscriptionId(queryKey: string, subscriptionId: string): void {\n this.activeSubscriptions.set(queryKey, subscriptionId)\n }\n \n /** Get the subscriptionId for a queryKey */\n getSubscriptionId(queryKey: string): string | undefined {\n return this.activeSubscriptions.get(queryKey)\n }\n\n // Handle QUERY_RESULT from server\n setQueryResult(queryKey: string, records: RecordData[]): void {\n const current = this.queries.get(queryKey)\n\n this.queries.set(queryKey, {\n status: 'ready',\n records, // New array reference\n version: (current?.version ?? 0) + 1,\n })\n this.notify(queryKey)\n }\n\n /** Check if a record exists in a query's results */\n hasRecord(queryKey: string, recordId: string): boolean {\n const state = this.queries.get(queryKey)\n if (!state) return false\n return state.records.some(r => r.recordId === recordId)\n }\n\n // Handle RECORD_CHANGE from server\n applyChange(\n queryKey: string,\n record: RecordData,\n changeType: 'create' | 'update' | 'delete'\n ): void {\n const state = this.queries.get(queryKey)\n if (!state) return\n\n let newRecords: RecordData[]\n\n if (changeType === 'delete') {\n newRecords = state.records.filter(r => r.recordId !== record.recordId)\n } else if (changeType === 'create') {\n // Check if record already exists (prevent duplicates from race conditions)\n const exists = state.records.some(r => r.recordId === record.recordId)\n if (exists) {\n // If it exists, treat as update instead\n newRecords = state.records.map(r => r.recordId === record.recordId ? record : r)\n } else {\n // Append (correct for asc order, which is the common case for real-time data)\n newRecords = [...state.records, record]\n }\n } else {\n // update\n newRecords = state.records.map(r => r.recordId === record.recordId ? record : r)\n }\n\n this.queries.set(queryKey, {\n ...state,\n records: newRecords,\n version: state.version + 1,\n })\n this.notify(queryKey)\n }\n\n /**\n * Reset a query to loading state (used on WebSocket reconnect).\n * Preserves stale records so the UI can show them while reconnecting.\n */\n resetToLoading(queryKey: string): void {\n const current = this.queries.get(queryKey)\n if (!current) return\n\n this.queries.set(queryKey, {\n ...current,\n status: 'loading',\n version: current.version + 1,\n })\n this.notify(queryKey)\n }\n\n setError(queryKey: string, error: string): void {\n const current = this.queries.get(queryKey)\n this.queries.set(queryKey, {\n status: 'error',\n records: current?.records ?? [],\n version: (current?.version ?? 0) + 1,\n error,\n })\n this.notify(queryKey)\n }\n\n // Cleanup when query is no longer needed\n removeQuery(queryKey: string): void {\n this.queries.delete(queryKey)\n this.listeners.delete(queryKey)\n }\n\n private notify(queryKey: string): void {\n const set = this.listeners.get(queryKey)\n if (set) {\n set.forEach(fn => fn())\n }\n }\n}\n","/**\n * ScopeRegistry\n *\n * React context that maps collection names to scope entries.\n * RecordScope registers its collections on mount, and hooks\n * (useQuery, useMutations) resolve the correct scope by collection name.\n *\n * Each registration is tagged with a scopeId so that unregister only\n * removes entries owned by the calling scope — preventing one scope\n * from breaking another when both register the same collections.\n */\n\nimport { createContext, useContext, useCallback, useRef, useMemo, type ReactNode } from 'react'\nimport type { RecordStore } from './store'\nimport type { RoomConnectionState } from './types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ScopeEntry {\n store: RecordStore\n sendMessage: (msg: { type: string; payload: unknown }) => void\n sendConfirmed: (\n msg: { type: string; payload: Record<string, unknown> },\n timeoutMs?: number,\n ) => Promise<unknown>\n registerSubscription: (subscriptionId: string, queryKey: string) => void\n unregisterSubscription: (subscriptionId: string) => void\n sendBinary: (data: Uint8Array) => void\n onBinaryMessage: (handler: (data: ArrayBuffer) => void) => () => void\n registerYjsJoinHandler: (\n docKey: string,\n handler: (canWrite: boolean) => void,\n ) => () => void\n ready: boolean\n status: RoomConnectionState\n}\n\ninterface Registration {\n scopeId: string\n entry: ScopeEntry\n}\n\ninterface ScopeRegistryValue {\n register: (scopeId: string, collections: string[], entry: ScopeEntry) => void\n unregister: (scopeId: string, collections: string[]) => void\n resolve: (collection: string) => ScopeEntry | null\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst ScopeRegistryContext = createContext<ScopeRegistryValue | null>(null)\n\nexport function useScopeRegistry(): ScopeRegistryValue | null {\n return useContext(ScopeRegistryContext)\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport function ScopeRegistryProvider({ children }: { children: ReactNode }) {\n const mapRef = useRef(new Map<string, Registration>())\n\n const register = useCallback((scopeId: string, collections: string[], entry: ScopeEntry) => {\n for (const name of collections) {\n mapRef.current.set(name, { scopeId, entry })\n }\n }, [])\n\n const unregister = useCallback((scopeId: string, collections: string[]) => {\n for (const name of collections) {\n const existing = mapRef.current.get(name)\n // Only unregister if this scope owns the registration\n if (existing?.scopeId === scopeId) {\n mapRef.current.delete(name)\n }\n }\n }, [])\n\n const resolve = useCallback((collection: string): ScopeEntry | null => {\n return mapRef.current.get(collection)?.entry ?? null\n }, [])\n\n const value = useMemo(() => ({ register, unregister, resolve }), [register, unregister, resolve])\n\n return (\n <ScopeRegistryContext.Provider value={value}>\n {children}\n </ScopeRegistryContext.Provider>\n )\n}\n","/**\n * Server Error Parser\n * \n * Parses server-side error strings into user-friendly messages.\n * Covers RBAC permission errors, validation errors, and generic errors.\n */\n\nexport interface ServerErrorInfo {\n title: string\n detail: string\n /** True for RBAC/permission errors (shown as toasts). False for validation/other (shown in error overlay). */\n isPermissionError: boolean\n}\n\n/**\n * Humanize a collection slug (e.g. \"rbac-notes\" → \"Notes\", \"team-posts\" → \"Team Posts\").\n */\nfunction humanizeCollection(slug: string): string {\n return slug\n .replace(/^rbac-/, '')\n .split(/[-_]/)\n .map(w => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ')\n}\n\n/**\n * Humanize a role name for display (e.g. \"viewer\" → \"Viewer\").\n */\nfunction humanizeRole(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1)\n}\n\n/**\n * Parse a server error string into a user-friendly message.\n * Handles RBAC errors, validation errors, and falls back to a generic error.\n */\nexport function parseServerError(error: string): ServerErrorInfo {\n // ── RBAC Errors ──────────────────────────────────────────────────────\n\n // UPDATE DENIED: role=viewer, collection=tasks\n const updateMatch = error.match(/^UPDATE DENIED: role=(\\w+), collection=(.+)/)\n if (updateMatch) {\n return {\n title: `${humanizeRole(updateMatch[1])}s can't edit ${humanizeCollection(updateMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const createMatch = error.match(/^CREATE DENIED: role=(\\w+), collection=(.+)/)\n if (createMatch) {\n return {\n title: `${humanizeRole(createMatch[1])}s can't create ${humanizeCollection(createMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const deleteMatch = error.match(/^DELETE DENIED: role=(\\w+), collection=(.+)/)\n if (deleteMatch) {\n return {\n title: `${humanizeRole(deleteMatch[1])}s can't delete ${humanizeCollection(deleteMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const readMatch = error.match(/^READ DENIED: role=(\\w+), collection=(.+)/)\n if (readMatch) {\n return {\n title: `${humanizeRole(readMatch[1])}s can't view ${humanizeCollection(readMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const fieldMatch = error.match(/^FIELD ERROR: Cannot update field '(\\w+)'.*role '(\\w+)'/)\n if (fieldMatch) {\n return {\n title: `${humanizeRole(fieldMatch[2])}s can't edit \"${fieldMatch[1]}\"`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const fieldGenericMatch = error.match(/^FIELD ERROR: (.+)/)\n if (fieldGenericMatch) {\n return {\n title: 'Field not editable',\n detail: '',\n isPermissionError: true,\n }\n }\n\n const permMatch = error.match(/^Permission denied: (.+)/)\n if (permMatch) {\n return {\n title: permMatch[1].charAt(0).toUpperCase() + permMatch[1].slice(1),\n detail: '',\n isPermissionError: true,\n }\n }\n\n // ── Validation Errors ────────────────────────────────────────────────\n\n // Missing required field: fieldName\n const requiredMatch = error.match(/^Missing required field: (.+)/)\n if (requiredMatch) {\n return {\n title: 'Missing field',\n detail: `\"${requiredMatch[1]}\" is required`,\n isPermissionError: false,\n }\n }\n\n // Cannot change immutable field: fieldName\n const immutableMatch = error.match(/^Cannot change immutable field: (.+)/)\n if (immutableMatch) {\n return {\n title: 'Cannot modify',\n detail: `\"${immutableMatch[1]}\" cannot be changed after creation`,\n isPermissionError: false,\n }\n }\n\n // Field 'x' must be your user ID\n const userBoundMatch = error.match(/^Field '(.+)' must be your user ID/)\n if (userBoundMatch) {\n return {\n title: 'Invalid value',\n detail: `\"${userBoundMatch[1]}\" must be your own user ID`,\n isPermissionError: false,\n }\n }\n\n // ── Fallback ─────────────────────────────────────────────────────────\n\n return {\n title: 'Error',\n detail: error,\n isPermissionError: false,\n }\n}\n","/**\n * RecordScope\n *\n * Opens a direct WebSocket connection to a RecordRoom DO.\n * Manages subscriptions, reconnection, and state via RecordStore.\n * Registers collections in ScopeRegistry so hooks resolve to the right scope.\n *\n * @example\n * ```tsx\n * <RecordProvider>\n * <RecordScope\n * roomId=\"app:my-app\"\n * schemas={appSchemas}\n * appId=\"my-app\"\n * sharedScopes={[\n * { roomId: 'workspace:default', schemas: workspaceSchemas },\n * ]}\n * >\n * <App />\n * </RecordScope>\n * </RecordProvider>\n * ```\n */\n\nimport React, {\n useEffect,\n useState,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react'\nimport type { CollectionSchema } from '../../shared/types'\nimport { RecordContext, type RecordContextValue } from './context'\nimport { useRecordAuth } from './context'\nimport { RecordStore } from './store'\nimport { useScopeRegistry, type ScopeEntry } from './ScopeRegistry'\nimport { getAuthToken } from '../auth'\nimport { wsLog } from './ws-log'\nimport { parseServerError } from './serverErrors'\nimport type { RoomUser, RoomConnectionState, RecordData } from './types'\nimport { MSG } from '@/shared/protocol/constants'\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction recordMatchesWhere(\n record: RecordData,\n where?: Record<string, unknown>,\n): boolean {\n if (!where) return true\n const r = record as RecordData & { data?: Record<string, unknown> }\n const data = r.data\n if (!data) return false\n // Schema columns take precedence over envelope fields — mirrors the\n // server-side where-builder in executeTableQuery so initial load and\n // live updates stay in sync when a schema defines a column named\n // 'createdBy' (e.g. the messaging `channels` collection).\n return Object.entries(where).every(([key, value]) => {\n if (key in data) return data[key] === value\n if (key === 'recordId') return r.recordId === value\n if (key === 'createdBy') return r.createdBy === value\n return false\n })\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface SharedScopeConfig {\n roomId: string\n schemas: CollectionSchema[]\n}\n\ninterface RecordScopeProps {\n roomId: string\n schemas: CollectionSchema[]\n children?: ReactNode\n /** App ID passed to the server for schema resolution. */\n appId: string\n /** Additional scopes to connect (headless — no children, just register collections). */\n sharedScopes?: SharedScopeConfig[]\n /** WebSocket base URL override. Derived from window.location if omitted. */\n wsUrl?: string\n /** Path prefix for WebSocket route. Default: '/ws'. */\n wsPathPrefix?: string\n /** Don't register collections in ScopeRegistry (prevents name collisions). */\n isolated?: boolean\n}\n\n// ============================================================================\n// Headless scope — opens a WS connection and registers collections only\n// ============================================================================\n\nfunction HeadlessScope({ roomId, schemas, appId, wsUrl, wsPathPrefix }: {\n roomId: string\n schemas: CollectionSchema[]\n appId: string\n wsUrl?: string\n wsPathPrefix?: string\n}) {\n return (\n <ScopeConnection\n roomId={roomId}\n schemas={schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n />\n )\n}\n\n// ============================================================================\n// Core WebSocket connection logic (shared by primary + headless scopes)\n// ============================================================================\n\nfunction ScopeConnection({\n roomId,\n schemas,\n appId,\n children,\n wsUrl,\n wsPathPrefix = '/ws',\n isolated = false,\n}: {\n roomId: string\n schemas: CollectionSchema[]\n appId: string\n children?: ReactNode\n wsUrl?: string\n wsPathPrefix?: string\n isolated?: boolean\n}) {\n const auth = useRecordAuth()\n const registry = useScopeRegistry()\n\n const scopeIdRef = useRef(`scope-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`)\n\n // Room state\n const [roomRole, setRoomRole] = useState<string | null>(null)\n const [allUsers, setAllUsers] = useState<RoomUser[]>([])\n const [usersLoaded, setUsersLoaded] = useState(false)\n const [status, setStatus] = useState<RoomConnectionState>('connecting')\n const [ready, setReady] = useState(false)\n const [discoveredSchemas, setDiscoveredSchemas] = useState<CollectionSchema[]>([])\n\n // Refs\n const storeRef = useRef<RecordStore>(new RecordStore())\n const wsRef = useRef<WebSocket | null>(null)\n const subscriptionMapRef = useRef<Map<string, string>>(new Map())\n const binaryHandlersRef = useRef<Set<(data: ArrayBuffer) => void>>(new Set())\n const yjsJoinHandlersRef = useRef<Map<string, Set<(canWrite: boolean) => void>>>(new Map())\n const pendingRequestsRef = useRef<Map<string, {\n resolve: (data?: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n }>>(new Map())\n const reconnectAttemptRef = useRef(0)\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n // Auth refs (stable across renders)\n const userProfileRef = useRef(auth?.userProfile ?? null)\n userProfileRef.current = auth?.userProfile ?? null\n const getAuthTokenRef = useRef(auth?.getAuthToken ?? null)\n getAuthTokenRef.current = auth?.getAuthToken ?? null\n const authCallbacksRef = useRef({\n onPermissionError: auth?.onPermissionError,\n onValidationError: auth?.onValidationError,\n })\n authCallbacksRef.current.onPermissionError = auth?.onPermissionError\n authCallbacksRef.current.onValidationError = auth?.onValidationError\n const allowAnonymous = auth?.allowAnonymous ?? false\n\n // ── Message handler ──────────────────────────────────────────────────\n\n const handleMessage = useCallback((event: MessageEvent) => {\n if (event.data instanceof ArrayBuffer) {\n binaryHandlersRef.current.forEach((h) => h(event.data as ArrayBuffer))\n return\n }\n\n let msg: { type: string; payload: unknown }\n try {\n msg = JSON.parse(event.data as string)\n } catch {\n console.error('[RecordScope] Failed to parse message')\n return\n }\n\n const { type, payload } = msg\n\n switch (type) {\n case MSG.USER_INFO: {\n const { role } = payload as { role: string }\n setRoomRole(role)\n setReady(true)\n reconnectAttemptRef.current = 0\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: MSG.USER_LIST, payload: {} }))\n }\n break\n }\n\n case MSG.USER_LIST:\n setAllUsers((payload as { users: RoomUser[] }).users)\n setUsersLoaded(true)\n break\n\n case MSG.QUERY_RESULT: {\n const { subscriptionId, records } = payload as { subscriptionId: string; records: RecordData[] }\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setQueryResult(queryKey, records)\n break\n }\n }\n break\n }\n\n case MSG.RECORD_CHANGE: {\n const { collection, record, changeType } = payload as {\n collection: string; record: RecordData; changeType: 'create' | 'update' | 'delete'\n }\n for (const [, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey) as { collection: string; where?: Record<string, unknown> }\n if (query.collection !== collection) continue\n const matches = recordMatchesWhere(record, query.where)\n const exists = storeRef.current.hasRecord(queryKey, record.recordId)\n if (changeType === 'delete') {\n if (exists) storeRef.current.applyChange(queryKey, record, 'delete')\n } else if (changeType === 'create') {\n if (matches) storeRef.current.applyChange(queryKey, record, 'create')\n } else {\n if (matches && exists) storeRef.current.applyChange(queryKey, record, 'update')\n else if (matches && !exists) storeRef.current.applyChange(queryKey, record, 'create')\n else if (!matches && exists) storeRef.current.applyChange(queryKey, record, 'delete')\n }\n } catch { /* skip invalid query keys */ }\n }\n break\n }\n\n case MSG.ERROR: {\n const { subscriptionId, error } = payload as { subscriptionId?: string; error: string }\n if (subscriptionId) {\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setError(queryKey, error)\n break\n }\n }\n } else {\n const parsed = parseServerError(error)\n if (parsed.isPermissionError) {\n authCallbacksRef.current.onPermissionError?.(parsed.title, parsed.detail)\n } else {\n authCallbacksRef.current.onValidationError?.(parsed.title, parsed.detail)\n }\n }\n break\n }\n\n case MSG.YJS_JOIN: {\n const { collection, recordId, fieldName, canWrite } = payload as {\n collection: string; recordId: string; fieldName: string; canWrite: boolean\n }\n const docKey = `${collection}:${recordId}:${fieldName}`\n yjsJoinHandlersRef.current.get(docKey)?.forEach((h) => h(canWrite))\n break\n }\n\n case MSG.ACK: {\n const { requestId, success, error, ...rest } = payload as {\n requestId: string; success: boolean; error?: string; [key: string]: unknown\n }\n const pending = pendingRequestsRef.current.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequestsRef.current.delete(requestId)\n success ? pending.resolve(rest) : pending.reject(new Error(error || 'Mutation rejected'))\n }\n break\n }\n\n case MSG.LIST_SCHEMAS: {\n const { schemas: list } = payload as { schemas: CollectionSchema[] }\n setDiscoveredSchemas(list ?? [])\n break\n }\n\n case MSG.RESUBSCRIBE: {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) {\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip */ }\n }\n }\n break\n }\n }\n }, [roomId])\n\n // ── WebSocket connect ────────────────────────────────────────────────\n\n const connect = useCallback(async () => {\n const profile = userProfileRef.current\n const hasTokenProvider = !!getAuthTokenRef.current\n if (!profile && !hasTokenProvider && !allowAnonymous) return\n\n if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) return\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = wsUrl?.replace(/^http/, 'ws') ?? `${protocol}//${window.location.host}`\n const params = new URLSearchParams()\n\n // Identity is derived server-side from the verified JWT — any\n // client-supplied identity params would be stripped at the worker\n // edge, so we don't send them.\n try {\n const tokenFn = getAuthTokenRef.current ?? getAuthToken\n const token = await tokenFn()\n if (token) params.set('token', token)\n } catch { /* token fetch failed — connect anyway if anonymous */ }\n\n params.set('appId', appId)\n\n const url = `${baseUrl}${wsPathPrefix}/${roomId}?${params.toString()}`\n wsLog('connecting', roomId)\n const ws = new WebSocket(url)\n ws.binaryType = 'arraybuffer'\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', roomId)\n setStatus('connected')\n // Re-subscribe all active queries\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip */ }\n }\n }\n\n ws.onmessage = handleMessage\n\n ws.onclose = () => {\n wsLog('disconnected', roomId)\n setStatus('disconnected')\n setReady(false)\n wsRef.current = null\n for (const [, queryKey] of subscriptionMapRef.current) storeRef.current.resetToLoading(queryKey)\n for (const [, pending] of pendingRequestsRef.current) {\n clearTimeout(pending.timer)\n pending.reject(new Error('WebSocket disconnected'))\n }\n pendingRequestsRef.current.clear()\n const attempt = reconnectAttemptRef.current\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000)\n reconnectAttemptRef.current = attempt + 1\n reconnectTimeoutRef.current = setTimeout(connect, delay)\n }\n\n ws.onerror = () => {}\n }, [roomId, wsUrl, wsPathPrefix, handleMessage, allowAnonymous, appId])\n\n // ── Disconnect helper ─────────────────────────────────────────────────\n\n const disconnect = useCallback(() => {\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n const ws = wsRef.current\n if (ws) {\n wsLog('closing', roomId)\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n wsRef.current = null\n }\n setStatus('connecting')\n setReady(false)\n reconnectAttemptRef.current = 0\n }, [roomId])\n\n // ── Auth identity change → disconnect and reconnect ──────────────────\n // Fires when: sign-in, sign-out, account switch, or initial load completes.\n // The identity is the user's profile ID (null = anonymous).\n\n const userProfileId = auth?.userProfile?.id ?? null\n const userProfileLoading = auth?.userProfileLoading ?? false\n\n useEffect(() => {\n // Still loading auth — wait\n if (userProfileLoading) return\n\n // Tear down existing connection (if any) so we reconnect with new identity\n disconnect()\n\n // Connect if we have auth OR anonymous is allowed\n if (userProfileId || allowAnonymous) {\n connect()\n }\n\n return disconnect\n }, [userProfileId, userProfileLoading, allowAnonymous, connect, disconnect])\n\n // Reconnect on tab focus\n useEffect(() => {\n const onVisible = () => {\n if (document.visibilityState === 'visible' && wsRef.current?.readyState !== WebSocket.OPEN) {\n reconnectAttemptRef.current = 0\n connect()\n }\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n }, [connect])\n\n // ── Send helpers ─────────────────────────────────────────────────────\n\n const sendMessage = useCallback((message: { type: string; payload: unknown }) => {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message))\n }, [])\n\n const sendBinary = useCallback((data: Uint8Array) => {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) ws.send(data)\n }, [])\n\n const onBinaryMessage = useCallback((handler: (data: ArrayBuffer) => void) => {\n binaryHandlersRef.current.add(handler)\n return () => { binaryHandlersRef.current.delete(handler) }\n }, [])\n\n const registerYjsJoinHandler = useCallback((docKey: string, handler: (canWrite: boolean) => void) => {\n if (!yjsJoinHandlersRef.current.has(docKey)) yjsJoinHandlersRef.current.set(docKey, new Set())\n yjsJoinHandlersRef.current.get(docKey)!.add(handler)\n return () => {\n const handlers = yjsJoinHandlersRef.current.get(docKey)\n if (handlers) { handlers.delete(handler); if (handlers.size === 0) yjsJoinHandlersRef.current.delete(docKey) }\n }\n }, [])\n\n const sendConfirmed = useCallback((\n message: { type: string; payload: Record<string, unknown> },\n timeoutMs = 10000,\n ): Promise<unknown> => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return Promise.reject(new Error('WebSocket not connected'))\n const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequestsRef.current.delete(requestId)\n reject(new Error('Mutation confirmation timed out'))\n }, timeoutMs)\n pendingRequestsRef.current.set(requestId, { resolve, reject, timer })\n ws.send(JSON.stringify({ ...message, payload: { ...message.payload, requestId } }))\n })\n }, [])\n\n const setUserRole = useCallback((userId: string, role: string) => {\n sendMessage({ type: MSG.SET_ROLE, payload: { userId, role } })\n }, [sendMessage])\n\n const requestUserList = useCallback(() => {\n sendMessage({ type: MSG.USER_LIST, payload: {} })\n }, [sendMessage])\n\n const registerSubscription = useCallback((subscriptionId: string, queryKey: string) => {\n subscriptionMapRef.current.set(subscriptionId, queryKey)\n }, [])\n\n const unregisterSubscription = useCallback((subscriptionId: string) => {\n subscriptionMapRef.current.delete(subscriptionId)\n }, [])\n\n // Auto-discover schemas\n useEffect(() => {\n if (ready) sendMessage({ type: MSG.LIST_SCHEMAS, payload: {} })\n }, [ready, sendMessage])\n\n // ── ScopeRegistry ────────────────────────────────────────────────────\n\n const scopeEntryRef = useRef<ScopeEntry | null>(null)\n if (!scopeEntryRef.current) {\n scopeEntryRef.current = {\n store: storeRef.current, sendMessage, sendConfirmed,\n registerSubscription, unregisterSubscription, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, ready, status,\n }\n }\n scopeEntryRef.current.ready = ready\n scopeEntryRef.current.status = status\n\n const registeredSchemasRef = useRef<CollectionSchema[] | null>(null)\n if (!isolated && registry && schemas !== registeredSchemasRef.current) {\n if (registeredSchemasRef.current) {\n registry.unregister(scopeIdRef.current, registeredSchemasRef.current.map((s) => s.name))\n }\n const names = schemas.map((s) => s.name)\n if (names.length > 0) registry.register(scopeIdRef.current, names, scopeEntryRef.current!)\n registeredSchemasRef.current = schemas\n }\n\n useEffect(() => {\n if (isolated || !registry) return\n return () => {\n const names = (registeredSchemasRef.current ?? []).map((s) => s.name)\n if (names.length > 0) registry.unregister(scopeIdRef.current, names)\n }\n }, [isolated, registry, roomId])\n\n // ── Context ──────────────────────────────────────────────────────────\n\n const registeredCollections = useMemo(() => new Set(schemas.map((s) => s.name)), [schemas])\n\n const value: RecordContextValue = useMemo(() => ({\n store: storeRef.current, roomId, registeredCollections,\n userProfile: auth?.userProfile ?? null,\n userProfileLoading: auth?.userProfileLoading ?? false,\n refetchUserProfile: auth?.refetchUserProfile ?? (async () => {}),\n roomRole, allUsers, usersLoaded, status, ready, discoveredSchemas,\n setUserRole, requestUserList, registerSubscription, unregisterSubscription,\n sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, sendConfirmed,\n }), [\n roomId, registeredCollections, auth?.userProfile, auth?.userProfileLoading,\n auth?.refetchUserProfile, roomRole, allUsers, usersLoaded, status, ready,\n discoveredSchemas, setUserRole, requestUserList, registerSubscription,\n unregisterSubscription, sendMessage, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, sendConfirmed,\n ])\n\n if (!children) return null\n return <RecordContext.Provider value={value}>{children}</RecordContext.Provider>\n}\n\n// ============================================================================\n// RecordScope (public API)\n// ============================================================================\n\nexport function RecordScope({\n roomId,\n schemas,\n children,\n appId,\n sharedScopes,\n wsUrl,\n wsPathPrefix = '/ws',\n isolated = false,\n}: RecordScopeProps) {\n return (\n <>\n {sharedScopes?.map((shared) => (\n <HeadlessScope\n key={shared.roomId}\n roomId={shared.roomId}\n schemas={shared.schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n />\n ))}\n <ScopeConnection\n roomId={roomId}\n schemas={schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n isolated={isolated}\n >\n {children}\n </ScopeConnection>\n </>\n )\n}\n","/**\n * Shared WebSocket connection logger with active connection count.\n */\n\nlet activeCount = 0\n\nexport function wsLog(event: 'connecting' | 'connected' | 'disconnected' | 'closing', label: string) {\n if (event === 'connected') activeCount++\n if (event === 'closing') activeCount--\n\n console.log(`[ds:ws] ${event} → ${label} (${activeCount} active)`)\n}\n","/**\n * useUser Hook\n * \n * Access current user with profile data and room role.\n */\n\nimport { useMemo } from 'react'\nimport { useRecordContext } from '../context'\nimport type { User } from '../types'\n\n/**\n * Hook to access current user.\n * \n * Returns merged user data:\n * - Profile from API (karma, credits, subscription, isAdmin)\n * - Role from room (derived from user-roles collection)\n * \n * The role is the user's role in THIS miniapp/room, which can be\n * different from their global isAdmin status.\n * \n * @example\n * ```tsx\n * const { user, refetch, isLoading } = useUser()\n * \n * // Check role\n * if (user?.role === 'admin') { ... }\n * if (user?.role === 'intern') { ... }\n * \n * // Access karma/credits\n * const karma = user?.karma?.total ?? 0\n * \n * // Refetch after expensive operations\n * await refetch() // Updates user.credits\n * ```\n */\nexport function useUser(): {\n user: User | null\n isLoading: boolean\n refetch: () => Promise<void>\n} {\n const { userProfile, userProfileLoading, refetchUserProfile, roomRole } = useRecordContext()\n \n // Merge profile + room role into unified User\n const user = useMemo((): User | null => {\n if (!userProfile) return null\n return {\n ...userProfile,\n role: roomRole ?? 'viewer', // Default to 'viewer' if no role set\n }\n }, [userProfile, roomRole])\n \n return { user, isLoading: userProfileLoading, refetch: refetchUserProfile }\n}\n","/**\n * useQuery Hook\n *\n * Subscribe to a query with real-time updates.\n * Resolves the correct scope via ScopeRegistry (multi-scope)\n * or falls back to useRecordContext() (single-scope backward compat).\n */\n\nimport { useEffect, useCallback, useRef, useMemo, useContext, useSyncExternalStore } from 'react'\nimport { RecordContext } from '../context'\nimport { useScopeRegistry } from '../ScopeRegistry'\nimport type { Query, RecordData } from '../types'\nimport { MSG } from '@/shared/protocol/constants'\n\n/**\n * Subscribe to a query with real-time updates.\n *\n * @example\n * ```tsx\n * const { records, status } = useQuery('tasks', {\n * where: { userId: me },\n * orderBy: 'createdAt',\n * orderDir: 'desc',\n * limit: 50\n * })\n * ```\n */\nexport function useQuery<T = unknown>(\n collection: string,\n options?: {\n where?: Record<string, unknown>\n orderBy?: string\n orderDir?: 'asc' | 'desc'\n limit?: number\n },\n): {\n records: RecordData<T>[]\n status: 'loading' | 'ready' | 'error'\n error?: string\n} {\n // Try scope resolution first (multi-scope), then fall back to RecordContext\n const registry = useScopeRegistry()\n const recordCtx = useContext(RecordContext)\n\n const scopeEntry = registry?.resolve(collection) ?? null\n\n // Prefer RecordContext when this scope handles the collection (avoids stale ScopeRegistry during navigation)\n const preferLocal = recordCtx?.registeredCollections?.has(collection) ?? false\n const store = preferLocal ? recordCtx!.store : (scopeEntry?.store ?? recordCtx?.store)\n const sendMessage = preferLocal ? recordCtx!.sendMessage : (scopeEntry?.sendMessage ?? recordCtx?.sendMessage)\n const registerSub = preferLocal ? recordCtx!.registerSubscription : (scopeEntry?.registerSubscription ?? recordCtx?.registerSubscription)\n const unregisterSub = preferLocal ? recordCtx!.unregisterSubscription : (scopeEntry?.unregisterSubscription ?? recordCtx?.unregisterSubscription)\n\n if (!store || !sendMessage || !registerSub || !unregisterSub) {\n throw new Error(\n `useQuery('${collection}'): No scope found. Wrap in a RecordProvider (with roomId) or a RecordScope that registers this collection.`,\n )\n }\n\n const optionsKey = JSON.stringify(options ?? null)\n\n const query: Query = useMemo(\n () => ({\n collection,\n where: options?.where,\n orderBy: options?.orderBy,\n orderDir: options?.orderDir,\n limit: options?.limit,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }),\n [collection, optionsKey],\n )\n\n const queryKey = useMemo(() => JSON.stringify(query), [query])\n\n const subscriptionIdRef = useRef<string>(\n `sub-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n )\n\n useEffect(() => {\n const subscriptionId = subscriptionIdRef.current\n\n const isFirst = store.initQuery(queryKey)\n\n if (isFirst) {\n store.setSubscriptionId(queryKey, subscriptionId)\n registerSub(subscriptionId, queryKey)\n sendMessage({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } })\n }\n\n return () => {\n const activeSubId = store.getSubscriptionId(queryKey) ?? subscriptionId\n const isLast = store.releaseQuery(queryKey)\n\n if (isLast) {\n sendMessage({ type: MSG.UNSUBSCRIBE, payload: { subscriptionId: activeSubId } })\n unregisterSub(activeSubId)\n }\n }\n }, [queryKey, query, store, sendMessage, registerSub, unregisterSub, collection])\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => store.subscribe(queryKey, onStoreChange),\n [store, queryKey],\n )\n\n const getSnapshot = useCallback(\n () => store.getSnapshot(queryKey) as RecordData<T>[],\n [store, queryKey],\n )\n\n const records = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n const status = store.getStatus(queryKey)\n const error = store.getError(queryKey)\n\n // Memoize the return object so consumers get a stable reference\n // (same rationale as useMutations — prevents spurious effect re-runs).\n return useMemo(() => ({ records, status, error }), [records, status, error])\n}\n","/**\n * useMutations Hook\n *\n * Get mutation functions for a collection.\n * Resolves the correct scope via ScopeRegistry (multi-scope)\n * or falls back to useRecordContext() (single-scope backward compat).\n */\n\nimport { useCallback, useContext, useMemo } from 'react'\nimport { RecordContext } from '../context'\nimport { useScopeRegistry } from '../ScopeRegistry'\nimport { MSG } from '@/shared/protocol/constants'\n\n/**\n * Get mutation functions for a collection.\n *\n * Type contract:\n * - `create(data)` requires the **full** record shape `T`. New records\n * have no existing data to merge with, so all fields the schema\n * considers required must be present.\n * - `put(recordId, patch)` accepts a **`Partial<T>`**. The server\n * merges the patch into the existing row (`{...existing, ...patch}`),\n * so callers should send only the fields they want to change.\n *\n * @example\n * ```tsx\n * const { create, put, remove } = useMutations<Task>('tasks')\n *\n * // create needs the full Task shape\n * const id = await create({ title: 'New task', completed: false, priority: 1 })\n *\n * // put is a partial update — only the fields you want to change\n * await put(id, { completed: true })\n * await remove(id)\n * ```\n */\nexport function useMutations<T = unknown>(collection: string): {\n create: (data: T) => Promise<string>\n put: (recordId: string, data: Partial<T>) => Promise<void>\n remove: (recordId: string) => Promise<void>\n createConfirmed: (data: T) => Promise<string>\n putConfirmed: (recordId: string, data: Partial<T>) => Promise<void>\n removeConfirmed: (recordId: string) => Promise<void>\n} {\n // Try scope resolution first (multi-scope), then fall back to RecordContext\n const registry = useScopeRegistry()\n const recordCtx = useContext(RecordContext)\n\n const scopeEntry = registry?.resolve(collection) ?? null\n\n // Prefer RecordContext when this scope handles the collection (avoids stale ScopeRegistry during navigation)\n const preferLocal = recordCtx?.registeredCollections?.has(collection) ?? false\n const sendMessage = preferLocal ? recordCtx!.sendMessage : (scopeEntry?.sendMessage ?? recordCtx?.sendMessage)\n const sendConfirmed = preferLocal ? recordCtx!.sendConfirmed : (scopeEntry?.sendConfirmed ?? recordCtx?.sendConfirmed)\n\n if (!sendMessage || !sendConfirmed) {\n throw new Error(\n `useMutations('${collection}'): No scope found. Wrap in a RecordProvider (with roomId) or a RecordScope that registers this collection.`,\n )\n }\n\n const create = useCallback(\n async (data: T): Promise<string> => {\n const recordId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n sendMessage({ type: MSG.PUT, payload: { collection, recordId, data } })\n return recordId\n },\n [sendMessage, collection],\n )\n\n const put = useCallback(\n async (recordId: string, data: Partial<T>): Promise<void> => {\n sendMessage({ type: MSG.PUT, payload: { collection, recordId, data } })\n },\n [sendMessage, collection],\n )\n\n const remove = useCallback(\n async (recordId: string): Promise<void> => {\n sendMessage({ type: MSG.DELETE, payload: { collection, recordId } })\n },\n [sendMessage, collection],\n )\n\n const createConfirmed = useCallback(\n async (data: T): Promise<string> => {\n const recordId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n await sendConfirmed({\n type: MSG.PUT,\n payload: { collection, recordId, data: data as Record<string, unknown> },\n })\n return recordId\n },\n [sendConfirmed, collection],\n )\n\n const putConfirmed = useCallback(\n async (recordId: string, data: Partial<T>): Promise<void> => {\n await sendConfirmed({\n type: MSG.PUT,\n payload: { collection, recordId, data: data as Record<string, unknown> },\n })\n },\n [sendConfirmed, collection],\n )\n\n const removeConfirmed = useCallback(\n async (recordId: string): Promise<void> => {\n await sendConfirmed({ type: MSG.DELETE, payload: { collection, recordId } })\n },\n [sendConfirmed, collection],\n )\n\n // Memoize the return object so consumers get a stable reference.\n // Without this, every render produces a new object, which breaks any\n // useCallback/useEffect that depends on the useMutations() result\n // (e.g., cleanup effects re-fire and delete records they shouldn't).\n return useMemo(\n () => ({ create, put, remove, createConfirmed, putConfirmed, removeConfirmed }),\n [create, put, remove, createConfirmed, putConfirmed, removeConfirmed],\n )\n}\n","/**\n * useUsers Hook\n *\n * Access all users in the current room.\n * User data (name, email, imageUrl, role) comes from the RecordRoom's users collection.\n */\n\nimport { useEffect, useMemo } from 'react'\nimport { useRecordContext } from '../context'\nimport type { RoomUser } from '../types'\n\nexport function useUsers(): {\n users: RoomUser[]\n usersLoaded: boolean\n setRole: (userId: string, role: string) => void\n refresh: () => void\n} {\n const { allUsers, usersLoaded, setUserRole, requestUserList, ready } = useRecordContext()\n\n useEffect(() => {\n if (ready) requestUserList()\n }, [ready, requestUserList])\n\n const users = useMemo(() => allUsers, [allUsers])\n\n return { users, usersLoaded, setRole: setUserRole, refresh: requestUserList }\n}\n","/**\n * Yjs Collaborative Editing Hooks\n * \n * Real-time collaborative editing using Yjs.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport * as Y from 'yjs'\nimport { useRecordContext } from '../context'\nimport { MSG_YJS_SYNC, MSG_YJS_AWARENESS, MSG } from '@/shared/protocol/constants'\nimport {\n MSG_SYNC_STEP1,\n MSG_SYNC_STEP2,\n MSG_SYNC_UPDATE,\n Awareness,\n createEncoder,\n createDecoder,\n toUint8Array,\n writeVarUint,\n writeVarUint8Array,\n readVarUint,\n readVarUint8Array,\n} from '@/shared/protocol/yjs'\n\n// ============================================================================\n// useYjsField\n// ============================================================================\n\nexport interface UseYjsFieldResult {\n /** The Yjs document for this field */\n doc: Y.Doc\n /** Awareness instance for cursor/presence sync */\n awareness: Awareness\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n /** Force re-render counter (changes when doc updates) */\n updateCount: number\n}\n\n/**\n * Hook for collaborative editing of a Yjs field.\n * \n * @param collection - Collection name\n * @param recordId - Record ID\n * @param fieldName - Field name (must be type: 'yjs' in schema)\n * \n * @example\n * const { doc, synced, canWrite } = useYjsField('documents', docId, 'content')\n * const text = doc.getText('content')\n */\nexport function useYjsField(\n collection: string,\n recordId: string,\n fieldName: string\n): UseYjsFieldResult {\n const { sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, ready } = useRecordContext()\n const [synced, setSynced] = useState(false)\n const [canWrite, setCanWrite] = useState(false)\n const [updateCount, setUpdateCount] = useState(0)\n const canWriteRef = useRef(false)\n\n // Stable Yjs doc instance\n const docRef = useRef<Y.Doc | null>(null)\n if (!docRef.current) {\n docRef.current = new Y.Doc()\n }\n const doc = docRef.current\n\n // Stable awareness instance (one per doc)\n const awarenessRef = useRef<Awareness | null>(null)\n if (!awarenessRef.current) {\n awarenessRef.current = new Awareness(doc)\n }\n const awareness = awarenessRef.current\n\n const docKey = `${collection}:${recordId}:${fieldName}`\n\n // Keep ref in sync with state for use in callbacks\n useEffect(() => {\n canWriteRef.current = canWrite\n }, [canWrite])\n\n // Handle join response from server\n useEffect(() => {\n return registerYjsJoinHandler(docKey, setCanWrite)\n }, [docKey, registerYjsJoinHandler])\n\n // Handle incoming binary messages (sync + awareness)\n useEffect(() => {\n const handleBinaryMessage = (data: ArrayBuffer) => {\n const decoder = createDecoder(new Uint8Array(data))\n const messageType = readVarUint(decoder)\n\n // Handle awareness messages\n if (messageType === MSG_YJS_AWARENESS) {\n const msgDocKey = new TextDecoder().decode(readVarUint8Array(decoder))\n if (msgDocKey !== docKey) return\n const payload = readVarUint8Array(decoder)\n awareness.applyUpdate(payload)\n return\n }\n\n if (messageType !== MSG_YJS_SYNC) return\n\n const msgDocKey = new TextDecoder().decode(readVarUint8Array(decoder))\n if (msgDocKey !== docKey) return\n\n const syncType = readVarUint(decoder)\n const payload = readVarUint8Array(decoder)\n\n switch (syncType) {\n case MSG_SYNC_STEP1: {\n // Server sent state vector - respond with our diff\n const ourDiff = Y.encodeStateAsUpdate(doc, payload)\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_SYNC)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint(encoder, MSG_SYNC_STEP2)\n writeVarUint8Array(encoder, ourDiff)\n sendBinary(toUint8Array(encoder))\n setSynced(true)\n break\n }\n case MSG_SYNC_STEP2: {\n // Server sent full state diff\n Y.applyUpdate(doc, payload, 'server')\n setSynced(true)\n break\n }\n case MSG_SYNC_UPDATE: {\n // Server relayed update from another client\n Y.applyUpdate(doc, payload, 'server')\n break\n }\n }\n }\n\n return onBinaryMessage(handleBinaryMessage)\n }, [doc, awareness, docKey, sendBinary, onBinaryMessage])\n\n // Send local awareness changes to server\n useEffect(() => {\n if (!ready) return\n\n const handleAwarenessUpdate = ({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {\n const changedClients = added.concat(updated).concat(removed)\n if (changedClients.length === 0) return\n\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_AWARENESS)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint8Array(encoder, awareness.encodeUpdate(changedClients))\n sendBinary(toUint8Array(encoder))\n }\n\n awareness.on('update', handleAwarenessUpdate)\n return () => { awareness.off('update', handleAwarenessUpdate) }\n }, [awareness, docKey, sendBinary, ready])\n\n // Join channel when ready - re-join on reconnect\n useEffect(() => {\n if (!ready) {\n // Reset state when disconnected\n console.log('[YJS] Not ready, resetting:', docKey)\n setSynced(false)\n setCanWrite(false)\n return\n }\n\n console.log('[YJS] Joining:', docKey)\n sendMessage({ type: MSG.YJS_JOIN, payload: { collection, recordId, fieldName } })\n\n return () => {\n // Clear local awareness state before leaving\n awareness.setLocalState(null)\n console.log('[YJS] Leaving:', docKey)\n sendMessage({ type: MSG.YJS_LEAVE, payload: { collection, recordId, fieldName } })\n }\n }, [ready, collection, recordId, fieldName, sendMessage, docKey, awareness])\n\n // Send local updates to server\n useEffect(() => {\n const handleUpdate = (update: Uint8Array, origin: unknown) => {\n setUpdateCount(c => c + 1)\n\n // Only send local updates when we have write permission\n if (origin === 'server' || !canWriteRef.current) return\n\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_SYNC)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint(encoder, MSG_SYNC_UPDATE)\n writeVarUint8Array(encoder, update)\n sendBinary(toUint8Array(encoder))\n }\n\n doc.on('update', handleUpdate)\n return () => { doc.off('update', handleUpdate) }\n }, [doc, docKey, sendBinary])\n\n // synced is only true when WebSocket is connected AND initial sync is complete\n return { doc, awareness, synced: ready && synced, canWrite, updateCount }\n}\n\n// ============================================================================\n// useYjsText\n// ============================================================================\n\nexport interface UseYjsTextResult {\n /** Current text content */\n text: string\n /** Set text content (replaces entire content) */\n setText: (value: string) => void\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n}\n\n/**\n * Simplified hook for collaborative text editing.\n * \n * Provides a string-based API instead of raw Yjs doc access.\n * Perfect for textarea/input fields.\n * \n * @param collection - Collection name\n * @param recordId - Record ID\n * @param fieldName - Field name (must be type: 'yjs' in schema)\n * \n * @example\n * const { text, setText, synced, canWrite } = useYjsText('documents', docId, 'content')\n * \n * <textarea \n * value={text} \n * onChange={(e) => setText(e.target.value)}\n * disabled={!synced || !canWrite}\n * />\n */\nexport function useYjsText(\n collection: string,\n recordId: string,\n fieldName: string\n): UseYjsTextResult {\n const { doc, synced, canWrite, updateCount } = useYjsField(collection, recordId, fieldName)\n const [text, setTextState] = useState('')\n const yTextRef = useRef<Y.Text | null>(null)\n const isLocalUpdateRef = useRef(false)\n\n // Get Y.Text instance once doc is ready\n useEffect(() => {\n yTextRef.current = doc.getText(fieldName)\n }, [doc, fieldName])\n\n // Sync Y.Text to local state when doc updates\n useEffect(() => {\n if (yTextRef.current && synced && !isLocalUpdateRef.current) {\n setTextState(yTextRef.current.toString())\n }\n isLocalUpdateRef.current = false\n }, [synced, updateCount])\n\n // setText function that updates both local state and Yjs\n const setText = useCallback((value: string) => {\n setTextState(value)\n \n if (yTextRef.current && canWrite) {\n isLocalUpdateRef.current = true\n doc.transact(() => {\n const yText = yTextRef.current!\n yText.delete(0, yText.length)\n yText.insert(0, value)\n })\n }\n }, [doc, canWrite])\n\n return { text, setText, synced, canWrite }\n}\n","/**\n * useUserLookup Hook\n * \n * Provides helper functions to look up user information by userId.\n * This is a convenience wrapper around useUsers() that provides O(1) lookups.\n * \n * The authoritative user data comes from the users collection.\n */\n\nimport { useMemo, useCallback } from 'react'\nimport { useUsers } from './useUsers'\n\nexport interface UserInfo {\n id: string\n email: string\n name: string\n imageUrl?: string\n role: string\n}\n\n/**\n * Hook for looking up user information by ID.\n * \n * @example\n * ```tsx\n * const { getUser, getEmail, getName } = useUserLookup()\n * \n * // Get full user info\n * const user = getUser(userId)\n * \n * // Get just email\n * const email = getEmail(userId)\n * ```\n */\nexport function useUserLookup() {\n const { users, usersLoaded } = useUsers()\n \n // Build a lookup map for O(1) access\n const userMap = useMemo(() => {\n const map = new Map<string, UserInfo>()\n for (const user of users) {\n map.set(user.id, {\n id: user.id,\n email: user.email,\n name: user.name,\n imageUrl: user.imageUrl,\n role: user.role,\n })\n }\n return map\n }, [users])\n \n /**\n * Get full user info by userId\n */\n const getUser = useCallback((userId: string): UserInfo | null => {\n return userMap.get(userId) ?? null\n }, [userMap])\n \n /**\n * Get user's email by userId\n */\n const getEmail = useCallback((userId: string): string | null => {\n return userMap.get(userId)?.email ?? null\n }, [userMap])\n \n /**\n * Get user's name by userId\n */\n const getName = useCallback((userId: string): string | null => {\n return userMap.get(userId)?.name ?? null\n }, [userMap])\n \n return {\n /** All users from the users collection */\n users,\n /** True once the user list has been received from the server. */\n usersLoaded,\n /** Map of userId -> UserInfo for direct access */\n userMap,\n /** Get full user info by userId */\n getUser,\n /** Get user email by userId */\n getEmail,\n /** Get user name by userId */\n getName,\n }\n}\n","/**\n * usePresence — Derives online/offline from lastSeenAt in users collection.\n *\n * Two mechanisms keep presence working:\n * 1. Heartbeat: Sends MSG.USER_UPDATE every 60s so the server refreshes\n * our lastSeenAt in the c_users table and broadcasts the change.\n * 2. Tick: A re-render trigger every 30s so isOnline() re-evaluates\n * Date.now() and users who stopped heartbeating transition to offline.\n */\n\nimport { useEffect, useCallback, useState } from 'react'\nimport { useUser } from './useUser'\nimport { useUsers } from './useUsers'\nimport { useRecordContext } from '../context'\nimport { MSG } from '@/shared/protocol/constants'\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nconst HEARTBEAT_INTERVAL_MS = 60 * 1000 // 1 minute\nconst TICK_INTERVAL_MS = 30 * 1000 // 30 seconds\n\ninterface UsePresenceOptions {\n timeoutMs?: number\n}\n\nexport function usePresence(opts?: UsePresenceOptions) {\n const { user } = useUser()\n const { users } = useUsers()\n const { sendMessage, ready } = useRecordContext()\n const [tick, setTick] = useState(0)\n\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n // Heartbeat: periodically send MSG.USER_UPDATE to refresh our lastSeenAt\n useEffect(() => {\n if (!user || !ready) return\n const interval = setInterval(() => {\n sendMessage({ type: MSG.USER_UPDATE, payload: {} })\n }, HEARTBEAT_INTERVAL_MS)\n return () => clearInterval(interval)\n }, [user, ready, sendMessage])\n\n // Tick: force re-render so isOnline() re-evaluates stale timestamps\n useEffect(() => {\n const interval = setInterval(() => {\n setTick((t) => t + 1)\n }, TICK_INTERVAL_MS)\n return () => clearInterval(interval)\n }, [])\n\n const isOnline = useCallback(\n (userId: string): boolean => {\n // tick is captured to ensure this callback refreshes on each tick\n void tick\n const u = users.find((u) => u.id === userId)\n if (!u?.lastSeenAt) return false\n return Date.now() - new Date(u.lastSeenAt).getTime() < timeoutMs\n },\n [users, timeoutMs, tick],\n )\n\n const getLastSeen = useCallback(\n (userId: string): string | null => {\n const u = users.find((u) => u.id === userId)\n return u?.lastSeenAt ?? null\n },\n [users],\n )\n\n return { isOnline, getLastSeen, users }\n}\n","/**\n * useYjsRoom — Connect to a dedicated YjsRoom Durable Object.\n *\n * Unlike useYjsField (which piggybacks on RecordRoom's WebSocket),\n * this hook opens a direct WebSocket to a YjsRoom DO at /ws/yjs/:docId.\n * Each document gets its own DO for horizontal scaling.\n *\n * Uses the shared yjs-protocol.ts encoding — no duplication.\n *\n * @example\n * const { doc, text, setText, synced, canWrite } = useYjsRoom(docId, 'content')\n */\n\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react'\nimport * as Y from 'yjs'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport {\n MSG_AWARENESS,\n MSG_SYNC,\n MSG_SYNC_STEP1,\n MSG_SYNC_STEP2,\n MSG_SYNC_UPDATE,\n Awareness,\n createEncoder,\n createDecoder,\n toUint8Array,\n encodeAwarenessMessage,\n handleAwarenessMessage,\n writeVarUint,\n writeVarUint8Array,\n readVarUint,\n readVarUint8Array,\n} from '@/shared/protocol/yjs'\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport interface UseYjsRoomResult {\n /** The Yjs document */\n doc: Y.Doc\n /** Awareness instance for presence/typing state */\n awareness: Awareness\n /** Current text content (for the specified field) */\n text: string\n /** Set text (replaces full content) */\n setText: (value: string) => void\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n}\n\n/**\n * Connect to a YjsRoom DO for collaborative editing.\n *\n * @param docId - Document identifier (maps to DO name)\n * @param fieldName - Y.Text field name within the Y.Doc\n */\nexport function useYjsRoom(docId: string, fieldName: string): UseYjsRoomResult {\n const [synced, setSynced] = useState(false)\n const [canWrite, setCanWrite] = useState(false)\n const [text, setTextState] = useState('')\n const [, setUpdateCount] = useState(0)\n\n const docRef = useRef<Y.Doc | null>(null)\n if (!docRef.current) docRef.current = new Y.Doc()\n const doc = docRef.current\n\n const awarenessRef = useRef<Awareness | null>(null)\n if (!awarenessRef.current) awarenessRef.current = new Awareness(doc)\n const awareness = awarenessRef.current\n\n const wsRef = useRef<WebSocket | null>(null)\n const isLocalRef = useRef(false)\n const applyingRemoteAwarenessRef = useRef(false)\n\n const yText = useMemo(() => doc.getText(fieldName), [doc, fieldName])\n\n // Observe remote Y.Text changes\n useEffect(() => {\n const observer = () => {\n if (isLocalRef.current) return\n setTextState(yText.toString())\n }\n yText.observe(observer)\n return () => yText.unobserve(observer)\n }, [yText])\n\n // WebSocket connection to YjsRoom DO\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/yjs/${encodeURIComponent(docId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `yjs:${docId}`)\n ws = new WebSocket(url.toString())\n ws.binaryType = 'arraybuffer'\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `yjs:${docId}`)\n setSynced(false)\n }\n\n ws.onmessage = (event) => {\n if (typeof event.data === 'string') {\n try {\n const msg = JSON.parse(event.data) as { type?: string; canWrite?: unknown }\n if (msg.type === 'auth' && typeof msg.canWrite === 'boolean') setCanWrite(msg.canWrite)\n } catch {\n /* ignore */\n }\n return\n }\n\n const data = new Uint8Array(event.data as ArrayBuffer)\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n\n if (messageType === MSG_SYNC) {\n const syncType = readVarUint(decoder)\n const payload = readVarUint8Array(decoder)\n\n switch (syncType) {\n case MSG_SYNC_STEP1: {\n const diff = Y.encodeStateAsUpdate(doc, payload)\n const enc = createEncoder()\n writeVarUint(enc, MSG_SYNC)\n writeVarUint(enc, MSG_SYNC_STEP2)\n writeVarUint8Array(enc, diff)\n ws?.send(toUint8Array(enc).buffer)\n setSynced(true)\n break\n }\n case MSG_SYNC_STEP2: {\n Y.applyUpdate(doc, payload, 'server')\n setTextState(yText.toString())\n setSynced(true)\n break\n }\n case MSG_SYNC_UPDATE: {\n Y.applyUpdate(doc, payload, 'server')\n setUpdateCount((c) => c + 1)\n break\n }\n }\n return\n }\n\n if (messageType === MSG_AWARENESS) {\n applyingRemoteAwarenessRef.current = true\n try {\n handleAwarenessMessage(awareness, data)\n } finally {\n applyingRemoteAwarenessRef.current = false\n }\n }\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `yjs:${docId}`)\n wsRef.current = null\n setSynced(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `yjs:${docId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [doc, awareness, docId, yText])\n\n // Relay local awareness updates (presence, typing) through YjsRoom with shared MSG_AWARENESS encoding.\n useEffect(() => {\n const handler = ({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {\n if (applyingRemoteAwarenessRef.current) return\n const changedClients = added.concat(updated).concat(removed)\n if (changedClients.length === 0) return\n\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n\n ws.send(encodeAwarenessMessage(awareness, changedClients).buffer)\n }\n\n awareness.on('update', handler)\n return () => {\n awareness.off('update', handler)\n awareness.setLocalState(null)\n }\n }, [awareness])\n\n // Send local Y.Doc updates to server\n useEffect(() => {\n const handler = (update: Uint8Array, origin: unknown) => {\n if (origin === 'server') return\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n\n const enc = createEncoder()\n writeVarUint(enc, MSG_SYNC)\n writeVarUint(enc, MSG_SYNC_UPDATE)\n writeVarUint8Array(enc, update)\n ws.send(toUint8Array(enc).buffer)\n }\n\n doc.on('update', handler)\n return () => { doc.off('update', handler) }\n }, [doc])\n\n // setText: update Y.Text + local state\n const setText = useCallback((value: string) => {\n setTextState(value)\n if (!canWrite) return\n\n isLocalRef.current = true\n doc.transact(() => {\n yText.delete(0, yText.length)\n yText.insert(0, value)\n })\n isLocalRef.current = false\n }, [doc, yText, canWrite])\n\n return { doc, awareness, text, setText, synced, canWrite }\n}\n","/**\n * useGameRoom — Connect to a GameRoom Durable Object.\n *\n * Opens a WebSocket to /ws/game/:roomId for real-time game state.\n *\n * @example\n * const { state, sendInput, players, connected } = useGameRoom('my-game')\n *\n * Implementation note: this hook uses the typed wire protocol helpers\n * (`clientBuild` for sends, `dispatch` for receives) from\n * `shared/protocol/messages`. Hand-rolled `switch (msg.type)` blocks and\n * raw `JSON.stringify({ type: MSG.X, payload: ... })` sends are a fast\n * route to the \"silent drop\" bug class when a payload shape drifts —\n * prefer the typed helpers instead.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface GamePlayer {\n userId: string\n userName: string\n ready: boolean\n connectedAt: string\n data: Record<string, unknown>\n}\n\nexport interface UseGameRoomResult {\n /** Current game state */\n state: Record<string, unknown>\n /** Current tick number */\n tick: number\n /** Connected players */\n players: GamePlayer[]\n /** Whether the game is currently running */\n running: boolean\n /** Whether WebSocket is connected */\n connected: boolean\n /** Send a game input */\n sendInput: (action: string, data?: Record<string, unknown>) => void\n /** Mark self as ready */\n setReady: () => void\n /** Request game start */\n startGame: () => void\n /** Request game end */\n endGame: () => void\n}\n\nexport function useGameRoom(roomId: string): UseGameRoomResult {\n const [gameState, setGameState] = useState<Record<string, unknown>>({})\n const [tick, setTick] = useState(0)\n const [players, setPlayers] = useState<GamePlayer[]>([])\n const [running, setRunning] = useState(false)\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/game/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `game:${roomId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `game:${roomId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.GAME_STATE]: (p) => {\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n setPlayers(p.players as GamePlayer[])\n setRunning(p.running)\n },\n [MSG.GAME_TICK]: (p) => {\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n },\n [MSG.GAME_PLAYER_JOIN]: (p) => {\n const player = p.player as GamePlayer\n setPlayers((prev) => [...prev.filter((x) => x.userId !== player.userId), player])\n },\n [MSG.GAME_PLAYER_LEAVE]: (p) => {\n setPlayers((prev) => prev.filter((x) => x.userId !== p.userId))\n },\n [MSG.GAME_PLAYER_READY]: (p) => {\n setPlayers((prev) =>\n prev.map((x) => (x.userId === p.userId ? { ...x, ready: true } : x)),\n )\n },\n [MSG.GAME_START]: (p) => {\n setRunning(true)\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n },\n [MSG.GAME_END]: (p) => {\n setRunning(false)\n setGameState(p.state as Record<string, unknown>)\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `game:${roomId}`)\n wsRef.current = null\n setConnected(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `game:${roomId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [roomId])\n\n const sendInput = useCallback((action: string, data: Record<string, unknown> = {}) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.gameInput(action, data)))\n }, [])\n\n const setReady = useCallback(() => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.gamePlayerReady()))\n }, [])\n\n const startGame = useCallback(() => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.gameStart()))\n }, [])\n\n const endGame = useCallback(() => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.gameEnd()))\n }, [])\n\n return { state: gameState, tick, players, running, connected, sendInput, setReady, startGame, endGame }\n}\n","/**\n * useCanvas — Connect to a CanvasRoom Durable Object.\n *\n * Opens a WebSocket to /ws/canvas/:roomId for collaborative spatial editing.\n *\n * @example\n * const { shapes, addShape, moveShape, deleteShape, viewports } = useCanvas('my-canvas')\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface CanvasShapeClient {\n id: string\n type: string\n x: number\n y: number\n width: number\n height: number\n rotation?: number\n props: Record<string, unknown>\n createdBy: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface ViewportClient {\n userId: string\n x: number\n y: number\n width: number\n height: number\n zoom: number\n}\n\nexport interface UseCanvasResult {\n /** All shapes on the canvas */\n shapes: CanvasShapeClient[]\n /** Other users' viewports */\n viewports: ViewportClient[]\n /** Whether WebSocket is connected */\n connected: boolean\n /** Add a shape */\n addShape: (shape: Partial<CanvasShapeClient>) => void\n /** Move a shape */\n moveShape: (shapeId: string, x: number, y: number) => void\n /** Resize a shape */\n resizeShape: (shapeId: string, width: number, height: number, x?: number, y?: number) => void\n /** Delete a shape */\n deleteShape: (shapeId: string) => void\n /** Update shape properties */\n updateShape: (shapeId: string, props: Record<string, unknown>) => void\n /** Report local viewport */\n setViewport: (viewport: Omit<ViewportClient, 'userId'>) => void\n /** Undo last action */\n undo: () => void\n /** Redo last undone action */\n redo: () => void\n}\n\nexport function useCanvas(roomId: string): UseCanvasResult {\n const [shapes, setShapes] = useState<CanvasShapeClient[]>([])\n const [viewports, setViewports] = useState<ViewportClient[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/canvas/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `canvas:${roomId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `canvas:${roomId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n // Typed dispatch — handler payloads are narrowed by the SDK's\n // discriminated `ServerMessage` union. Shape/viewport objects\n // on the wire are typed as `unknown` (the protocol layer\n // doesn't know the app's domain types), so we cast to the\n // local `CanvasShapeClient` / `ViewportClient` where we use\n // them.\n dispatch<ServerMessage>(event.data, {\n [MSG.CANVAS_SHAPES]: (p) => {\n setShapes(p.shapes as CanvasShapeClient[])\n setViewports(p.viewports as ViewportClient[])\n },\n [MSG.CANVAS_ADD]: (p) => {\n const shape = p.shape as CanvasShapeClient\n setShapes((prev) => [...prev.filter((s) => s.id !== shape.id), shape])\n },\n [MSG.CANVAS_MOVE]: (p) => {\n setShapes((prev) =>\n prev.map((s) => (s.id === p.shapeId ? { ...s, x: p.x, y: p.y } : s)),\n )\n },\n [MSG.CANVAS_RESIZE]: (p) => {\n setShapes((prev) =>\n prev.map((s) => {\n if (s.id !== p.shapeId) return s\n const updated = { ...s, width: p.width, height: p.height }\n if (p.x !== undefined) updated.x = p.x\n if (p.y !== undefined) updated.y = p.y\n return updated\n }),\n )\n },\n [MSG.CANVAS_DELETE]: (p) => {\n setShapes((prev) => prev.filter((s) => s.id !== p.shapeId))\n },\n [MSG.CANVAS_UPDATE]: (p) => {\n setShapes((prev) =>\n prev.map((s) =>\n s.id === p.shapeId ? { ...s, props: { ...s.props, ...p.props } } : s,\n ),\n )\n },\n [MSG.CANVAS_VIEWPORT]: (p) => {\n // The payload is a union of `{ viewport }` and\n // `{ userId, removed: true }` — narrow by presence.\n if ('removed' in p) {\n const removed = p\n setViewports((prev) => prev.filter((v) => v.userId !== removed.userId))\n } else {\n const viewport = p.viewport as ViewportClient\n setViewports((prev) => [\n ...prev.filter((v) => v.userId !== viewport.userId),\n viewport,\n ])\n }\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `canvas:${roomId}`)\n wsRef.current = null\n setConnected(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `canvas:${roomId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [roomId])\n\n // Typed builders — `clientBuild.canvasX` returns a validated\n // `ClientMessage` that `encode` stringifies. No hand-rolled\n // `JSON.stringify({ type, payload })` calls here.\n const sendBuilt = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [],\n )\n\n const addShape = useCallback(\n (shape: Partial<CanvasShapeClient>) => sendBuilt(clientBuild.canvasAdd(shape)),\n [sendBuilt],\n )\n\n const moveShape = useCallback(\n (shapeId: string, x: number, y: number) =>\n sendBuilt(clientBuild.canvasMove(shapeId, x, y)),\n [sendBuilt],\n )\n\n const resizeShape = useCallback(\n (shapeId: string, width: number, height: number, x?: number, y?: number) =>\n sendBuilt(clientBuild.canvasResize(shapeId, width, height, x, y)),\n [sendBuilt],\n )\n\n const deleteShape = useCallback(\n (shapeId: string) => sendBuilt(clientBuild.canvasDelete(shapeId)),\n [sendBuilt],\n )\n\n const updateShape = useCallback(\n (shapeId: string, props: Record<string, unknown>) =>\n sendBuilt(clientBuild.canvasUpdate(shapeId, props)),\n [sendBuilt],\n )\n\n const setViewport = useCallback(\n (viewport: Omit<ViewportClient, 'userId'>) =>\n sendBuilt(clientBuild.canvasViewport(viewport)),\n [sendBuilt],\n )\n\n const undo = useCallback(() => sendBuilt(clientBuild.canvasUndo()), [sendBuilt])\n const redo = useCallback(() => sendBuilt(clientBuild.canvasRedo()), [sendBuilt])\n\n return { shapes, viewports, connected, addShape, moveShape, resizeShape, deleteShape, updateShape, setViewport, undo, redo }\n}\n","/**\n * useCronMonitor — Connect to a CronRoom for monitoring scheduled tasks.\n *\n * Opens a WebSocket to /cron/:roomId for real-time task status.\n *\n * @example\n * const { tasks, history, trigger, pause, resume } = useCronMonitor('cron')\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface CronTaskState {\n name: string\n intervalMinutes: number | null\n schedule: string | null\n timezone: string | null\n paused: boolean\n lastRunAt: string | null\n nextRunAt: string | null\n}\n\nexport interface CronHistoryEntry {\n taskName: string\n startedAt: string\n completedAt: string | null\n success: boolean\n durationMs: number\n error?: string\n}\n\nexport interface UseCronMonitorResult {\n /** Current task states */\n tasks: CronTaskState[]\n /** Execution history */\n history: CronHistoryEntry[]\n /** Whether WebSocket is connected */\n connected: boolean\n /** Manually trigger a task */\n trigger: (taskName: string) => void\n /** Pause a task */\n pause: (taskName: string) => void\n /** Resume a paused task */\n resume: (taskName: string) => void\n}\n\nexport function useCronMonitor(roomId: string): UseCronMonitorResult {\n const [tasks, setTasks] = useState<CronTaskState[]>([])\n const [history, setHistory] = useState<CronHistoryEntry[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/cron/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => setConnected(true)\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.CRON_TASKS]: (p) => {\n setTasks(p.tasks as CronTaskState[])\n },\n [MSG.CRON_HISTORY]: (p) => {\n setHistory(p.history as CronHistoryEntry[])\n },\n [MSG.CRON_STATUS]: (p) => {\n setTasks(p.tasks as CronTaskState[])\n setHistory(p.recentHistory as CronHistoryEntry[])\n },\n })\n }\n\n ws.onclose = () => {\n wsRef.current = null\n setConnected(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n ws?.close()\n wsRef.current = null\n }\n }, [roomId])\n\n const sendBuilt = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [],\n )\n\n const trigger = useCallback(\n (taskName: string) => sendBuilt(clientBuild.cronTrigger(taskName)),\n [sendBuilt],\n )\n const pause = useCallback(\n (taskName: string) => sendBuilt(clientBuild.cronPause(taskName)),\n [sendBuilt],\n )\n const resume = useCallback(\n (taskName: string) => sendBuilt(clientBuild.cronResume(taskName)),\n [sendBuilt],\n )\n\n return { tasks, history, connected, trigger, pause, resume }\n}\n","/**\n * useJobs — Connect to a JobRoom for enqueueing and tracking background\n * jobs in real time.\n *\n * Opens a WebSocket to /ws/jobs/:roomId. The DO pushes a snapshot on\n * connect and JOB_UPDATE messages for every state change after that, so\n * `jobs` stays current without polling. `enqueue` returns a promise that\n * resolves with the new jobId once the server acks.\n *\n * Client-side names (`JobView`, `JobStatusView`) differ from the\n * server-side equivalents (`Job`, `JobStatus` in `deepspace/worker`) so\n * apps importing from both ends don't get type collisions.\n *\n * @example\n * const { jobs, enqueue, getJob, cancel } = useJobs(`app:${APP_NAME}`)\n *\n * async function onClick() {\n * const jobId = await enqueue('ai-summarize', { text })\n * // Now `getJob(jobId)` is reactive until the job reaches a terminal state.\n * }\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\n/** How long enqueue() waits for a server ack before rejecting. */\nconst ENQUEUE_TIMEOUT_MS = 10_000\n\nexport type JobStatusView =\n | 'queued'\n | 'running'\n | 'succeeded'\n | 'failed'\n | 'canceled'\n\nexport interface JobView<P = unknown, R = unknown> {\n id: string\n type: string\n status: JobStatusView\n payload?: P\n result?: R\n error?: string\n progress?: number\n progressMessage?: string\n attempts: number\n maxAttempts: number\n enqueuedAt: string\n startedAt?: string | null\n completedAt?: string | null\n enqueuedBy?: string | null\n}\n\nexport interface UseJobsResult<P = unknown, R = unknown> {\n /** All jobs the room currently knows about, newest-first. */\n jobs: JobView<P, R>[]\n /** WebSocket connection state. */\n connected: boolean\n /**\n * Enqueue a new job. Resolves with the new jobId once the server acks\n * (typically <100ms). Rejects if:\n * - the WebSocket isn't connected\n * - the WebSocket closes before the ack arrives\n * - no ack arrives within 10s (server dropped the message)\n */\n enqueue(\n type: string,\n payload?: P,\n options?: { maxAttempts?: number },\n ): Promise<string>\n /**\n * Reactive single-job lookup. Returns undefined while the snapshot is\n * loading or if the job has been GC'd by the room's TTL sweep.\n */\n getJob(jobId: string): JobView<P, R> | undefined\n /** Best-effort cancel. The job is marked canceled even if the handler ignores `ctx.signal`. */\n cancel(jobId: string): void\n /** Manually re-queue a failed/canceled job. No-op for other statuses. */\n retry(jobId: string): void\n}\n\ninterface PendingEnqueue {\n resolve: (id: string) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * @param roomId DO room id, typically `app:<APP_NAME>`. Apps with sharded\n * queues pass different ids — each id maps to its own DO instance.\n */\nexport function useJobs<P = unknown, R = unknown>(\n roomId: string,\n): UseJobsResult<P, R> {\n const [jobs, setJobs] = useState<JobView<P, R>[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n /**\n * Pending enqueue promises keyed by requestId. Each entry carries a\n * timeout timer so the caller doesn't hang forever if the server drops\n * the enqueue (validation error swallowed, isolate restart, etc.).\n */\n const pendingEnqueueRef = useRef<Map<string, PendingEnqueue>>(new Map())\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const upsert = (next: JobView<P, R>) => {\n setJobs((prev) => {\n const idx = prev.findIndex((j) => j.id === next.id)\n if (idx === -1) return [next, ...prev]\n const copy = prev.slice()\n copy[idx] = next\n return copy\n })\n }\n\n const rejectAllPending = (err: Error) => {\n for (const [id, pending] of pendingEnqueueRef.current.entries()) {\n clearTimeout(pending.timer)\n pending.reject(err)\n pendingEnqueueRef.current.delete(id)\n }\n }\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/jobs/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => setConnected(true)\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.JOB_UPDATE]: (p) => {\n if (p.kind === 'snapshot' && Array.isArray(p.jobs)) {\n setJobs(p.jobs as JobView<P, R>[])\n return\n }\n const job = p.job as JobView<P, R> | undefined\n if (!job) return\n upsert(job)\n // Resolve the enqueue promise once the server acks.\n if (p.kind === 'enqueued' && typeof p.requestId === 'string') {\n const pending = pendingEnqueueRef.current.get(p.requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingEnqueueRef.current.delete(p.requestId)\n pending.resolve(job.id)\n }\n }\n },\n })\n }\n\n ws.onclose = () => {\n wsRef.current = null\n setConnected(false)\n rejectAllPending(new Error('JobRoom WebSocket closed'))\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n rejectAllPending(new Error('useJobs unmounted'))\n ws?.close()\n wsRef.current = null\n }\n }, [roomId])\n\n const enqueue = useCallback(\n (type: string, payload?: P, options?: { maxAttempts?: number }) => {\n return new Promise<string>((resolve, reject) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n reject(new Error('JobRoom WebSocket not connected'))\n return\n }\n const requestId = crypto.randomUUID()\n const timer = setTimeout(() => {\n pendingEnqueueRef.current.delete(requestId)\n reject(\n new Error(\n `JobRoom enqueue timed out (no server ack within ${ENQUEUE_TIMEOUT_MS}ms)`,\n ),\n )\n }, ENQUEUE_TIMEOUT_MS)\n pendingEnqueueRef.current.set(requestId, { resolve, reject, timer })\n // ws.send can throw synchronously if the socket transitions between\n // the readyState check and the call (browser-specific, quota errors).\n // Without this guard the pending entry would sit until the 10s\n // timeout — fine for safety, bad for caller latency.\n try {\n ws.send(\n encode(clientBuild.jobEnqueue(requestId, type, payload, options?.maxAttempts)),\n )\n } catch (e) {\n clearTimeout(timer)\n pendingEnqueueRef.current.delete(requestId)\n reject(e instanceof Error ? e : new Error(String(e)))\n }\n })\n },\n [],\n )\n\n const sendBuilt = useCallback(\n <M extends { type: string; payload: unknown }>(message: M): void => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [],\n )\n\n const getJob = useCallback(\n (jobId: string) => jobs.find((j) => j.id === jobId),\n [jobs],\n )\n\n const cancel = useCallback(\n (jobId: string) => sendBuilt(clientBuild.jobCancel(jobId)),\n [sendBuilt],\n )\n\n const retry = useCallback(\n (jobId: string) => sendBuilt(clientBuild.jobRetry(jobId)),\n [sendBuilt],\n )\n\n return { jobs, connected, enqueue, getJob, cancel, retry }\n}\n","/**\n * usePresenceRoom — Connect to a PresenceRoom Durable Object.\n *\n * Opens a WebSocket to /ws/presence/:scopeId for real-time presence tracking.\n * Use with any scope: canvas, doc, thread, page, etc.\n *\n * Peers can share arbitrary state (cursor position, typing indicator,\n * viewport, selection) via updateState().\n *\n * @example\n * // Track who's on a canvas\n * const { peers, connected, updateState } = usePresenceRoom(`canvas:${canvasId}`)\n *\n * // Share cursor position\n * updateState({ cursor: { x: 100, y: 200 } })\n *\n * // Track who's viewing a thread\n * const { peers } = usePresenceRoom(`thread:${channelId}`)\n *\n * // Show typing indicator\n * updateState({ typing: true })\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PresencePeerClient {\n userId: string\n userName: string\n userEmail: string\n userImageUrl?: string\n joinedAt: string\n state: Record<string, unknown>\n}\n\nexport interface UsePresenceRoomResult {\n /** All peers currently present in this scope (excludes self) */\n peers: PresencePeerClient[]\n /** Whether the WebSocket is connected */\n connected: boolean\n /** Send a state update (cursor, typing, viewport, etc.) — merges with existing state */\n updateState: (state: Record<string, unknown>) => void\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function usePresenceRoom(scopeId: string): UsePresenceRoomResult {\n const [peers, setPeers] = useState<PresencePeerClient[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/presence/${encodeURIComponent(scopeId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `presence:${scopeId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `presence:${scopeId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.PRESENCE_SYNC]: (p) => {\n setPeers(p.peers as PresencePeerClient[])\n },\n [MSG.PRESENCE_JOIN]: (p) => {\n const peer = p.peer as PresencePeerClient\n setPeers((prev) => [...prev.filter((x) => x.userId !== peer.userId), peer])\n },\n [MSG.PRESENCE_LEAVE]: (p) => {\n setPeers((prev) => prev.filter((x) => x.userId !== p.userId))\n },\n [MSG.PRESENCE_UPDATE]: (p) => {\n setPeers((prev) =>\n prev.map((x) =>\n x.userId === p.userId ? { ...x, state: { ...x.state, ...p.state } } : x,\n ),\n )\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `presence:${scopeId}`)\n wsRef.current = null\n setConnected(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `presence:${scopeId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [scopeId])\n\n const updateState = useCallback((state: Record<string, unknown>) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.presenceUpdate(state)))\n }, [])\n\n return { peers, connected, updateState }\n}\n","/**\n * ConnectionStatus type and utility for domain hooks.\n *\n * Maps useQuery() status to a simpler connection state\n * used by app-level platform providers.\n */\n\nexport type ConnectionStatus = 'connecting' | 'connected' | 'reconnecting' | 'error'\n\n/**\n * Map a useQuery() status string to a ConnectionStatus.\n *\n * useQuery returns: 'pending' | 'ready' | 'error'\n * This maps to the simplified connection states used by platform providers.\n */\nexport function toConnectionStatus(queryStatus: string): ConnectionStatus {\n if (queryStatus === 'ready') return 'connected'\n if (queryStatus === 'error') return 'error'\n return 'connecting'\n}\n","/**\n * useR2Files — Scoped file storage hook for DeepSpace apps.\n *\n * Provides upload, download, list, and delete for files in R2, scoped to\n * the current app (\"self\" — uses hostname-based scoping on the server).\n *\n * @example\n * ```tsx\n * const { upload, downloadFile, deleteFile, list } = useR2Files()\n * await upload(myFile, 'photo.png')\n *\n * const files = await list()\n * await downloadFile(files[0]) // uses originalName automatically\n * await deleteFile(files[0])\n * ```\n */\n\nimport { useCallback, useState, useMemo } from 'react'\nimport { getAuthToken } from '../auth'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface R2UploadResult {\n success: boolean\n key?: string\n url?: string\n name?: string\n error?: string\n}\n\nexport interface R2FileInfo {\n key: string\n size: number\n uploaded: string\n url: string\n originalName?: string\n uploadedBy?: string\n}\n\nexport interface UseR2FilesReturn {\n /** Upload a File or Blob. Optionally provide a display name. */\n upload: (file: File | Blob, name?: string) => Promise<R2UploadResult>\n /** Upload raw base64 data. */\n uploadBase64: (base64Data: string, name: string, mimeType?: string) => Promise<R2UploadResult>\n /**\n * Delete a file. Accepts an R2FileInfo from `list()` or a raw key string.\n *\n * @example\n * ```tsx\n * const files = await list()\n * await deleteFile(files[0]) // pass the object\n * await deleteFile('widgets/abc/f.pdf') // or a raw key\n * ```\n */\n deleteFile: (fileOrKey: R2FileInfo | string) => Promise<{ success: boolean; error?: string }>\n /** List files, optionally filtered by a sub-prefix within the scope. */\n list: (prefix?: string) => Promise<R2FileInfo[]>\n /**\n * Download a file. Accepts an R2FileInfo from `list()` or a raw key string.\n * Uses an authenticated fetch and triggers a browser download via blob URL.\n *\n * When an R2FileInfo is passed, `originalName` is used as the download\n * filename automatically. When a string key is passed, an optional\n * `fileName` override can be provided.\n *\n * @example\n * ```tsx\n * const files = await list()\n * await downloadFile(files[0]) // uses originalName\n * await downloadFile('widgets/abc/f.pdf', 'report.pdf') // explicit name\n * ```\n */\n downloadFile: (fileOrKey: R2FileInfo | string, fileName?: string) => Promise<{ success: boolean; error?: string }>\n /**\n * Read a file's contents with authentication. Returns the raw Response.\n * Unlike `downloadFile`, this does NOT trigger a browser download —\n * it returns the Response so you can call `.text()`, `.blob()`,\n * `.arrayBuffer()`, `.json()`, etc.\n *\n * @example\n * ```tsx\n * const resp = await readFile('data/cleaned.txt')\n * const text = await resp.text()\n * ```\n */\n readFile: (fileOrKey: R2FileInfo | string) => Promise<Response>\n /**\n * Build a plain URL for a file. Accepts an R2FileInfo or a raw key string.\n *\n * **Note**: This URL has no auth token attached. It only works for\n * unauthenticated reads on deployed sites where the prefix is derived\n * from the hostname. For authenticated access, use `downloadFile` or\n * `readFile` instead.\n */\n getUrl: (fileOrKey: R2FileInfo | string) => string\n /** Whether an upload is currently in progress. */\n isUploading: boolean\n}\n\nexport type R2Scope = { scope?: 'self' }\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Extract key (and optional original name) from an R2FileInfo or raw string. */\nfunction resolveFile(fileOrKey: R2FileInfo | string): { key: string; name: string | undefined } {\n if (typeof fileOrKey === 'string') {\n return { key: fileOrKey, name: undefined }\n }\n return { key: fileOrKey.key, name: fileOrKey.originalName }\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useR2Files(options?: R2Scope): UseR2FilesReturn {\n const [isUploading, setIsUploading] = useState(false)\n\n /** Query string that tells the worker which scope to use. */\n const scopeParams = useMemo(() => {\n const params = new URLSearchParams()\n params.set('scope', 'self')\n return params.toString()\n }, [])\n\n /** Get auth headers using the DeepSpace auth token. */\n const authHeaders = useCallback(async (): Promise<Record<string, string>> => {\n const token = await getAuthToken()\n if (token) {\n return { Authorization: `Bearer ${token}` }\n }\n return {}\n }, [])\n\n const upload = useCallback(async (file: File | Blob, name?: string): Promise<R2UploadResult> => {\n setIsUploading(true)\n try {\n const headers = await authHeaders()\n const formData = new FormData()\n formData.append('file', file)\n if (name) formData.append('name', name)\n\n const response = await fetch(`/api/files/upload?${scopeParams}`, {\n method: 'POST',\n headers,\n body: formData,\n })\n return await response.json() as R2UploadResult\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Upload failed' }\n } finally {\n setIsUploading(false)\n }\n }, [scopeParams, authHeaders])\n\n const uploadBase64 = useCallback(async (base64Data: string, name: string, mimeType?: string): Promise<R2UploadResult> => {\n setIsUploading(true)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/upload?${scopeParams}`, {\n method: 'POST',\n headers: { ...headers, 'Content-Type': 'application/json' },\n body: JSON.stringify({ data: base64Data, name, mimeType }),\n })\n return await response.json() as R2UploadResult\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Upload failed' }\n } finally {\n setIsUploading(false)\n }\n }, [scopeParams, authHeaders])\n\n const deleteFile = useCallback(async (fileOrKey: R2FileInfo | string): Promise<{ success: boolean; error?: string }> => {\n const { key } = resolveFile(fileOrKey)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { method: 'DELETE', headers })\n return await response.json() as { success: boolean; error?: string }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Delete failed' }\n }\n }, [scopeParams, authHeaders])\n\n const list = useCallback(async (prefix?: string): Promise<R2FileInfo[]> => {\n try {\n const headers = await authHeaders()\n const params = new URLSearchParams(scopeParams)\n if (prefix) params.set('prefix', prefix)\n const response = await fetch(`/api/files?${params.toString()}`, { headers })\n const result = await response.json() as { files: R2FileInfo[] }\n return result.files || []\n } catch {\n return []\n }\n }, [scopeParams, authHeaders])\n\n const downloadFile = useCallback(async (fileOrKey: R2FileInfo | string, fileName?: string): Promise<{ success: boolean; error?: string }> => {\n const { key, name: infoName } = resolveFile(fileOrKey)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { headers })\n\n if (!response.ok) {\n const body = await response.json().catch(() => null) as { error?: string } | null\n return { success: false, error: body?.error ?? `Download failed (${response.status})` }\n }\n\n // Derive a display name: explicit arg > R2FileInfo.originalName > Content-Disposition > last key segment\n const disposition = response.headers.get('Content-Disposition')\n const dispositionName = disposition?.match(/filename=\"(.+?)\"/)?.[1]\n const fallbackName = key.split('/').pop() ?? 'download'\n const resolvedName = fileName ?? infoName ?? dispositionName ?? fallbackName\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n\n const anchor = document.createElement('a')\n anchor.href = blobUrl\n anchor.download = resolvedName\n document.body.appendChild(anchor)\n anchor.click()\n\n // Clean up\n document.body.removeChild(anchor)\n URL.revokeObjectURL(blobUrl)\n\n return { success: true }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Download failed' }\n }\n }, [scopeParams, authHeaders])\n\n const readFile = useCallback(async (fileOrKey: R2FileInfo | string): Promise<Response> => {\n const { key } = resolveFile(fileOrKey)\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { headers })\n if (!response.ok) {\n const body = await response.text().catch(() => '')\n throw new Error(`Failed to read file (${response.status}): ${body}`)\n }\n return response\n }, [scopeParams, authHeaders])\n\n const getUrl = useCallback((fileOrKey: R2FileInfo | string): string => {\n const { key } = resolveFile(fileOrKey)\n return `/api/files/${key}?${scopeParams}`\n }, [scopeParams])\n\n return { upload, uploadBase64, deleteFile, downloadFile, readFile, list, getUrl, isUploading }\n}\n","/**\n * Shared types and utilities for file attachments across miniapps.\n */\n\nexport interface FileAttachment {\n key: string\n url: string\n name: string\n size: number\n mimeType: string\n}\n\nconst IMAGE_MIME_PREFIXES = ['image/']\n\nexport function isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_PREFIXES.some(prefix => mimeType.startsWith(prefix))\n}\n\nexport function formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n","/**\n * Deterministic user color assignment.\n * Same user ID always maps to the same color across sessions.\n */\n\nexport const DEFAULT_USER_COLORS = [\n '#f87171', '#fb923c', '#fbbf24', '#34d399',\n '#22d3ee', '#60a5fa', '#a78bfa', '#f472b6',\n '#e879f9', '#4ade80', '#38bdf8', '#facc15',\n] as const\n\nexport function getUserColor(userId: string, palette: readonly string[] = DEFAULT_USER_COLORS): string {\n let hash = 0\n for (let i = 0; i < userId.length; i++) {\n hash = ((hash << 5) - hash + userId.charCodeAt(i)) | 0\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","/**\n * useMessages — subscribe to messages in a channel with send/edit/remove.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Message } from './channel-types'\n\nexport function useMessages(\n channelId: string | undefined,\n options?: { parentMessageId?: string }\n) {\n const where = useMemo(() => {\n if (!channelId) return { channelId: '__none__' }\n const w: Record<string, unknown> = { channelId }\n if (options?.parentMessageId !== undefined) {\n w.parentMessageId = options.parentMessageId\n }\n return w\n }, [channelId, options?.parentMessageId])\n\n const { user } = useUser()\n\n const { records, status, error } = useQuery<Message>('messages', {\n where,\n orderBy: 'createdAt',\n orderDir: 'asc',\n })\n\n const { create, put, remove: removeMutation } = useMutations<Message>('messages')\n\n const send = useCallback(\n (content: string, parentMessageId?: string) => {\n if (!channelId || !user) return\n const data: Record<string, unknown> = { channelId, content, authorId: user.id, edited: false }\n if (parentMessageId) data.parentMessageId = parentMessageId\n return create(data as unknown as Message)\n },\n [channelId, create],\n )\n\n const edit = useCallback(\n (messageId: string, newContent: string) => {\n put(messageId, { content: newContent, edited: true } as unknown as Message)\n },\n [put],\n )\n\n /** Hard-delete: drops the row entirely. Use when threads/replies don't matter. */\n const remove = useCallback(\n (messageId: string) => { removeMutation(messageId) },\n [removeMutation],\n )\n\n /**\n * Soft-delete: sets `deleted: true` on the message. The row stays so threads,\n * read-receipts, and parent links remain coherent. UIs render a tombstone\n * (e.g. \"This message was deleted.\") for messages with `deleted === true`.\n */\n const softDelete = useCallback(\n (messageId: string) => {\n put(messageId, { deleted: true } as unknown as Message)\n },\n [put],\n )\n\n return { messages: records as RecordData<Message>[], status, error, send, edit, remove, softDelete }\n}\n","/**\n * useChannels — subscribe to channels with create/archive/update.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Channel } from './channel-types'\n\nexport function useChannels() {\n const { user } = useUser()\n const { records, status, error } = useQuery<Channel>('channels', {\n orderBy: 'createdAt',\n orderDir: 'asc',\n })\n\n const { create: createMutation, put, remove } = useMutations<Channel>('channels')\n\n const create = useCallback(\n (data: { name: string; type: Channel['type']; description?: string }) => {\n return createMutation({\n name: data.name,\n type: data.type,\n description: data.description ?? '',\n createdBy: user?.id ?? '',\n archived: false,\n } as unknown as Channel)\n },\n [createMutation],\n )\n\n const archive = useCallback(\n (channelId: string) => { put(channelId, { archived: true } as unknown as Channel) },\n [put],\n )\n\n const update = useCallback(\n (channelId: string, data: Partial<Pick<Channel, 'name' | 'description'>>) => {\n put(channelId, data as unknown as Channel)\n },\n [put],\n )\n\n return { channels: records as RecordData<Channel>[], status, error, create, archive, update, remove }\n}\n","/**\n * useReactions — subscribe to reactions in a channel with toggle.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Reaction } from './channel-types'\nimport type { GroupedReaction } from './types'\n\nexport function useReactions(channelId: string | undefined) {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<Reaction>('reactions', {\n where: channelId ? { channelId } : { channelId: '__none__' },\n })\n\n const { create, remove: removeMutation } = useMutations<Reaction>('reactions')\n\n const getReactionsForMessage = useCallback(\n (messageId: string): GroupedReaction[] => {\n const messageReactions = records.filter((r) => r.data.messageId === messageId)\n const grouped = new Map<string, string[]>()\n\n for (const r of messageReactions) {\n if (!grouped.has(r.data.emoji)) grouped.set(r.data.emoji, [])\n grouped.get(r.data.emoji)!.push(r.data.userId)\n }\n\n return Array.from(grouped.entries()).map(([emoji, userIds]) => ({\n emoji,\n count: userIds.length,\n userIds,\n currentUserReacted: user ? userIds.includes(user.id) : false,\n }))\n },\n [records, user],\n )\n\n const toggle = useCallback(\n (messageId: string, emoji: string) => {\n if (!channelId || !user) return\n const existing = records.find(\n (r) => r.data.messageId === messageId && r.data.emoji === emoji && r.data.userId === user.id,\n )\n if (existing) {\n removeMutation(existing.recordId)\n } else {\n create({ messageId, channelId, emoji, userId: user.id } as unknown as Reaction)\n }\n },\n [channelId, user, records, create, removeMutation],\n )\n\n return { reactions: records as RecordData<Reaction>[], status, error, getReactionsForMessage, toggle }\n}\n","/**\n * useChannelMembers — subscribe to channel membership with join/leave.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { ChannelMember } from './channel-types'\n\nexport function useChannelMembers(channelId: string | undefined) {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<ChannelMember>('channel-members', {\n where: channelId ? { channelId } : { channelId: '__none__' },\n })\n\n const { create, remove: removeMutation } = useMutations<ChannelMember>('channel-members')\n\n const join = useCallback(() => {\n if (!channelId || !user) return\n const existing = records.find((r) => r.data.userId === user.id)\n if (existing) return\n create({ channelId, userId: user.id, joinedAt: new Date().toISOString() } as unknown as ChannelMember)\n }, [channelId, user, records, create])\n\n const leave = useCallback(() => {\n if (!channelId || !user) return\n const membership = records.find((r) => r.data.userId === user.id)\n if (membership) removeMutation(membership.recordId)\n }, [channelId, user, records, removeMutation])\n\n const isMember = user ? records.some((r) => r.data.userId === user.id) : false\n\n return { members: records as RecordData<ChannelMember>[], status, error, join, leave, isMember }\n}\n","/**\n * useReadReceipts — track read state per channel for the current user.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { ReadReceipt, Message } from './channel-types'\n\nexport function useReadReceipts() {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<ReadReceipt>('read-receipts', {\n where: user ? { userId: user.id } : { userId: '__none__' },\n })\n\n const { create, put } = useMutations<ReadReceipt>('read-receipts')\n\n const markAsRead = useCallback(\n (channelId: string) => {\n if (!user) return\n const existing = records.find((r) => r.data.channelId === channelId)\n const now = new Date().toISOString()\n if (existing) {\n put(existing.recordId, { lastReadAt: now } as unknown as ReadReceipt)\n } else {\n create({ channelId, userId: user.id, lastReadAt: now } as unknown as ReadReceipt)\n }\n },\n [user, records, create, put],\n )\n\n const getUnreadCount = useCallback(\n (channelId: string, messages: RecordData<Message>[]): number => {\n const receipt = records.find((r) => r.data.channelId === channelId)\n if (!receipt) return messages.length\n const lastReadAt = new Date(receipt.data.lastReadAt).getTime()\n return messages.filter((m) => new Date(m.createdAt).getTime() > lastReadAt).length\n },\n [records],\n )\n\n return { receipts: records as RecordData<ReadReceipt>[], status, error, markAsRead, getUnreadCount }\n}\n","/**\n * useConversation — Shared hook for conversation messaging.\n *\n * Wraps useQuery/useMutations for conv_messages, conv_reactions, conv_members\n * and returns a ConversationObject. Must be used inside a RecordScope for the\n * conversation DO (conv:{channelId}).\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useRecordContext } from '../storage/context'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { ConvMessageData, ConvReactionData, ConvMemberData } from '../../shared/types'\nimport type { MessageRecord, ReactionRecord, MemberRecord, ConversationObject } from './types'\n\ninterface UseConversationOptions {\n onMessageSent?: (content: string, parentMessageId?: string) => void\n}\n\nexport function useConversation(opts?: UseConversationOptions): ConversationObject {\n const { user } = useUser()\n const { ready } = useRecordContext()\n\n const { records: allMessages } = useQuery<ConvMessageData>('conv_messages', { orderBy: '_created_at' })\n const { records: allReactions } = useQuery<ConvReactionData>('conv_reactions')\n const { records: members } = useQuery<ConvMemberData>('conv_members')\n\n const messageMut = useMutations<ConvMessageData>('conv_messages')\n const reactionMut = useMutations<ConvReactionData>('conv_reactions')\n\n const send = useCallback(\n (content: string, parentMessageId?: string, messageType?: string, metadata?: Record<string, unknown>) => {\n messageMut.create({\n Content: content,\n AuthorId: user?.id ?? '',\n ParentId: parentMessageId ?? '',\n Edited: 0,\n MessageType: messageType ?? 'message',\n Metadata: metadata ? JSON.stringify(metadata) : '',\n })\n opts?.onMessageSent?.(content, parentMessageId)\n },\n [messageMut, user?.id, opts?.onMessageSent],\n )\n\n const edit = useCallback(\n (recordId: string, content: string) => {\n const existing = allMessages.find((m) => m.recordId === recordId)\n if (!existing) return\n messageMut.put(recordId, { ...existing.data, Content: content, Edited: 1 })\n },\n [messageMut, allMessages],\n )\n\n const remove = useCallback(\n (recordId: string) => {\n const existing = allMessages.find((m) => m.recordId === recordId)\n if (!existing) return\n messageMut.put(recordId, {\n ...existing.data,\n Content: '',\n MessageType: 'deleted',\n Metadata: '',\n })\n },\n [messageMut, allMessages],\n )\n\n const toggleReaction = useCallback(\n (messageId: string, emoji: string) => {\n const existing = allReactions.find(\n (r) => r.data.MessageId === messageId && r.data.Emoji === emoji && r.data.UserId === user?.id,\n )\n if (existing) {\n reactionMut.remove(existing.recordId)\n } else {\n reactionMut.create({ MessageId: messageId, Emoji: emoji, UserId: user?.id ?? '' })\n }\n },\n [reactionMut, allReactions, user?.id],\n )\n\n return useMemo(\n () => ({\n messages: allMessages as MessageRecord[],\n reactions: allReactions as ReactionRecord[],\n members: members as MemberRecord[],\n status: ready ? ('connected' as const) : ('connecting' as const),\n send,\n edit,\n remove,\n toggleReaction,\n }),\n [allMessages, allReactions, members, ready, send, edit, remove, toggleReaction],\n )\n}\n","/**\n * Shared messaging utility functions.\n */\n\nimport type { ReactionRecord, GroupedReaction, MessageRecord } from './types'\n\nexport function groupReactionsForMessage(\n reactions: ReactionRecord[],\n messageId: string,\n currentUserId: string,\n): GroupedReaction[] {\n const forMessage = reactions.filter((r) => r.data.MessageId === messageId)\n const groups = new Map<string, { count: number; currentUserReacted: boolean; userIds: string[] }>()\n\n for (const r of forMessage) {\n const existing = groups.get(r.data.Emoji) ?? { count: 0, currentUserReacted: false, userIds: [] }\n existing.count++\n existing.userIds.push(r.data.UserId)\n if (r.data.UserId === currentUserId) existing.currentUserReacted = true\n groups.set(r.data.Emoji, existing)\n }\n\n return Array.from(groups.entries()).map(([emoji, data]) => ({\n emoji,\n count: data.count,\n currentUserReacted: data.currentUserReacted,\n userIds: data.userIds,\n }))\n}\n\n/** Default grouping threshold: 5 minutes */\nconst GROUPING_THRESHOLD_MS = 5 * 60 * 1000\n\n/**\n * Determine whether a message should be visually grouped with the previous one\n * (same author, within threshold, no date boundary).\n */\nexport function shouldGroupMessages(\n current: MessageRecord,\n previous: MessageRecord | null | undefined,\n options?: { thresholdMs?: number; dateChanged?: boolean },\n): boolean {\n if (!previous) return false\n if (options?.dateChanged) return false\n if (previous.data.AuthorId !== current.data.AuthorId) return false\n const timeDiff = new Date(current.createdAt).getTime() - new Date(previous.createdAt).getTime()\n return timeDiff < (options?.thresholdMs ?? GROUPING_THRESHOLD_MS)\n}\n\n/**\n * Compute thread reply counts from a flat message array.\n */\nexport function getThreadCounts(messages: MessageRecord[]): Map<string, number> {\n const counts = new Map<string, number>()\n for (const m of messages) {\n if (m.data.ParentId) {\n counts.set(m.data.ParentId, (counts.get(m.data.ParentId) ?? 0) + 1)\n }\n }\n return counts\n}\n\n/**\n * Format a message timestamp for display.\n * Returns \"2:30 PM\" style short time.\n */\nexport function formatMessageTime(dateStr: string): string {\n return new Date(dateStr).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\n/**\n * Format a full message timestamp.\n * Returns \"Mar 5, 2026 at 2:30 PM\" style.\n */\nexport function formatFullTimestamp(dateStr: string): string {\n const date = new Date(dateStr)\n const datePart = date.toLocaleDateString([], { month: 'short', day: 'numeric', year: 'numeric' })\n const timePart = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n return `${datePart} at ${timePart}`\n}\n","/**\n * Conversation Display Utilities\n *\n * Shared helpers for rendering conversation names, participant lists,\n * and type checks across apps (slack-clone, discord-clone, etc.).\n */\n\nimport type { UserInfo } from '../storage/hooks/useUserLookup'\n\ninterface ConversationData {\n Name: string\n Type: string\n ParticipantIds: string\n ParticipantHash: string\n}\n\n/**\n * Get a display name for a conversation.\n *\n * - Channels: use Name field\n * - DMs: look up the other participant's name\n * - Group DMs: \"User A, User B, +N\"\n */\nexport function getConversationDisplayName(\n conversation: { data: ConversationData },\n currentUserId: string,\n getUser: (id: string) => UserInfo | undefined,\n): string {\n const { Type, Name, ParticipantIds } = conversation.data\n\n if (Type !== 'dm' && Type !== 'group') {\n return Name || 'Untitled'\n }\n\n const ids = getConversationParticipantIds(conversation, currentUserId)\n\n if (ids.length === 0) return 'Unknown'\n\n if (Type === 'dm') {\n const other = getUser(ids[0])\n return other?.name ?? 'Unknown'\n }\n\n // Group DM\n const MAX_NAMES = 3\n const names: string[] = []\n for (let i = 0; i < Math.min(ids.length, MAX_NAMES); i++) {\n const u = getUser(ids[i])\n names.push(u?.name?.split(' ')[0] ?? 'Unknown')\n }\n const remaining = ids.length - MAX_NAMES\n if (remaining > 0) {\n return `${names.join(', ')}, +${remaining}`\n }\n return names.join(', ')\n}\n\n/**\n * Check if a conversation type is a DM or group DM.\n */\nexport function isDMConversation(type: string): boolean {\n return type === 'dm' || type === 'group'\n}\n\n/**\n * Parse participant IDs from a conversation.\n * Tries ParticipantIds JSON first, falls back to ParticipantHash (colon-separated).\n */\nexport function getConversationParticipantIds(\n conversation: { data: Pick<ConversationData, 'ParticipantIds' | 'ParticipantHash'> },\n excludeUserId?: string,\n): string[] {\n let ids: string[] = []\n\n // Try ParticipantIds JSON first\n try {\n const parsed = JSON.parse(conversation.data.ParticipantIds)\n if (Array.isArray(parsed) && parsed.length > 0) {\n ids = parsed\n }\n } catch {\n // fall through to ParticipantHash\n }\n\n // Fallback to ParticipantHash (colon-separated user IDs)\n if (ids.length === 0 && conversation.data.ParticipantHash) {\n ids = conversation.data.ParticipantHash.split(':')\n }\n\n if (excludeUserId) {\n return ids.filter((id) => id !== excludeUserId)\n }\n return ids\n}\n","/**\n * Safely parse a Metadata field that may be a JSON string, an object, or null/undefined.\n * Returns the parsed object or null on failure.\n */\nexport function parseMessageMetadata(raw: unknown): Record<string, unknown> | null {\n if (!raw) return null\n if (typeof raw === 'object') return raw as Record<string, unknown>\n if (typeof raw === 'string') {\n try { return JSON.parse(raw) } catch { return null }\n }\n return null\n}\n","/**\n * useConversations Hook\n *\n * Standardized conversation directory backed by the `conversations` and\n * `conversation_state` collections in the dir:{appName} DO.\n *\n * Apps that need a sidebar list of channels / DMs / threads should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call useConversations() inside a RecordProvider.\n */\n\nimport { useCallback, useMemo, useRef } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryConversationData, ConversationStateData } from '../../shared/types'\n\nexport function useConversations() {\n const { records: conversations, status } = useQuery<DirectoryConversationData>('conversations')\n const { create, put } = useMutations<DirectoryConversationData>('conversations')\n const { records: stateRecords } = useQuery<ConversationStateData>('conversation_state')\n const stateMut = useMutations<ConversationStateData>('conversation_state')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const recentCreationsRef = useRef(new Map<string, DirectoryConversationData>())\n for (const [id] of recentCreationsRef.current) {\n if (conversations.find((c) => c.recordId === id)) {\n recentCreationsRef.current.delete(id)\n }\n }\n\n const readStateMap = useMemo(\n () => new Map(stateRecords.map((r) => [r.data.ConversationId, r.data.LastReadAt])),\n [stateRecords],\n )\n\n const readMessageCountMap = useMemo(\n () => new Map(stateRecords.map((r) => [r.data.ConversationId, r.data.LastReadMessageCount ?? 0])),\n [stateRecords],\n )\n\n const starredSet = useMemo(\n () => new Set(stateRecords.filter((r) => r.data.Starred).map((r) => r.data.ConversationId)),\n [stateRecords],\n )\n\n const archivedSet = useMemo(\n () => new Set(stateRecords.filter((r) => r.data.Archived).map((r) => r.data.ConversationId)),\n [stateRecords],\n )\n\n\n const getConversationState = useCallback(\n (conversationId: string): ConversationStateData | undefined => {\n return stateRecords.find((r) => r.data.ConversationId === conversationId)?.data\n },\n [stateRecords],\n )\n\n const defaultConvFields = {\n Visibility: 'public',\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n MessageCount: 0,\n }\n\n const createChannel = useCallback(\n async (name: string, description?: string) => {\n const existing = conversations.find((r) => r.data.Name === name && r.data.Type !== 'dm')\n if (existing) return existing.recordId\n\n const recordId = await create({\n Name: name,\n Description: description ?? '',\n Type: 'public',\n CreatedBy: user?.id ?? '',\n ParticipantHash: '',\n ParticipantIds: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n ...defaultConvFields,\n })\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const createDM = useCallback(\n async (otherUserId: string) => {\n if (!user?.id) return null\n const hash = [user.id, otherUserId].sort().join(':')\n\n const existing = conversations.find((r) => r.data.ParticipantHash === hash)\n if (existing) return existing.recordId\n\n const data: DirectoryConversationData = {\n Name: '',\n Description: '',\n Type: 'dm',\n Visibility: 'private',\n CreatedBy: user.id,\n ParticipantHash: hash,\n ParticipantIds: JSON.stringify([user.id, otherUserId]),\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n MessageCount: 0,\n }\n const recordId = await create(data)\n recentCreationsRef.current.set(recordId, data)\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const createGroupDM = useCallback(\n async (participantIds: string[]) => {\n if (!user?.id) return null\n // Add current user + deduplicate\n const allIds = [...new Set([user.id, ...participantIds])]\n if (allIds.length < 3) return null // Use createDM for 2 participants\n\n const hash = allIds.sort().join(':')\n\n const existing = conversations.find((r) => r.data.ParticipantHash === hash)\n if (existing) return existing.recordId\n\n const data: DirectoryConversationData = {\n Name: '',\n Description: '',\n Type: 'group',\n Visibility: 'private',\n CreatedBy: user.id,\n ParticipantHash: hash,\n ParticipantIds: JSON.stringify(allIds),\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n MessageCount: 0,\n }\n const recordId = await create(data)\n recentCreationsRef.current.set(recordId, data)\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const lookupByName = useCallback(\n (name: string) => {\n const found = conversations.find((r) => r.data.Name === name)\n return found?.recordId ?? null\n },\n [conversations],\n )\n\n const updateLastMessage = useCallback(\n (conversationId: string, preview: string, authorId?: string) => {\n const conv = conversations.find((c) => c.recordId === conversationId)\n const baseData = conv?.data ?? recentCreationsRef.current.get(conversationId)\n if (!baseData) return\n const updatedData = {\n ...baseData,\n LastMessageAt: new Date().toISOString(),\n LastMessagePreview: preview.slice(0, 100),\n LastMessageAuthor: authorId ?? baseData.LastMessageAuthor,\n MessageCount: (baseData.MessageCount ?? 0) + 1,\n }\n put(conversationId, updatedData)\n if (recentCreationsRef.current.has(conversationId)) {\n recentCreationsRef.current.set(conversationId, updatedData)\n }\n },\n [put, conversations],\n )\n\n /** Upsert the user's conversation_state row for a conversation. */\n const upsertState = useCallback(\n (conversationId: string, partial: Partial<ConversationStateData>) => {\n if (!user?.id) return\n const existing = stateRecords.find(\n (r) => r.data.ConversationId === conversationId && r.data.UserId === user.id,\n )\n const base: ConversationStateData = existing?.data ?? {\n ConversationId: conversationId,\n UserId: user.id,\n LastReadAt: '',\n LastReadMessageCount: 0,\n Starred: 0,\n Archived: 0,\n Trashed: 0,\n Labels: '',\n Folder: '',\n }\n const recordId = existing?.recordId ?? `state-${user.id}-${conversationId}`\n stateMut.put(recordId, { ...base, ...partial })\n },\n [stateMut, stateRecords, user?.id],\n )\n\n const markRead = useCallback(\n (conversationId: string) => {\n const conv = conversations.find((c) => c.recordId === conversationId)\n const msgCount = conv?.data.MessageCount ?? recentCreationsRef.current.get(conversationId)?.MessageCount ?? 0\n upsertState(conversationId, {\n LastReadAt: new Date().toISOString(),\n LastReadMessageCount: msgCount,\n })\n },\n [upsertState, conversations],\n )\n\n const toggleStar = useCallback(\n (conversationId: string) => {\n const isStarred = starredSet.has(conversationId)\n upsertState(conversationId, { Starred: isStarred ? 0 : 1 })\n },\n [upsertState, starredSet],\n )\n\n const setArchived = useCallback(\n (conversationId: string, archived: boolean) => {\n upsertState(conversationId, { Archived: archived ? 1 : 0 })\n },\n [upsertState],\n )\n\n const setTrashed = useCallback(\n (conversationId: string, trashed: boolean) => {\n upsertState(conversationId, { Trashed: trashed ? 1 : 0 })\n },\n [upsertState],\n )\n\n const setLabels = useCallback(\n (conversationId: string, labels: string[]) => {\n upsertState(conversationId, { Labels: JSON.stringify(labels) })\n },\n [upsertState],\n )\n\n const setFolder = useCallback(\n (conversationId: string, folder: string) => {\n upsertState(conversationId, { Folder: folder })\n },\n [upsertState],\n )\n\n return {\n conversations: conversations as RecordData<DirectoryConversationData>[],\n ready,\n createChannel,\n createDM,\n createGroupDM,\n lookupByName,\n updateLastMessage,\n readStateMap,\n readMessageCountMap,\n starredSet,\n archivedSet,\n getConversationState,\n upsertState,\n markRead,\n toggleStar,\n setArchived,\n setTrashed,\n setLabels,\n setFolder,\n }\n}\n","/**\n * useCommunities Hook\n *\n * CRUD operations for the `communities` and `memberships` collections\n * in the dir:{appName} DO.\n *\n * Apps that need forums, groups, or boards should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call useCommunities() inside a RecordProvider.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryCommunityData, DirectoryMembershipData } from '../../shared/types'\n\nexport function useCommunities() {\n const { records: communities, status } = useQuery<DirectoryCommunityData>('communities')\n const communityMut = useMutations<DirectoryCommunityData>('communities')\n const { records: memberships } = useQuery<DirectoryMembershipData>('memberships')\n const membershipMut = useMutations<DirectoryMembershipData>('memberships')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const membershipMap = useMemo(() => {\n const map = new Map<string, DirectoryMembershipData[]>()\n for (const m of memberships) {\n const list = map.get(m.data.CommunityId) ?? []\n list.push(m.data)\n map.set(m.data.CommunityId, list)\n }\n return map\n }, [memberships])\n\n const myMemberships = useMemo(\n () => new Set(\n memberships\n .filter((m) => m.data.UserId === user?.id)\n .map((m) => m.data.CommunityId),\n ),\n [memberships, user?.id],\n )\n\n const createCommunity = useCallback(\n async (name: string, opts?: { description?: string; type?: string; visibility?: string; rules?: string }) => {\n const existing = communities.find((c) => c.data.Name === name)\n if (existing) return existing.recordId\n\n const recordId = await communityMut.create({\n Name: name,\n Description: opts?.description ?? '',\n CreatedBy: user?.id ?? '',\n Type: opts?.type ?? 'community',\n Visibility: opts?.visibility ?? 'public',\n MemberCount: 0,\n Rules: opts?.rules ?? '',\n IconUrl: '',\n CoverUrl: '',\n })\n return recordId\n },\n [communityMut, user?.id, communities],\n )\n\n const updateCommunity = useCallback(\n (communityId: string, updates: Partial<DirectoryCommunityData>) => {\n const existing = communities.find((c) => c.recordId === communityId)\n if (!existing) return\n communityMut.put(communityId, { ...existing.data, ...updates })\n },\n [communityMut, communities],\n )\n\n const joinCommunity = useCallback(\n async (communityId: string, userName: string) => {\n if (!user?.id) return null\n const existing = memberships.find(\n (m) => m.data.CommunityId === communityId && m.data.UserId === user.id,\n )\n if (existing) return existing.recordId\n\n const recordId = await membershipMut.create({\n CommunityId: communityId,\n UserId: user.id,\n UserName: userName,\n Role: 'member',\n JoinedAt: new Date().toISOString(),\n })\n return recordId\n },\n [membershipMut, memberships, user?.id],\n )\n\n const leaveCommunity = useCallback(\n (communityId: string) => {\n if (!user?.id) return\n const membership = memberships.find(\n (m) => m.data.CommunityId === communityId && m.data.UserId === user.id,\n )\n if (membership) {\n membershipMut.remove(membership.recordId)\n }\n },\n [membershipMut, memberships, user?.id],\n )\n\n const getMembersOf = useCallback(\n (communityId: string): DirectoryMembershipData[] => {\n return membershipMap.get(communityId) ?? []\n },\n [membershipMap],\n )\n\n const lookupByName = useCallback(\n (name: string) => {\n const found = communities.find((c) => c.data.Name === name)\n return found?.recordId ?? null\n },\n [communities],\n )\n\n return {\n communities: communities as RecordData<DirectoryCommunityData>[],\n memberships: memberships as RecordData<DirectoryMembershipData>[],\n ready,\n myMemberships,\n createCommunity,\n updateCommunity,\n joinCommunity,\n leaveCommunity,\n getMembersOf,\n lookupByName,\n }\n}\n","/**\n * usePosts Hook\n *\n * CRUD operations for the `posts` collection in the dir:{appName} DO.\n *\n * Apps that need feeds, Q&A, or tweet-style content should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call usePosts() inside a RecordProvider.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryPostData } from '../../shared/types'\n\nexport function usePosts(opts?: { communityId?: string }) {\n const { records: allPosts, status } = useQuery<DirectoryPostData>('posts')\n const postMut = useMutations<DirectoryPostData>('posts')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const posts = opts?.communityId\n ? allPosts.filter((p) => p.data.CommunityId === opts.communityId)\n : allPosts\n\n const createPost = useCallback(\n async (data: {\n title: string\n content: string\n type?: string\n communityId?: string\n parentId?: string\n tags?: string[]\n linkUrl?: string\n }) => {\n const recordId = await postMut.create({\n Title: data.title,\n Content: data.content,\n AuthorId: user?.id ?? '',\n Type: data.type ?? 'post',\n CommunityId: data.communityId ?? '',\n ParentId: data.parentId ?? '',\n ConversationId: '',\n Status: 'published',\n Tags: data.tags ? JSON.stringify(data.tags) : '',\n LinkUrl: data.linkUrl ?? '',\n })\n return recordId\n },\n [postMut, user?.id],\n )\n\n const updatePost = useCallback(\n (postId: string, updates: Partial<DirectoryPostData>) => {\n const existing = allPosts.find((p) => p.recordId === postId)\n if (!existing) return\n postMut.put(postId, { ...existing.data, ...updates })\n },\n [postMut, allPosts],\n )\n\n const deletePost = useCallback(\n (postId: string) => {\n postMut.remove(postId)\n },\n [postMut],\n )\n\n const setConversationId = useCallback(\n (postId: string, conversationId: string) => {\n updatePost(postId, { ConversationId: conversationId })\n },\n [updatePost],\n )\n\n return {\n posts: posts as RecordData<DirectoryPostData>[],\n ready,\n createPost,\n updatePost,\n deletePost,\n setConversationId,\n }\n}\n","'use client';\n\nimport React, { useEffect, type ReactNode } from 'react';\nimport type { DeepSpaceThemeConfig } from './types';\nimport { applyDeepSpaceTheme, readThemeFromDOM } from './applyTheme';\n\nexport interface DeepSpaceThemeProviderProps {\n children: ReactNode;\n /**\n * Explicit theme config. If omitted, auto-detects from the widget's\n * --color-* CSS custom properties (defined in the @theme block of styles.css).\n */\n theme?: DeepSpaceThemeConfig;\n}\n\n/**\n * DeepSpaceThemeProvider — sets --theme-* CSS variables for pill,\n * and other DeepSpace UI components on deployed sites and mini-apps.\n *\n * **Zero-config**: reads colors from the widget's @theme CSS block.\n * **Explicit**: pass a `theme` prop to override.\n *\n * @example\n * ```tsx\n * // Zero-config — reads from styles.css @theme block\n * <DeepSpaceThemeProvider>\n * <App />\n * </DeepSpaceThemeProvider>\n *\n * // Explicit theme\n * <DeepSpaceThemeProvider theme={{\n * primaryColor: '#0f172a',\n * secondaryColor: '#1e293b',\n * accentColor: '#8b5cf6',\n * textColor: '#f1f5f9',\n * }}>\n * <App />\n * </DeepSpaceThemeProvider>\n * ```\n */\nexport function DeepSpaceThemeProvider({\n children,\n theme,\n}: DeepSpaceThemeProviderProps): React.ReactElement {\n useEffect(() => {\n const root = document.documentElement;\n const config = theme ?? readThemeFromDOM(root);\n applyDeepSpaceTheme(config, root);\n }, [theme]);\n\n return <>{children}</>;\n}\n","import type { DeepSpaceThemeConfig } from './types';\n\n/**\n * CSS color-mix helper — produces `color-mix(in srgb, color pct%, base)`.\n * Works with any valid CSS color format (hex, rgb, rgba, hsl, named).\n */\nfunction mix(color: string, pct: number, base = 'transparent'): string {\n return `color-mix(in srgb, ${color} ${Math.round(pct * 100)}%, ${base})`;\n}\n\n/**\n * Determine whether a CSS color is \"dark\" using relative luminance.\n */\nexport function isDarkColor(color: string): boolean {\n const c = color.trim();\n\n // getComputedStyle normalises colors to rgb()/rgba() — handle that first.\n const rgbMatch = c.match(/^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)/);\n if (rgbMatch) {\n const r = parseFloat(rgbMatch[1]) / 255;\n const g = parseFloat(rgbMatch[2]) / 255;\n const b = parseFloat(rgbMatch[3]) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.5;\n }\n\n // #hex (#rgb / #rrggbb)\n if (!c.startsWith('#')) return true; // unrecognised format — assume dark\n let hex = c.slice(1);\n if (hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];\n if (hex.length !== 6) return true;\n const r = parseInt(hex.slice(0, 2), 16) / 255;\n const g = parseInt(hex.slice(2, 4), 16) / 255;\n const b = parseInt(hex.slice(4, 6), 16) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.5;\n}\n\n/**\n * Static UI tokens for light themes.\n *\n * KEEP IN SYNC with apps/web/app/styles/tokens.css (:root block)\n *\n * Two delivery paths use these same values:\n * - Web app (SSR): defined in tokens.css (instant, no flash)\n * - Deployed sites: applyDeepSpaceTheme() sets them via JS from these constants\n */\nconst UI_TOKENS_LIGHT: Record<string, string> = {\n '--ui-overlay': 'rgba(0, 0, 0, 0.5)',\n '--ui-bg-primary': '#ffffff',\n '--ui-bg-secondary': '#f9fafb',\n '--ui-bg-tertiary': '#f3f4f6',\n '--ui-bg-elevated': '#ffffff',\n '--ui-border': '#e5e7eb',\n '--ui-border-strong': '#d1d5db',\n '--ui-text-primary': '#111827',\n '--ui-text-secondary': '#6b7280',\n '--ui-text-muted': '#9ca3af',\n '--ui-text-disabled': '#d1d5db',\n '--ui-hover-bg': '#f3f4f6',\n '--ui-success': '#10b981',\n '--ui-warning': '#f59e0b',\n '--ui-error': '#ef4444',\n '--ui-shadow-sm': '0 1px 3px rgba(0, 0, 0, 0.1)',\n '--ui-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.1)',\n '--ui-shadow-lg': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\n '--ui-vote-up': '#f97316',\n '--ui-vote-down': '#3b82f6',\n};\n\n/** Static UI tokens for dark themes — KEEP IN SYNC with [data-ui-theme=\"dark\"] in tokens.css */\nconst UI_TOKENS_DARK: Record<string, string> = {\n '--ui-overlay': 'rgba(0, 0, 0, 0.7)',\n '--ui-bg-primary': '#1a1a1b',\n '--ui-bg-secondary': '#1e1f20',\n '--ui-bg-tertiary': '#2d2e30',\n '--ui-bg-elevated': '#1e1f20',\n '--ui-border': '#3c4043',\n '--ui-border-strong': '#5a5d61',\n '--ui-text-primary': '#e8eaed',\n '--ui-text-secondary': '#bdc1c6',\n '--ui-text-muted': '#9aa0a6',\n '--ui-text-disabled': '#5a5d61',\n '--ui-hover-bg': '#3c4043',\n '--ui-success': '#34d399',\n '--ui-warning': '#fbbf24',\n '--ui-error': '#f87171',\n '--ui-shadow-sm': '0 1px 3px rgba(0, 0, 0, 0.25)',\n '--ui-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.3)',\n '--ui-shadow-lg': '0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.3)',\n '--ui-vote-up': '#f97316',\n '--ui-vote-down': '#60a5fa',\n};\n\n/** All --ui-* property names for cleanup */\nconst UI_TOKEN_PROPERTIES = [\n '--ui-overlay', '--ui-bg-primary', '--ui-bg-secondary', '--ui-bg-tertiary', '--ui-bg-elevated',\n '--ui-border', '--ui-border-strong',\n '--ui-text-primary', '--ui-text-secondary', '--ui-text-muted', '--ui-text-disabled',\n '--ui-accent', '--ui-accent-hover', '--ui-accent-secondary',\n '--ui-hover-bg', '--ui-active-bg', '--ui-active-text',\n '--ui-success', '--ui-warning', '--ui-error',\n '--ui-shadow-sm', '--ui-shadow-md', '--ui-shadow-lg',\n '--ui-vote-up', '--ui-vote-down',\n] as const;\n\n/**\n * All CSS custom properties set by applyDeepSpaceTheme.\n * Used by clearDeepSpaceTheme to remove stale values on theme switch.\n */\nexport const DEEPSPACE_THEME_PROPERTIES = [\n // Panel & background\n '--theme-panel-bg', '--theme-panel-bg-opaque', '--theme-panel-bg-secondary',\n '--theme-panel-solid', '--theme-top-panel-bg', '--theme-panel-border',\n '--theme-panel-highlight', '--theme-background',\n // Buttons\n '--theme-button-bg', '--theme-button-border', '--theme-button-hover',\n '--theme-button-border-hover', '--theme-button-active', '--theme-button-fg',\n // Text\n '--theme-text', '--theme-text-hover', '--theme-text-secondary', '--theme-text-tertiary',\n // Accent & colors\n '--theme-accent', '--theme-accent-contrast', '--theme-accent-hover',\n '--theme-secondary', '--theme-secondary-hover', '--theme-primary-hover',\n // Shadows\n '--theme-shadow-primary', '--theme-shadow-secondary', '--theme-shadow-accent',\n '--theme-component-shadow',\n // Surfaces\n '--theme-surface', '--theme-surface-solid',\n '--theme-library-card-bg', '--theme-library-surface', '--theme-library-panel-glass',\n // Borders\n '--theme-border',\n // Status\n '--theme-destructive', '--theme-destructive-hover',\n '--theme-success', '--theme-warning', '--theme-warning-bg', '--theme-warning-fg',\n // Glass\n '--theme-highlight', '--theme-font',\n '--beveled-gradient', '--beveled-glass-shadow',\n // UI component tokens\n ...UI_TOKEN_PROPERTIES,\n] as const;\n\n/**\n * Remove all CSS custom properties previously set by applyDeepSpaceTheme.\n * Call before re-applying a new theme to prevent stale variable bleed.\n */\nexport function clearDeepSpaceTheme(\n root: HTMLElement = document.documentElement,\n): void {\n for (const prop of DEEPSPACE_THEME_PROPERTIES) {\n root.style.removeProperty(prop);\n }\n}\n\n/**\n * Apply the correct set of --ui-* inline styles for the given UI theme.\n *\n * Single source of truth for --ui-* token application. Called by:\n * - `applyDeepSpaceTheme()` (initial theme setup, canvas theme changes)\n * - `useUITheme` toggle (user switches dark <-> light)\n *\n * When `accent` overrides are provided they are used directly (the\n * `applyDeepSpaceTheme` path). Otherwise the current --theme-accent /\n * --theme-secondary values are read from computed styles.\n */\nexport function applyUIThemeTokens(\n theme: 'dark' | 'light',\n root: HTMLElement = document.documentElement,\n accent?: { color: string; hover: string; secondary: string },\n): void {\n const dark = theme === 'dark';\n\n // Base tokens (surfaces, text, borders, etc.)\n const base = dark ? UI_TOKENS_DARK : UI_TOKENS_LIGHT;\n for (const [prop, val] of Object.entries(base)) {\n root.style.setProperty(prop, val);\n }\n\n // Accent-derived tokens\n const accentColor = accent?.color\n ?? (getComputedStyle(root).getPropertyValue('--theme-accent').trim() || (dark ? '#818cf8' : '#3b82f6'));\n const accentHover = accent?.hover\n ?? `color-mix(in srgb, ${accentColor} 90%, black)`;\n const secondary = accent?.secondary\n ?? (getComputedStyle(root).getPropertyValue('--theme-secondary').trim() || accentColor);\n\n root.style.setProperty('--ui-accent', accentColor);\n root.style.setProperty('--ui-accent-hover', accentHover);\n root.style.setProperty('--ui-accent-secondary', secondary);\n root.style.setProperty('--ui-active-bg', `color-mix(in srgb, ${accentColor} ${dark ? 15 : 10}%, transparent)`);\n root.style.setProperty('--ui-active-text', dark ? secondary : accentColor);\n}\n\n/**\n * Apply a DeepSpace theme by setting CSS custom properties on the given root element.\n *\n * Maps a simplified theme config to the full set of --theme-* CSS variables\n * consumed by DeepSpace UI components, pills, and panels.\n *\n * Uses CSS color-mix() for derived colors so any valid CSS color format works\n * (hex, rgb, rgba, hsl, etc.).\n */\nexport function applyDeepSpaceTheme(\n config: DeepSpaceThemeConfig,\n root: HTMLElement = document.documentElement,\n): void {\n const {\n primaryColor,\n panelColor = primaryColor,\n secondaryColor,\n accentColor,\n accentContrastColor = '#ffffff',\n textColor,\n shadowColor = '#000000',\n borderColor = secondaryColor,\n backgroundColor = primaryColor,\n highlightColor = '#ffffff',\n glassmorphism = true,\n } = config;\n\n // ---------- derived colors ----------\n\n // Panel backgrounds\n const panelBg = glassmorphism ? mix(panelColor, 0.4) : panelColor;\n const panelBgOpaque = glassmorphism ? mix(panelColor, 0.85) : panelColor;\n const panelSolid = glassmorphism ? mix(panelColor, 0.6, 'white') : panelColor;\n const panelBgSecondary = glassmorphism ? mix(secondaryColor, 0.5) : secondaryColor;\n const topPanelBg = glassmorphism ? mix(panelColor, 0.6) : panelColor;\n\n // Borders\n const panelBorder = glassmorphism ? mix(borderColor, 0.3) : borderColor;\n\n // Buttons\n const buttonBg = glassmorphism ? mix(secondaryColor, 0.4) : secondaryColor;\n const buttonBorder = glassmorphism ? mix(borderColor, 0.3) : borderColor;\n const buttonBorderHover = glassmorphism ? mix(borderColor, 0.7) : borderColor;\n const buttonHover = mix(accentColor, 0.2);\n const buttonActive = mix(accentColor, 0.3);\n\n // Text\n const textSecondary = mix(textColor, 0.8);\n const textTertiary = mix(textColor, 0.6);\n\n // Accents\n const accentHover = mix(accentColor, 0.9, 'black');\n const secondary = mix(secondaryColor, 0.9);\n const secondaryHover = mix(secondaryColor, 0.9, 'black');\n const primaryHover = mix(primaryColor, 0.9, 'black');\n\n // Shadows\n const shadowPrimary = mix(shadowColor, 0.1);\n const shadowSecondary = mix(shadowColor, 0.2);\n const shadowAccent = mix(shadowColor, 0.01);\n const componentShadow =\n `0 1px 3px ${mix(shadowColor, 0.12)}, 0 1px 2px ${mix(shadowColor, 0.24)}`;\n\n // Surfaces & highlights\n const surface = mix(primaryColor, 0.95);\n const panelHighlight = glassmorphism ? mix(textColor, 0.05) : 'transparent';\n\n // Glass gradients\n const beveledGradient = `linear-gradient(180deg,color-mix(in srgb, ${highlightColor} 40%, transparent) 0%,color-mix(in srgb, ${highlightColor} 15%, transparent) 15%,color-mix(in srgb, ${highlightColor} 5%, transparent) 50%,color-mix(in srgb, ${highlightColor} 8%, transparent) 85%,color-mix(in srgb, ${highlightColor} 25%, transparent) 100%)`;\n\n // Glass shadows\n const beveledGlassShadow = [\n `inset 0 1px 1px color-mix(in srgb, ${highlightColor} 80%, transparent)`,\n `inset 0 2px 4px color-mix(in srgb, ${highlightColor} 40%, transparent)`,\n `inset 0 -1px 2px rgba(0, 0, 0, 0.08)`,\n `inset 0 -0.5px 0.5px rgba(0, 0, 0, 0.12)`,\n `0 4px 2px -2px rgba(0, 0, 0, 0.12)`,\n `0 8px 16px -4px rgba(0, 0, 0, 0.1)`,\n `0 0 0 0.5px color-mix(in srgb, ${highlightColor} 20%, transparent) inset`,\n ].join(', ');\n\n // ---------- dark/light detection for UI tokens ----------\n // Respect the user's explicit UI theme preference (set by useUITheme via\n // localStorage) if one exists. Only auto-detect from background luminance\n // when no preference has been set (e.g. deployed sites / mini-apps).\n const preferredUITheme = root.dataset.uiTheme;\n const dark = (preferredUITheme === 'dark' || preferredUITheme === 'light')\n ? preferredUITheme === 'dark'\n : isDarkColor(backgroundColor);\n\n // ---------- data attributes ----------\n root.dataset.glassmorphism = glassmorphism ? 'enabled' : 'disabled';\n if (!preferredUITheme) {\n root.dataset.uiTheme = dark ? 'dark' : 'light';\n }\n\n // ---------- batch set CSS properties ----------\n const updates: [string, string][] = [\n // Panel & background\n ['--theme-panel-bg', panelBg],\n ['--theme-panel-bg-opaque', panelBgOpaque],\n ['--theme-panel-bg-secondary', panelBgSecondary],\n ['--theme-panel-solid', panelSolid],\n ['--theme-top-panel-bg', topPanelBg],\n ['--theme-panel-border', panelBorder],\n ['--theme-panel-highlight', panelHighlight],\n ['--theme-background', backgroundColor],\n\n // Buttons\n ['--theme-button-bg', buttonBg],\n ['--theme-button-border', buttonBorder],\n ['--theme-button-hover', buttonHover],\n ['--theme-button-border-hover', buttonBorderHover],\n ['--theme-button-active', buttonActive],\n ['--theme-button-fg', textColor],\n\n // Text\n ['--theme-text', textColor],\n ['--theme-text-hover', textColor],\n ['--theme-text-secondary', textSecondary],\n ['--theme-text-tertiary', textTertiary],\n\n // Accent & colors\n ['--theme-accent', accentColor],\n ['--theme-accent-contrast', accentContrastColor],\n ['--theme-accent-hover', accentHover],\n ['--theme-secondary', secondary],\n ['--theme-secondary-hover', secondaryHover],\n ['--theme-primary-hover', primaryHover],\n\n // Shadows\n ['--theme-shadow-primary', shadowPrimary],\n ['--theme-shadow-secondary', shadowSecondary],\n ['--theme-shadow-accent', shadowAccent],\n ['--theme-component-shadow', componentShadow],\n\n // Surfaces\n ['--theme-surface', surface],\n ['--theme-surface-solid', primaryColor],\n ['--theme-library-card-bg', 'rgba(24, 24, 27, 0.95)'],\n ['--theme-library-surface', 'rgba(9, 9, 11, 0.92)'],\n ['--theme-library-panel-glass', 'rgba(24, 24, 27, 0.85)'],\n\n // Borders\n ['--theme-border', mix(borderColor, 0.8)],\n\n // Status\n ['--theme-destructive', '#FF3B30'],\n ['--theme-destructive-hover', 'rgba(255, 59, 48, 0.1)'],\n ['--theme-success', '#34C759'],\n ['--theme-warning', '#FF9500'],\n ['--theme-warning-bg', 'rgba(245, 158, 11, 0.15)'],\n ['--theme-warning-fg', '#f59e0b'],\n\n // Glass highlight\n ['--theme-highlight', highlightColor],\n\n // Font\n ['--theme-font', \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"],\n\n // Glass gradients & shadows\n ['--beveled-gradient', beveledGradient],\n ['--beveled-glass-shadow', beveledGlassShadow],\n ];\n\n for (const [property, value] of updates) {\n root.style.setProperty(property, value);\n }\n\n // ---------- UI component tokens (modals, profile, library, etc.) ----------\n applyUIThemeTokens(dark ? 'dark' : 'light', root, {\n color: accentColor,\n hover: accentHover,\n secondary,\n });\n}\n\n/**\n * Read a DeepSpace theme config from CSS custom properties on the DOM.\n *\n * Reads the widget template's --color-* variables (from the @theme block)\n * and maps them to a DeepSpaceThemeConfig.\n *\n * Falls back to sensible dark-theme defaults if variables are missing.\n */\nexport function readThemeFromDOM(\n root: HTMLElement = document.documentElement,\n): DeepSpaceThemeConfig {\n const styles = getComputedStyle(root);\n const get = (name: string, fallback: string): string =>\n styles.getPropertyValue(name).trim() || fallback;\n\n return {\n primaryColor: get('--color-surface-elevated', '#0f172a'),\n secondaryColor: get('--color-surface-overlay', '#1e293b'),\n accentColor: get('--color-primary', '#818cf8'),\n textColor: get('--color-content', '#f1f5f9'),\n borderColor: get('--color-border', 'rgba(51, 65, 85, 0.5)'),\n backgroundColor: get('--color-surface', '#0a0f1a'),\n highlightColor: '#ffffff',\n shadowColor: '#000000',\n accentContrastColor: '#ffffff',\n };\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\n/**\n * Reads `data-ui-theme` from the root element (set by `applyDeepSpaceTheme`)\n * and re-evaluates when a `canvas-theme-changed` event fires.\n */\nexport function useIsDarkTheme(): boolean {\n const [isDark, setIsDark] = useState(() =>\n typeof document === 'undefined' || document.documentElement.dataset.uiTheme !== 'light',\n );\n\n useEffect(() => {\n const update = (): void => {\n setIsDark(document.documentElement.dataset.uiTheme !== 'light');\n };\n update();\n window.addEventListener('canvas-theme-changed', update);\n return () => window.removeEventListener('canvas-theme-changed', update);\n }, []);\n\n return isDark;\n}\n","/**\n * PlatformProvider — Zero-cost context for platform worker integration.\n *\n * Always present in the component tree (via template main.tsx), but only\n * activates expensive features (WebSocket connections, polling) when a\n * component subscribes via the corresponding hook.\n *\n * Always available (zero overhead):\n * platformFetch(path, init) — authenticated fetch, prepends /platform\n *\n * Subscription-activated (zero cost until first subscriber):\n * useInbox() — inbox entries from InboxRoom WebSocket\n *\n * Auth uses getAuthToken() from deepspace on demand.\n * The template already provides DeepSpaceAuthProvider.\n *\n * Usage:\n * import { PlatformProvider, usePlatform, useInbox } from 'deepspace'\n *\n * // Already in template main.tsx:\n * <PlatformProvider>\n * <App />\n * </PlatformProvider>\n *\n * // In any component:\n * const { platformFetch } = usePlatform()\n * const inbox = useInbox() // activates WebSocket on mount\n */\n\nimport { createContext, useContext, useState, useEffect, useRef, useCallback } from 'react'\nimport { getAuthToken } from '../auth/token'\n\nexport interface InboxEntry {\n conversationId: string\n scope: { type: string; participants?: string[]; appId?: string; contentRef?: string; ticketNumber?: string }\n displayName: string\n muted: boolean\n joinedAt: string\n lastMessageAt: string | null\n lastMessagePreview: string | null\n lastMessageAuthor: string | null\n unreadCount: number\n}\n\nexport interface PlatformContextValue {\n /** Authenticated fetch — prepends /platform, sets Authorization + Content-Type */\n platformFetch: (path: string, init?: RequestInit) => Promise<Response>\n /** Subscribe to inbox — returns unsubscribe. Internal use by useInbox(). */\n subscribeInbox: () => () => void\n /** Current inbox entries (populated when at least one subscriber is active) */\n inbox: InboxEntry[]\n}\n\nexport const PlatformContext = createContext<PlatformContextValue | null>(null)\n\nexport function usePlatform(): PlatformContextValue {\n const ctx = useContext(PlatformContext)\n if (!ctx) throw new Error('usePlatform must be used within a PlatformProvider')\n return ctx\n}\n\n/**\n * Subscribe to inbox entries from the InboxRoom WebSocket.\n * The WebSocket connects when the first component calls useInbox()\n * and disconnects when the last one unmounts.\n */\nexport function useInbox(): InboxEntry[] {\n const { inbox, subscribeInbox } = usePlatform()\n useEffect(() => subscribeInbox(), [subscribeInbox])\n return inbox\n}\n\nexport function PlatformProvider({ children }: { children: React.ReactNode }) {\n const [inbox, setInbox] = useState<InboxEntry[]>([])\n\n // --- Subscription-activated inbox WebSocket ---\n const inboxSubscribers = useRef(0)\n const [inboxActive, setInboxActive] = useState(false)\n\n const subscribeInbox = useCallback(() => {\n inboxSubscribers.current++\n if (inboxSubscribers.current === 1) setInboxActive(true)\n return () => {\n inboxSubscribers.current--\n if (inboxSubscribers.current === 0) setInboxActive(false)\n }\n }, [])\n\n useEffect(() => {\n if (!inboxActive) return\n\n let mounted = true\n let ws: WebSocket | null = null\n let pingInterval: ReturnType<typeof setInterval>\n let retryTimer: ReturnType<typeof setTimeout>\n\n async function connect() {\n const token = await getAuthToken()\n if (!mounted) return\n if (!token) {\n // Auth not ready yet — retry\n retryTimer = setTimeout(connect, 2_000)\n return\n }\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n ws = new WebSocket(\n `${protocol}//${window.location.host}/platform/ws/inbox?token=${encodeURIComponent(token)}`,\n )\n\n ws.onmessage = (e) => {\n if (e.data === 'pong') return\n try {\n const msg = JSON.parse(e.data)\n switch (msg.type) {\n case 'inbox_init':\n setInbox(msg.entries)\n break\n case 'inbox_added':\n setInbox(prev => [...prev, msg.entry])\n break\n case 'inbox_removed':\n setInbox(prev => prev.filter(x => x.conversationId !== msg.conversationId))\n break\n case 'inbox_updated':\n setInbox(prev =>\n prev.map(x => (x.conversationId === msg.entry.conversationId ? msg.entry : x)),\n )\n break\n }\n } catch {\n // ignore\n }\n }\n\n ws.onclose = () => {\n if (mounted) {\n // Reconnect after brief delay\n retryTimer = setTimeout(connect, 3_000)\n }\n }\n\n pingInterval = setInterval(() => {\n if (ws?.readyState === WebSocket.OPEN) ws.send('ping')\n }, 30_000)\n }\n\n connect()\n\n return () => {\n mounted = false\n clearTimeout(retryTimer)\n clearInterval(pingInterval)\n ws?.close()\n setInbox([])\n }\n }, [inboxActive])\n\n // --- platformFetch — always available, zero overhead until called ---\n const platformFetch = useCallback(async (path: string, init?: RequestInit) => {\n const token = await getAuthToken()\n const headers = new Headers(init?.headers)\n if (token) headers.set('Authorization', `Bearer ${token}`)\n if (!headers.has('Content-Type') && init?.body) headers.set('Content-Type', 'application/json')\n return fetch(`/platform${path}`, { ...init, headers })\n }, [])\n\n return (\n <PlatformContext.Provider value={{ platformFetch, subscribeInbox, inbox }}>\n {children}\n </PlatformContext.Provider>\n )\n}\n","/**\n * usePlatformWS — Generic WebSocket hook for platform DO connections.\n *\n * Handles all the boilerplate:\n * - Auth token fetch\n * - WebSocket connection with wss:// protocol detection\n * - Exponential backoff reconnect (500ms -> 10s max)\n * - Ping every 30s\n * - Cleanup on unmount or scopeId change\n *\n * Usage:\n * const state = usePlatformWS({\n * path: 'orders', // -> /platform/ws/orders/{scopeId}\n * scopeId: 'app:demo-corp',\n * initialState: { orders: [], items: {}, status: 'connecting' },\n * onMessage: (msg, prev) => {\n * switch (msg.type) {\n * case 'init': return { orders: msg.orders, items: msg.items, status: 'connected' }\n * case 'order_created': return { ...prev, orders: [...prev.orders, msg.order] }\n * default: return prev\n * }\n * },\n * })\n */\n\nimport { useState, useEffect, useRef } from 'react'\nimport { getAuthToken } from '../auth/token'\nimport type { ConnectionStatus } from '../storage/connection-status'\n\nconst MAX_RECONNECT_DELAY = 10_000\nconst BASE_RECONNECT_DELAY = 500\n\nexport interface PlatformWSOptions<S> {\n /** DO path segment — e.g. 'orders' for /platform/ws/orders/{scopeId} */\n path: string\n /** Scope ID — e.g. 'app:demo-corp'. Passing undefined skips connection. */\n scopeId: string | undefined\n /** Initial state before WS connects */\n initialState: S\n /**\n * Message handler. Receives the parsed message and current state.\n * Return a new state to update, or the same `prev` reference to skip.\n * The 'init' message should reset reconnect (handled automatically)\n * and return state with status: 'connected'.\n */\n onMessage: (msg: Record<string, unknown>, prev: S) => S\n}\n\nexport interface PlatformWSResult<S> {\n state: S\n /** Send a JSON message to the WebSocket */\n send: (msg: Record<string, unknown>) => void\n}\n\nexport function usePlatformWS<S extends { status: ConnectionStatus }>(\n options: PlatformWSOptions<S>,\n): PlatformWSResult<S> {\n const { path, scopeId, initialState, onMessage } = options\n const wsRef = useRef<WebSocket | null>(null)\n const pingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n const [state, setState] = useState<S>(initialState)\n const reconnectAttemptRef = useRef(0)\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const mountedRef = useRef(true)\n\n // Keep onMessage ref stable to avoid reconnecting when handler identity changes\n const onMessageRef = useRef(onMessage)\n onMessageRef.current = onMessage\n\n const initialStateRef = useRef(initialState)\n initialStateRef.current = initialState\n\n useEffect(() => {\n mountedRef.current = true\n return () => { mountedRef.current = false }\n }, [])\n\n useEffect(() => {\n if (!scopeId) return\n\n setState(initialStateRef.current)\n reconnectAttemptRef.current = 0\n\n async function connect() {\n if (!mountedRef.current || !scopeId) return\n\n const token = await getAuthToken()\n if (!token || !mountedRef.current) {\n reconnectTimerRef.current = setTimeout(connect, 2_000)\n return\n }\n\n const params = new URLSearchParams()\n params.set('token', token)\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const ws = new WebSocket(\n `${protocol}//${window.location.host}/platform/ws/${path}/${scopeId}?${params}`,\n )\n wsRef.current = ws\n\n ws.onmessage = (e) => {\n if (e.data === 'pong') return\n try {\n const msg = JSON.parse(e.data)\n if (msg.type === 'init') {\n reconnectAttemptRef.current = 0\n }\n setState(prev => onMessageRef.current(msg, prev))\n } catch (err) {\n console.error(`[usePlatformWS:${path}] message parse error:`, err)\n }\n }\n\n ws.onclose = () => {\n if (!mountedRef.current) return\n const attempt = reconnectAttemptRef.current++\n const delay = Math.min(BASE_RECONNECT_DELAY * Math.pow(2, attempt), MAX_RECONNECT_DELAY)\n setState(prev => ({\n ...prev,\n status: (attempt === 0 ? 'connecting' : 'reconnecting') as ConnectionStatus,\n }))\n reconnectTimerRef.current = setTimeout(connect, delay)\n }\n\n if (pingIntervalRef.current) clearInterval(pingIntervalRef.current)\n pingIntervalRef.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) ws.send('ping')\n }, 30_000)\n }\n\n connect()\n\n return () => {\n if (reconnectTimerRef.current) {\n clearTimeout(reconnectTimerRef.current)\n reconnectTimerRef.current = null\n }\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current)\n pingIntervalRef.current = null\n }\n wsRef.current?.close()\n wsRef.current = null\n }\n }, [scopeId, path])\n\n const send = useRef((msg: Record<string, unknown>) => {\n wsRef.current?.send(JSON.stringify(msg))\n }).current\n\n return { state, send }\n}\n","/**\n * Integration API client.\n *\n * Plain functions for calling third-party integrations (OpenAI, weather, etc.)\n * through the DeepSpace API worker. Works anywhere — React components,\n * event handlers, server actions, outside React entirely.\n *\n * Usage:\n * import { integration } from 'deepspace'\n * const result = await integration.post('openai/chat-completion', { messages })\n */\n\nimport { getAuthToken } from '../auth/token'\n\nconst ENDPOINT_PREFIX = '/api/integrations'\nconst DEFAULT_TIMEOUT_MS = 120_000\n\ninterface IntegrationResponse<T = unknown> {\n success: boolean\n data?: T\n error?: string\n issues?: Array<{ path?: string[]; message: string; code?: string }>\n}\n\ninterface RequestOptions {\n headers?: Record<string, string>\n timeoutMs?: number\n}\n\nfunction resolveUrl(endpoint: string): string {\n if (endpoint.startsWith('http://') || endpoint.startsWith('https://')) {\n return endpoint\n }\n const path = endpoint.startsWith('/') ? endpoint : endpoint ? `${ENDPOINT_PREFIX}/${endpoint}` : ENDPOINT_PREFIX\n if (typeof window !== 'undefined') {\n return `${window.location.origin}${path}`\n }\n return path\n}\n\nasync function request<T>(\n method: string,\n endpoint: string,\n body?: unknown,\n options?: RequestOptions,\n): Promise<IntegrationResponse<T>> {\n const url = resolveUrl(endpoint)\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options?.headers,\n }\n\n // Attach auth token if available\n try {\n const token = await getAuthToken()\n if (token) headers['Authorization'] = `Bearer ${token}`\n } catch {\n // Not signed in — continue without auth\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), timeoutMs)\n\n try {\n const res = await fetch(url, {\n method,\n headers,\n body: body != null ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n })\n\n let payload: Record<string, unknown>\n try {\n payload = (await res.json()) as Record<string, unknown>\n } catch {\n return { success: false, error: `Request failed (${res.status})` }\n }\n\n if (!res.ok || payload.success === false) {\n return {\n success: false,\n error: (payload.error as string) ?? (payload.message as string) ?? `Request failed (${res.status})`,\n ...(payload.issues ? { issues: payload.issues as IntegrationResponse['issues'] } : {}),\n }\n }\n\n // Normalize response — handle both { success, data } and { success, ...rest }\n if ('data' in payload) {\n return { success: true, data: payload.data as T }\n }\n const { success: _success, ...rest } = payload\n return { success: true, data: rest as T }\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n return { success: false, error: `Request timed out after ${timeoutMs}ms` }\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : 'Request failed',\n }\n } finally {\n clearTimeout(timeout)\n }\n}\n\nexport const integration = {\n post<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('POST', endpoint, data, options)\n },\n get<T = unknown>(endpoint: string, params?: Record<string, string | number | boolean | null | undefined>, options?: RequestOptions) {\n let url = endpoint\n if (params) {\n const searchParams = new URLSearchParams()\n for (const [k, v] of Object.entries(params)) {\n if (v != null) searchParams.set(k, String(v))\n }\n const qs = searchParams.toString()\n if (qs) url = `${endpoint}?${qs}`\n }\n return request<T>('GET', url, undefined, options)\n },\n put<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('PUT', endpoint, data, options)\n },\n delete<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('DELETE', endpoint, data, options)\n },\n}\n\nexport type { IntegrationResponse, RequestOptions }\n","/**\n * Pure decoders for the Vercel AI SDK v5 `toUIMessageStreamResponse` body.\n *\n * The wire format is SSE: each event is `data: <json>\\n\\n`, terminated by\n * `data: [DONE]\\n\\n`. Each event carries a `type` discriminator\n * (`text-delta`, `tool-input-available`, `tool-output-available`,\n * `tool-input-error`, `tool-output-error`, `error`, `abort`, …) — see the\n * `UIMessageChunk` union in `ai/dist/index.d.ts`.\n *\n * This module decodes those chunks into a small action vocabulary that\n * the React layer then applies to its state. Keeping decode pure means\n * the v5-boundary behavior is fully testable without spinning up a\n * component tree.\n */\n\n/** Raw v5 stream chunk, as parsed off the wire. `type` may be any string. */\nexport type AiStreamChunk = Record<string, unknown> & { type?: unknown }\n\n/**\n * Strip one SSE line's framing. Returns the parsed JSON payload, or `null`\n * for blank lines, comment lines (`:` prefix), non-`data:` SSE fields, the\n * `[DONE]` terminator, or any line whose payload doesn't parse as JSON.\n *\n * Multi-line `data:` events (per the SSE spec, joined by `\\n` before\n * dispatch) are NOT supported — v5's emitter never produces them. If you\n * hit a wire intermediary that re-splits long payloads (e.g. a proxy that\n * caps line length), upgrade this to accumulate consecutive `data:` lines\n * until a blank line.\n */\nexport function parseSseLine(line: string): AiStreamChunk | null {\n if (!line) return null\n if (line.startsWith(':')) return null // SSE comment\n if (!line.startsWith('data:')) return null // we only consume `data:` events\n // SSE allows exactly one space after the colon to be elided. Trim a\n // trailing \\r so CRLF-framed responses still hit the [DONE] short-circuit.\n const raw = line.slice(5).replace(/^ /, '').replace(/\\r$/, '')\n if (raw === '[DONE]') return null\n try {\n const parsed: unknown = JSON.parse(raw)\n if (!parsed || typeof parsed !== 'object') return null\n return parsed as AiStreamChunk\n } catch {\n return null\n }\n}\n\n/**\n * Action vocabulary the React layer applies. Every `decodeAiStreamChunk`\n * output is one of these — `null` means the chunk is intentionally ignored\n * (lifecycle markers, reasoning we don't surface yet, etc.).\n *\n * Wire field renames (v5): chunks carry `input` / `output` directly. We\n * map them to `args` / `result` here so persisted UI shapes stay v4-stable.\n */\nexport type AiStreamAction =\n | { type: 'append-text'; delta: string }\n | { type: 'upsert-tool-call'; toolCallId: string; toolName: string; input: unknown }\n | { type: 'finalize-tool-call'; toolCallId: string; result: unknown }\n /**\n * Schema validation rejected the input before the tool ran; no preceding\n * `upsert-tool-call` was emitted, so the React layer must create the\n * invocation and finalize it as failed in one step.\n */\n | { type: 'fail-tool-input'; toolCallId: string; toolName: string; input: unknown; errorText: string }\n /** Tool execution failed; a previous `upsert-tool-call` exists to finalize. */\n | { type: 'fail-tool-output'; toolCallId: string; errorText: string }\n | { type: 'stream-error'; errorText: string }\n /** Server-side abort with no error chunk to follow. */\n | { type: 'abort' }\n\n/** Decode one v5 UIMessage stream chunk into an action, or `null` to ignore. */\nexport function decodeAiStreamChunk(chunk: AiStreamChunk): AiStreamAction | null {\n if (typeof chunk.type !== 'string') return null\n\n switch (chunk.type) {\n case 'text-delta': {\n const delta = typeof chunk.delta === 'string' ? chunk.delta : ''\n if (!delta) return null\n return { type: 'append-text', delta }\n }\n\n case 'tool-input-available': {\n if (typeof chunk.toolCallId !== 'string' || typeof chunk.toolName !== 'string') return null\n return {\n type: 'upsert-tool-call',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: chunk.input,\n }\n }\n\n case 'tool-output-available': {\n if (typeof chunk.toolCallId !== 'string') return null\n // The wire emits `output: part.output` directly (no `toJSONValue`\n // wrapping at this layer). When `part.output` is `undefined`,\n // `JSON.stringify` drops the key entirely, so `'output' in chunk`\n // reads false on the receiving side. Treat absence as an explicit\n // `null` result — finalizing the invocation is what stops the\n // spinner; ignoring the chunk would hang the UI forever for any\n // tool whose `execute` returns undefined.\n const result = 'output' in chunk ? chunk.output : null\n return { type: 'finalize-tool-call', toolCallId: chunk.toolCallId, result }\n }\n\n case 'tool-input-error': {\n if (typeof chunk.toolCallId !== 'string' || typeof chunk.toolName !== 'string') return null\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Tool input rejected'\n return {\n type: 'fail-tool-input',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: chunk.input,\n errorText,\n }\n }\n\n case 'tool-output-error': {\n if (typeof chunk.toolCallId !== 'string') return null\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Tool execution failed'\n return { type: 'fail-tool-output', toolCallId: chunk.toolCallId, errorText }\n }\n\n case 'error': {\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Stream error'\n return { type: 'stream-error', errorText }\n }\n\n case 'abort':\n return { type: 'abort' }\n\n // Forward-compat: silently ignore lifecycle markers (start/finish,\n // start-step/finish-step), text-start/-end, tool-input-start/-delta,\n // reasoning-*, source-*, message-metadata.\n default:\n return null\n }\n}\n","// Per-app subscription state hook. Reads through the starter's same-origin\n// /_deepspace proxy, which signs with the app identity token.\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { getAuthToken } from '../auth/token'\nimport { isEntitled, type PlanInfo, type SubscriptionStatus } from '../../shared/subscription'\n\n// Re-export for SDK consumers — these are public types the hook is generic over.\nexport type { SubscriptionStatus, PlanInfo }\n\nexport interface SubscriptionState {\n tier: string\n status: SubscriptionStatus\n /** Billing interval of the active subscription, or null for free / no sub. */\n interval: 'month' | 'year' | null\n currentPeriodEnd: number | null\n cancelAtPeriodEnd: boolean\n trialEndsAt: number | null\n plans: PlanInfo[]\n}\n\nexport interface SubscribeOpts {\n interval?: 'month' | 'year'\n returnUrl?: string\n cancelUrl?: string\n}\n\nexport interface SubscribeResult {\n url: string | null\n immediate: boolean\n requiresPayment?: boolean\n hostedInvoiceUrl?: string | null\n}\n\ninterface UseSubscriptionReturn {\n tier: string\n status: SubscriptionStatus\n /**\n * True iff status is `active` or `trialing`. `hasTier` and `isAtLeast`\n * already encode this — read `entitled` only when you need the raw boolean\n * without picking a tier.\n */\n entitled: boolean\n /** Current billing interval, or null when on free / no subscription. */\n interval: 'month' | 'year' | null\n currentPeriodEnd: number | null\n cancelAtPeriodEnd: boolean\n trialEndsAt: number | null\n isLoading: boolean\n error: string | null\n /**\n * Returns true only when `tier === slug` AND the subscription is currently\n * entitled (status ∈ {active, trialing}). A `past_due` / `canceled` /\n * `unpaid` subscription that still has a stored paid tier returns false.\n * The free tier is always entitled.\n */\n hasTier: (slug: string) => boolean\n /**\n * Returns true when the tier's rank meets-or-exceeds `slug` AND the\n * subscription is currently entitled. Same entitlement gate as `hasTier`.\n */\n isAtLeast: (slug: string) => boolean\n /** Plan catalog from /me — pass into `<PricingTable plans={...}>` directly. */\n plans: PlanInfo[]\n subscribe: (planSlug: string, opts?: SubscribeOpts) => Promise<SubscribeResult>\n openPortal: (returnUrl?: string) => Promise<{ url: string }>\n refresh: () => Promise<void>\n}\n\nasync function authedJson<T>(path: string, init?: RequestInit): Promise<T> {\n const token = await getAuthToken()\n const res = await fetch(path, {\n ...init,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...init?.headers,\n },\n })\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>\n if (!res.ok) {\n throw new Error((data.error as string) ?? `Request failed (${res.status})`)\n }\n return data as T\n}\n\nexport function useSubscription(): UseSubscriptionReturn {\n const [state, setState] = useState<SubscriptionState>({\n tier: 'free',\n status: 'none',\n interval: null,\n currentPeriodEnd: null,\n cancelAtPeriodEnd: false,\n trialEndsAt: null,\n plans: [],\n })\n const [isLoading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n setLoading(true)\n try {\n const r = await authedJson<SubscriptionState>('/_deepspace/subscriptions/me')\n setState({\n tier: r.tier,\n status: r.status,\n interval: r.interval ?? null,\n currentPeriodEnd: r.currentPeriodEnd,\n cancelAtPeriodEnd: r.cancelAtPeriodEnd,\n trialEndsAt: r.trialEndsAt,\n plans: r.plans ?? [],\n })\n setError(null)\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to load subscription')\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n const entitled = isEntitled(state.tier, state.status)\n const hasTier = useCallback(\n (slug: string) => state.tier === slug && isEntitled(state.tier, state.status),\n [state.tier, state.status],\n )\n const isAtLeast = useCallback(\n (slug: string) => {\n if (!isEntitled(state.tier, state.status)) return false\n const targetRank = state.plans.find((p) => p.slug === slug)?.rank\n const currentRank = state.plans.find((p) => p.slug === state.tier)?.rank\n if (targetRank == null || currentRank == null) return false\n return currentRank >= targetRank\n },\n [state.plans, state.tier, state.status],\n )\n\n const subscribe = useCallback(\n async (planSlug: string, opts?: SubscribeOpts): Promise<SubscribeResult> => {\n const result = await authedJson<SubscribeResult>('/_deepspace/subscriptions/checkout', {\n method: 'POST',\n body: JSON.stringify({\n planSlug,\n interval: opts?.interval ?? 'month',\n returnUrl: opts?.returnUrl ?? window.location.href,\n cancelUrl: opts?.cancelUrl ?? window.location.href,\n requestNonce: crypto.randomUUID(),\n }),\n })\n if (result.immediate) await refresh()\n // Auto-redirect when the server tells us to navigate. `result.url` is\n // populated in every redirect-bound case: Stripe Checkout session URL\n // (new sub), returnUrl (immediate in-place tier/interval change), and\n // hostedInvoiceUrl (SCA-pending proration). Matches useCheckout's\n // chargeOnce behavior so docs that show `await sub.subscribe('pro')`\n // and expect a redirect actually work without extra plumbing.\n if (typeof window !== 'undefined' && result.url) {\n window.location.href = result.url\n }\n return result\n },\n [refresh],\n )\n\n const openPortal = useCallback(\n async (returnUrl?: string) => {\n return authedJson<{ url: string }>('/_deepspace/subscriptions/portal', {\n method: 'POST',\n body: JSON.stringify({ returnUrl: returnUrl ?? window.location.href }),\n })\n },\n [],\n )\n\n return {\n tier: state.tier,\n status: state.status,\n entitled,\n interval: state.interval,\n currentPeriodEnd: state.currentPeriodEnd,\n cancelAtPeriodEnd: state.cancelAtPeriodEnd,\n trialEndsAt: state.trialEndsAt,\n isLoading,\n error,\n hasTier,\n isAtLeast,\n plans: state.plans,\n subscribe,\n openPortal,\n refresh,\n }\n}\n","/**\n * Subscription primitives shared between client (useSubscription hook) and\n * server (requireSubscription helper). Pulled into a shared module so the\n * entitlement gate has a single source of truth — if it ever diverges between\n * client and server, gated features silently disagree about who's allowed in,\n * which is a security bug, not a UX bug.\n */\n\nexport type SubscriptionStatus =\n | 'none'\n | 'trialing'\n | 'active'\n | 'past_due'\n | 'canceled'\n | 'incomplete'\n | 'incomplete_expired'\n | 'unpaid'\n | 'paused'\n\n/** Per-interval price advertised by a plan. */\nexport interface PlanPrice {\n interval: 'month' | 'year'\n priceCents: number\n currency?: string\n}\n\n/**\n * Plan shape returned by `/api/subscriptions/me` and consumed directly by\n * `<PricingTable plans={sub.plans}>`. Fields beyond slug/rank are optional so\n * a free tier (no prices, no trial) doesn't need to fabricate them.\n */\nexport interface PlanInfo {\n slug: string\n rank: number\n name: string\n trialDays?: number | null\n prices: PlanPrice[]\n}\n\n// Statuses that grant access to paid features. Other statuses (past_due,\n// unpaid, incomplete, paused, canceled) keep the user's recorded planSlug so\n// the UI can surface \"your Pro plan is past-due\" — but they MUST NOT unlock.\n//\n// Typed as `ReadonlySet<string>` (not `Set<SubscriptionStatus>`) so callers\n// passing a server-supplied string don't need a runtime cast; unknown statuses\n// fall through as \"not entitled\", which is the safe default.\nexport const ENTITLED_STATUSES: ReadonlySet<string> = new Set([\n 'active',\n 'trialing',\n])\n\n/**\n * True iff the subscription currently grants access to paid features.\n *\n * - Free tier always counts as entitled — no payment required.\n * - Otherwise the status must be in `ENTITLED_STATUSES`.\n *\n * `status` is typed as `string` deliberately: server responses can carry\n * statuses we haven't enumerated yet (e.g. if Stripe adds a new one), and\n * those should fall through as not-entitled rather than crashing the check.\n */\nexport function isEntitled(tier: string, status: string): boolean {\n if (tier === 'free') return true\n return ENTITLED_STATUSES.has(status)\n}\n","// Minimal pre-fab pricing UI. Stateless: pass in `plans` from\n// `useSubscription().plans` and an `onSelect` callback that calls\n// `useSubscription().subscribe()`. Apps that want their own design can ignore\n// this and roll their own; this is just the \"works out of the box\" path for\n// starter apps.\n\nimport type { PlanInfo, PlanPrice } from '../../shared/subscription'\n\n// Re-export shared types so callers can do\n// `import { PricingTablePlan } from 'deepspace'` without reaching into shared.\nexport type PricingTablePrice = PlanPrice\nexport type PricingTablePlan = PlanInfo\n\nexport function PricingTable(props: {\n plans: PricingTablePlan[]\n interval?: 'month' | 'year'\n currentTier?: string\n onSelect: (planSlug: string, interval: 'month' | 'year') => void | Promise<void>\n}) {\n const interval = props.interval ?? 'month'\n return (\n <div className=\"grid gap-4 md:grid-cols-3\">\n {props.plans.map((plan) => {\n const price = plan.prices.find((p) => p.interval === interval)\n const selected = props.currentTier === plan.slug\n // A plan is truly free only if it has no priced interval at all.\n // If `price` is missing but the plan has prices on OTHER intervals,\n // this interval is unavailable — clicking checkout would fail with\n // `unknown_price`, so we render \"Unavailable\" and disable the button\n // instead of mislabeling it as free.\n const isTrueFree = plan.prices.length === 0\n const otherIntervals = plan.prices\n .map((p) => p.interval)\n .filter((i) => i !== interval)\n const intervalUnavailable = !price && !isTrueFree\n const onlyInterval = otherIntervals.length === 1 ? otherIntervals[0] : null\n const unavailableLabel = onlyInterval\n ? onlyInterval === 'month'\n ? 'Monthly only'\n : 'Yearly only'\n : 'Unavailable'\n const priceLabel = price\n ? `$${(price.priceCents / 100).toFixed(0)}`\n : isTrueFree\n ? 'Free'\n : unavailableLabel\n const disabled = selected || intervalUnavailable\n return (\n <section key={plan.slug} className=\"rounded-lg border border-border p-5\">\n <div className=\"space-y-1\">\n <h3 className=\"text-lg font-semibold\">{plan.name}</h3>\n <p className=\"text-3xl font-semibold\">\n {priceLabel}\n <span className=\"text-sm font-normal text-muted-foreground\">\n {price ? `/${interval}` : ''}\n </span>\n </p>\n {plan.trialDays ? (\n <p className=\"text-xs text-muted-foreground\">{plan.trialDays}-day free trial</p>\n ) : null}\n </div>\n <button\n type=\"button\"\n disabled={disabled}\n onClick={() => void props.onSelect(plan.slug, interval)}\n className=\"mt-5 w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {selected\n ? 'Current plan'\n : intervalUnavailable\n ? unavailableLabel\n : 'Select plan'}\n </button>\n </section>\n )\n })}\n </div>\n )\n}\n","// One-time charge hook. Two modes:\n//\n// 1. Server-declared product (`chargeOnce({ productId })`): the platform\n// resolves amount/name from your declared product catalog. The browser\n// can't pick `productId` + `amount` together — only the declared\n// amount is charged. This is the only entitlement-safe mode:\n// `useCheckout({productId}).owned` answers truthfully.\n//\n// 2. Ad-hoc (`chargeOnce({ amount, name })`): tips, donations, dynamic\n// amounts. The resulting invoice has no `productId` so `ownsProduct()`\n// cannot satisfy gating against it. Use for collection, not unlock.\n//\n// To declare products, POST to `/api/charges/products/sync` from a deploy\n// step or admin tool with `{appName, products: [{productId, name,\n// amountCents}]}`. Products dropped from a later sync are deactivated.\n//\n// The hook fetches the customer's purchase history on mount, caches it in\n// state, and exposes `owned` + `ownsProduct(id)` for gating features behind\n// a one-time purchase the same way `useSubscription().tier` gates behind a\n// recurring plan.\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { getAuthToken } from '../auth/token'\n\ninterface ChargeRedirectOpts {\n /** Defaults to window.location.href. */\n returnUrl?: string\n /** Defaults to window.location.href. */\n cancelUrl?: string\n}\n\n/**\n * Product-mode charge: amount, name, and currency are resolved server-side\n * from the developer's declared product catalog (`src/products.ts`). The\n * browser cannot influence the price — this is the only entitlement-safe\n * shape because `useCheckout({productId}).owned` can be trusted afterwards.\n */\nexport interface ProductChargeOpts extends ChargeRedirectOpts {\n productId: string\n}\n\n/**\n * Ad-hoc charge: tips, donations, \"name your price\". Caller supplies the\n * amount and display name; the resulting invoice has `productId=null`, so\n * `ownsProduct()` will never report ownership against it. Use for revenue\n * collection, not for feature gating.\n */\nexport interface AdHocChargeOpts extends ChargeRedirectOpts {\n /** Amount in cents. Minimum 100 (Stripe fees eat smaller amounts). */\n amount: number\n /** Product name shown in Checkout and on the customer's receipt. */\n name: string\n /** Optional description rendered under the product name. */\n description?: string\n /** Must be omitted in ad-hoc mode — the never type makes the union disjoint. */\n productId?: never\n}\n\n/**\n * `chargeOnce` accepts either a `productId` (server-resolves price/name) or\n * an `amount`+`name` pair (ad-hoc). The two are mutually exclusive at the\n * type level so the safe path doesn't require dummy amount/name fields.\n */\nexport type ChargeOnceOpts = ProductChargeOpts | AdHocChargeOpts\n\nexport interface ChargeOnceResult {\n url: string\n}\n\nexport interface Purchase {\n /** Internal invoice row id. Stable across refetches. */\n id: string\n /** Developer-supplied product id, or null for pre-entitlement rows. */\n productId: string | null\n /** Display name captured at checkout time. */\n name: string\n /** Amount paid in cents (post-tax — uses Stripe's `amount_total`). */\n amount: number\n currency: string\n /** ISO timestamp of the payment. */\n paidAt: string\n}\n\nexport interface UseCheckoutOpts {\n /**\n * Product id to derive `owned` against. Without this, `owned` is always\n * false — the hook still surfaces `purchases` and `ownsProduct` for\n * callers that need to ask about more than one product.\n */\n productId?: string\n}\n\ninterface UseCheckoutReturn {\n // Action surface\n chargeOnce: (opts: ChargeOnceOpts) => Promise<ChargeOnceResult>\n isLoading: boolean\n error: string | null\n\n // Read surface\n purchases: Purchase[]\n /** True iff `opts.productId` was provided and a non-fully-refunded row matches. */\n owned: boolean\n /** Pure function over the in-memory `purchases` array. No network. */\n ownsProduct: (productId: string) => boolean\n /** Re-fetch the purchase list. Useful right after a successful checkout. */\n refresh: () => Promise<void>\n}\n\nasync function authedJson<T>(path: string, init?: RequestInit): Promise<T> {\n const token = await getAuthToken()\n const res = await fetch(path, {\n ...init,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...init?.headers,\n },\n })\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>\n if (!res.ok) {\n throw new Error((data.error as string) ?? `Request failed (${res.status})`)\n }\n return data as T\n}\n\nexport function useCheckout(opts?: UseCheckoutOpts): UseCheckoutReturn {\n const [purchases, setPurchases] = useState<Purchase[]>([])\n const [isLoading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n // No productId param on the fetch — the hook caches the full list and the\n // per-product question is answered in-memory. Cheaper than refetching on\n // every productId change and lets one component check ownership of N\n // products without N requests.\n const refresh = useCallback(async () => {\n setLoading(true)\n try {\n const r = await authedJson<{ purchases: Purchase[] }>(\n '/_deepspace/charges/me',\n )\n setPurchases(r.purchases ?? [])\n setError(null)\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to load purchases')\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n const chargeOnce = useCallback(\n async (chargeOpts: ChargeOnceOpts): Promise<ChargeOnceResult> => {\n // Note: isLoading intentionally not toggled here — it tracks the\n // fetch lifecycle (initial + refresh), not the chargeOnce redirect.\n // Mirrors the v1 semantics callers already depend on.\n setError(null)\n\n // Build the request body by mode. In product mode we deliberately\n // omit amount/name from the wire — the server resolves them from the\n // declared catalog and would ignore client values anyway, but sending\n // them keeps the dangerous \"browser picks the price\" shape on the\n // wire. In ad-hoc mode we send what the caller supplied.\n const common = {\n returnUrl: chargeOpts.returnUrl ?? window.location.href,\n cancelUrl: chargeOpts.cancelUrl ?? window.location.href,\n requestNonce: crypto.randomUUID(),\n }\n const body =\n chargeOpts.productId !== undefined\n ? { ...common, productId: chargeOpts.productId }\n : {\n ...common,\n amount: chargeOpts.amount,\n name: chargeOpts.name,\n ...(chargeOpts.description ? { description: chargeOpts.description } : {}),\n }\n\n try {\n const result = await authedJson<{ url: string }>(\n '/_deepspace/charges/create',\n {\n method: 'POST',\n body: JSON.stringify(body),\n },\n )\n if (typeof window !== 'undefined' && result.url) {\n window.location.href = result.url\n }\n return result\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Failed to start checkout'\n setError(msg)\n throw e\n }\n },\n [],\n )\n\n const ownsProduct = useCallback(\n (productId: string) => purchases.some((p) => p.productId === productId),\n [purchases],\n )\n\n // `owned` is the convenience binding for the single-product case. Vacuously\n // false when no productId was passed to the hook — the caller didn't ask a\n // question, so the answer is \"no entitlement\".\n const owned = useMemo(\n () => !!opts?.productId && purchases.some((p) => p.productId === opts.productId),\n [opts?.productId, purchases],\n )\n\n return {\n chargeOnce,\n isLoading,\n error,\n purchases,\n owned,\n ownsProduct,\n refresh,\n }\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'relative rounded-2xl border border-border bg-card text-card-foreground shadow-card',\n className\n )}\n {...props}\n />\n))\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1.5 p-4 sm:p-6', className)}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-4 pt-0 sm:p-6 sm:pt-0', className)} {...props} />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-4 pt-0 sm:p-6 sm:pt-0', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n","import * as React from 'react'\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\n\nimport { cn } from './utils'\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = 'horizontal', decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'shrink-0 bg-border',\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn('w-full caption-bottom text-sm', className)}\n {...props}\n />\n </div>\n))\nTable.displayName = 'Table'\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />\n))\nTableHeader.displayName = 'TableHeader'\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n))\nTableBody.displayName = 'TableBody'\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',\n className\n )}\n {...props}\n />\n))\nTableFooter.displayName = 'TableFooter'\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',\n className\n )}\n {...props}\n />\n))\nTableRow.displayName = 'TableRow'\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n 'h-10 px-2 sm:px-3 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n className\n )}\n {...props}\n />\n))\nTableHead.displayName = 'TableHead'\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\n 'p-2 sm:p-3 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n className\n )}\n {...props}\n />\n))\nTableCell.displayName = 'TableCell'\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn('mt-4 text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nTableCaption.displayName = 'TableCaption'\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","import * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\n\nimport { cn } from './utils'\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground overflow-x-auto max-w-full',\n className\n )}\n {...props}\n />\n))\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n className\n )}\n {...props}\n />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n","import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default:\n 'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n outline:\n 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3 text-xs',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, loading = false, disabled, children, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={disabled || loading}\n {...props}\n >\n {loading && (\n <span className=\"w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin\" />\n )}\n {children}\n </Comp>\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<'textarea'>\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n 'flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = 'Textarea'\n\nexport { Textarea }\n","import * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'relative z-50 max-h-96 min-w-[8rem] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-sm font-semibold', className)}\n {...props}\n />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center rounded-sm py-2 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n}\n","import * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { Check } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn('grid place-content-center text-current')}\n >\n <Check className=\"h-4 w-4\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n","import * as React from 'react'\nimport * as SwitchPrimitives from '@radix-ui/react-switch'\n\nimport { cn } from './utils'\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n 'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',\n className\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n 'pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'\n )}\n />\n </SwitchPrimitives.Root>\n))\nSwitch.displayName = SwitchPrimitives.Root.displayName\n\nexport { Switch }\n","import * as React from 'react'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst labelVariants = cva(\n 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'\n)\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full border font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n variant: {\n default:\n 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',\n secondary:\n 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n destructive:\n 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',\n outline: 'text-foreground',\n success:\n 'border-transparent bg-success text-success-foreground shadow hover:bg-success/80',\n warning:\n 'border-transparent bg-warning text-warning-foreground shadow hover:bg-warning/80',\n info:\n 'border-transparent bg-info text-info-foreground shadow hover:bg-info/80',\n },\n size: {\n default: 'px-2.5 py-0.5 text-xs',\n sm: 'px-2 py-px text-[10px]',\n lg: 'px-3 py-1 text-sm',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, size, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant, size }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n","import * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\n\nimport { cn } from './utils'\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(\n 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',\n className\n )}\n {...props}\n />\n))\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn('aspect-square h-full w-full', className)}\n {...props}\n />\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n 'flex h-full w-full items-center justify-center rounded-full bg-muted',\n className\n )}\n {...props}\n />\n))\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","import * as React from 'react'\nimport * as ProgressPrimitive from '@radix-ui/react-progress'\n\nimport { cn } from './utils'\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-primary/20',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n))\nProgress.displayName = ProgressPrimitive.Root.displayName\n\nexport { Progress }\n","import React, { type ReactNode, type JSX } from 'react'\n\nimport { cn } from './utils'\n\n// ============================================================================\n// Skeleton - Base skeleton component (shadcn-compatible)\n// ============================================================================\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-primary/10', className)}\n {...props}\n />\n )\n}\n\n// ============================================================================\n// SkeletonText - Text line skeleton\n// ============================================================================\n\ninterface SkeletonTextProps {\n lines?: number\n lastLineWidth?: string\n className?: string\n}\n\nfunction SkeletonText({\n lines = 3,\n lastLineWidth = '60%',\n className = '',\n}: SkeletonTextProps): JSX.Element {\n return (\n <div className={cn('space-y-2', className)}>\n {Array.from({ length: lines }).map((_, i) => (\n <Skeleton\n key={i}\n className=\"h-4\"\n style={{ width: i === lines - 1 ? lastLineWidth : '100%' }}\n />\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonCard - Card skeleton\n// ============================================================================\n\ninterface SkeletonCardProps {\n hasImage?: boolean\n className?: string\n}\n\nfunction SkeletonCard({ hasImage = false, className = '' }: SkeletonCardProps): JSX.Element {\n return (\n <div className={cn('border border-border rounded-lg overflow-hidden', className)}>\n {hasImage && <Skeleton className=\"w-full h-32 rounded-none\" />}\n <div className=\"p-4 space-y-3\">\n <Skeleton className=\"h-5 w-3/4\" />\n <SkeletonText lines={2} />\n <Skeleton className=\"h-3 w-1/3\" />\n </div>\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonList - List skeleton\n// ============================================================================\n\ninterface SkeletonListProps {\n items?: number\n className?: string\n}\n\nfunction SkeletonList({ items = 5, className = '' }: SkeletonListProps): JSX.Element {\n return (\n <div className={cn('space-y-3', className)}>\n {Array.from({ length: items }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 p-3 border border-border rounded-lg\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n <Skeleton className=\"w-16 h-6\" />\n </div>\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonTable - Table skeleton\n// ============================================================================\n\ninterface SkeletonTableProps {\n rows?: number\n columns?: number\n className?: string\n}\n\nfunction SkeletonTable({\n rows = 5,\n columns = 4,\n className = '',\n}: SkeletonTableProps): JSX.Element {\n return (\n <div className={cn('border border-border rounded-lg overflow-hidden', className)}>\n {/* Header */}\n <div className=\"flex gap-4 p-4 bg-muted/50 border-b border-border\">\n {Array.from({ length: columns }).map((_, i) => (\n <Skeleton key={i} className=\"h-4 flex-1\" />\n ))}\n </div>\n {/* Rows */}\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <div key={rowIndex} className=\"flex gap-4 p-4 border-b border-border last:border-0\">\n {Array.from({ length: columns }).map((_, colIndex) => (\n <Skeleton\n key={colIndex}\n className=\"h-4 flex-1\"\n style={{ width: colIndex === 0 ? '40%' : undefined }}\n />\n ))}\n </div>\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonAvatar - Avatar skeleton\n// ============================================================================\n\ninterface SkeletonAvatarProps {\n size?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction SkeletonAvatar({ size = 'md', className = '' }: SkeletonAvatarProps): JSX.Element {\n const sizes = {\n sm: 'w-8 h-8',\n md: 'w-10 h-10',\n lg: 'w-12 h-12',\n }\n\n return <Skeleton className={cn(sizes[size], 'rounded-full', className)} />\n}\n\n// ============================================================================\n// LoadingSpinner - Simple spinner\n// ============================================================================\n\ninterface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction LoadingSpinner({ size = 'md', className = '' }: LoadingSpinnerProps): JSX.Element {\n const sizes = {\n sm: 'w-4 h-4',\n md: 'w-6 h-6',\n lg: 'w-8 h-8',\n }\n\n return (\n <div\n className={cn(sizes[size], 'border-2 border-muted border-t-primary rounded-full animate-spin', className)}\n />\n )\n}\n\n// ============================================================================\n// LoadingOverlay - Full-page or container loading\n// ============================================================================\n\ninterface LoadingOverlayProps {\n children?: ReactNode\n message?: string\n className?: string\n}\n\nfunction LoadingOverlay({\n children,\n message,\n className = '',\n}: LoadingOverlayProps): JSX.Element {\n return (\n <div className={cn('flex flex-col items-center justify-center py-16', className)}>\n <LoadingSpinner size=\"lg\" />\n {message && <p className=\"mt-4 text-muted-foreground\">{message}</p>}\n {children}\n </div>\n )\n}\n\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n SkeletonAvatar,\n LoadingSpinner,\n LoadingOverlay,\n}\n","import React, { ReactNode, JSX } from 'react'\nimport { MoreHorizontal, Trash2 } from 'lucide-react'\nimport { cn } from './utils'\n\n// ============================================================================\n// CardGrid - Responsive grid container\n// ============================================================================\n\ninterface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n columns?: 1 | 2 | 3 | 4\n}\n\nexport function CardGrid({ children, columns = 3, className = '', ...rest }: CardGridProps): JSX.Element {\n const gridCols = {\n 1: 'grid-cols-1',\n 2: 'grid-cols-1 sm:grid-cols-2',\n 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',\n }\n\n return (\n <div className={cn('grid gap-3 sm:gap-4', gridCols[columns], className)} {...rest}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard - Base card component (named GridCard to avoid conflict with shadcn Card)\n// ============================================================================\n\ninterface GridCardProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n onClick?: () => void\n hoverable?: boolean\n}\n\nexport function GridCard({ children, onClick, className = '', hoverable = true, ...rest }: GridCardProps): JSX.Element {\n return (\n <div\n onClick={onClick}\n className={cn(\n 'group relative bg-card rounded-xl border border-border overflow-hidden transition-all duration-200',\n hoverable && 'hover:border-border hover:shadow-card-hover hover:-translate-y-0.5',\n onClick && 'cursor-pointer',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Image - Optional image header\n// ============================================================================\n\ninterface GridCardImageProps {\n src: string\n alt?: string\n height?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction GridCardImage({ src, alt = '', height = 'md', className = '' }: GridCardImageProps): JSX.Element {\n const heights = {\n sm: 'h-24',\n md: 'h-36',\n lg: 'h-48',\n }\n\n return (\n <div className={cn(heights[height], 'overflow-hidden bg-muted', className)}>\n <img\n src={src}\n alt={alt}\n referrerPolicy=\"no-referrer\"\n className=\"w-full h-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Header - Title area with optional actions\n// ============================================================================\n\ninterface GridCardHeaderProps {\n children: ReactNode\n actions?: ReactNode\n className?: string\n}\n\nfunction GridCardHeader({ children, actions, className = '' }: GridCardHeaderProps): JSX.Element {\n return (\n <div className={cn('flex items-start justify-between gap-2 p-4 pb-2', className)}>\n <div className=\"flex-1 min-w-0\">{children}</div>\n {actions && (\n <div className=\"sm:opacity-0 sm:group-hover:opacity-100 transition-opacity shrink-0\">\n {actions}\n </div>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Title\n// ============================================================================\n\ninterface GridCardTitleProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardTitle({ children, className = '' }: GridCardTitleProps): JSX.Element {\n return (\n <h3 className={cn('font-semibold text-foreground truncate', className)}>\n {children}\n </h3>\n )\n}\n\n// ============================================================================\n// GridCard.Content - Main content area\n// ============================================================================\n\ninterface GridCardContentProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardContent({ children, className = '' }: GridCardContentProps): JSX.Element {\n return (\n <div className={cn('px-4 pb-4', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Description - Muted text with line clamp\n// ============================================================================\n\ninterface GridCardDescriptionProps {\n children: ReactNode\n lines?: 1 | 2 | 3 | 4\n className?: string\n}\n\nfunction GridCardDescription({ children, lines = 2, className = '' }: GridCardDescriptionProps): JSX.Element {\n const lineClamp = {\n 1: 'line-clamp-1',\n 2: 'line-clamp-2',\n 3: 'line-clamp-3',\n 4: 'line-clamp-4',\n }\n\n return (\n <p className={cn('text-sm text-muted-foreground leading-relaxed', lineClamp[lines], className)}>\n {children}\n </p>\n )\n}\n\n// ============================================================================\n// GridCard.Footer - Bottom area for meta info\n// ============================================================================\n\ninterface GridCardFooterProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardFooter({ children, className = '' }: GridCardFooterProps): JSX.Element {\n return (\n <div className={cn('px-4 pb-4 pt-2 text-xs text-muted-foreground', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Badge - Status badge\n// ============================================================================\n\ninterface GridCardBadgeProps {\n children: ReactNode\n variant?: 'default' | 'success' | 'warning' | 'danger'\n className?: string\n}\n\nfunction GridCardBadge({ children, variant = 'default', className = '' }: GridCardBadgeProps): JSX.Element {\n const variants = {\n default: 'bg-muted text-muted-foreground border-border',\n success: 'bg-success/20 text-success border-success/40',\n warning: 'bg-warning/20 text-warning border-warning/40',\n danger: 'bg-destructive/20 text-destructive border-destructive/40',\n }\n\n return (\n <span className={cn('inline-flex px-2 py-0.5 text-xs font-medium rounded border', variants[variant], className)}>\n {children}\n </span>\n )\n}\n\n// ============================================================================\n// GridCard.Actions - Common action buttons\n// ============================================================================\n\ninterface GridCardActionsProps {\n onDelete?: () => void\n onMore?: () => void\n}\n\nfunction GridCardActions({ onDelete, onMore }: GridCardActionsProps): JSX.Element {\n const handleClick = (e: React.MouseEvent, handler?: () => void): void => {\n e.stopPropagation()\n handler?.()\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n {onMore && (\n <button\n onClick={(e) => handleClick(e, onMore)}\n className=\"p-2 rounded-lg bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n >\n <MoreHorizontal className=\"w-4 h-4\" />\n </button>\n )}\n {onDelete && (\n <button\n onClick={(e) => handleClick(e, onDelete)}\n className=\"p-2 rounded-lg bg-muted/50 hover:bg-destructive/20 text-muted-foreground hover:text-destructive transition-colors\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// Attach sub-components\n// ============================================================================\n\nGridCard.Image = GridCardImage\nGridCard.Header = GridCardHeader\nGridCard.Title = GridCardTitle\nGridCard.Content = GridCardContent\nGridCard.Description = GridCardDescription\nGridCard.Footer = GridCardFooter\nGridCard.Badge = GridCardBadge\nGridCard.Actions = GridCardActions\n\nexport default GridCard\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive [&>svg]:text-destructive',\n success:\n 'border-success/50 text-success [&>svg]:text-success',\n warning:\n 'border-warning/50 text-warning [&>svg]:text-warning',\n info:\n 'border-info/50 text-info [&>svg]:text-info',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n))\nAlert.displayName = 'Alert'\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n))\nAlertTitle.displayName = 'AlertTitle'\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm [&_p]:leading-relaxed', className)}\n {...props}\n />\n))\nAlertDescription.displayName = 'AlertDescription'\n\nexport { Alert, AlertTitle, AlertDescription }\n","/**\n * Toast Notification System\n *\n * Self-contained toast provider with success/error/warning/info variants.\n * Uses the theme's semantic color tokens (success, warning, info, destructive).\n *\n * @example\n * // Wrap your app once:\n * <ToastProvider position=\"bottom-right\">\n * <App />\n * </ToastProvider>\n *\n * // In any child component:\n * const { success, error, warning, info } = useToast()\n * success('Saved!', 'Your changes have been saved.')\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode,\n} from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype ToastType = 'success' | 'error' | 'warning' | 'info'\n\ninterface Toast {\n id: string\n type: ToastType\n title: string\n description?: string\n duration?: number\n}\n\ninterface ToastContextValue {\n toasts: Toast[]\n toast: (options: Omit<Toast, 'id'>) => void\n success: (title: string, description?: string) => void\n error: (title: string, description?: string) => void\n warning: (title: string, description?: string) => void\n info: (title: string, description?: string) => void\n dismiss: (id: string) => void\n dismissAll: () => void\n}\n\n// ============================================================================\n// Icons (inline SVGs — no external dependency)\n// ============================================================================\n\nfunction CheckCircleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n )\n}\n\nfunction AlertCircleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n )\n}\n\nfunction AlertTriangleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" />\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n )\n}\n\nfunction InfoIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n )\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst ToastContext = createContext<ToastContextValue | null>(null)\n\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext)\n if (!ctx) throw new Error('useToast must be used within ToastProvider')\n return ctx\n}\n\n// ============================================================================\n// ToastProvider\n// ============================================================================\n\ninterface ToastProviderProps {\n children: ReactNode\n position?:\n | 'top-right'\n | 'top-left'\n | 'bottom-right'\n | 'bottom-left'\n | 'top-center'\n | 'bottom-center'\n maxToasts?: number\n}\n\nexport function ToastProvider({\n children,\n position = 'bottom-right',\n maxToasts = 5,\n}: ToastProviderProps): React.ReactElement {\n const [toasts, setToasts] = useState<Toast[]>([])\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n setToasts([])\n }, [])\n\n const addToast = useCallback(\n (options: Omit<Toast, 'id'>) => {\n const id = Math.random().toString(36).slice(2)\n const duration = options.duration ?? 5000\n\n setToasts((prev) => {\n const next = [...prev, { ...options, id }]\n return next.slice(-maxToasts)\n })\n\n if (duration > 0) {\n setTimeout(() => dismiss(id), duration)\n }\n },\n [dismiss, maxToasts],\n )\n\n const toast = useCallback(\n (options: Omit<Toast, 'id'>) => addToast(options),\n [addToast],\n )\n const success = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'success', title, description }),\n [addToast],\n )\n const error = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'error', title, description }),\n [addToast],\n )\n const warning = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'warning', title, description }),\n [addToast],\n )\n const info = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'info', title, description }),\n [addToast],\n )\n\n const positionClasses: Record<string, string> = {\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n 'top-center': 'top-4 left-1/2 -translate-x-1/2',\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\n }\n\n return (\n <ToastContext.Provider\n value={{ toasts, toast, success, error, warning, info, dismiss, dismissAll }}\n >\n {children}\n\n {/* Toast container */}\n <div\n className={`fixed z-[100] flex flex-col gap-2 ${positionClasses[position]}`}\n >\n {toasts.map((t) => (\n <ToastItem key={t.id} toast={t} onDismiss={() => dismiss(t.id)} />\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\n// ============================================================================\n// ToastItem\n// ============================================================================\n\n/**\n * Per-type visual config. Body uses the neutral popover surface — the type\n * is conveyed by a thin colored left-edge accent and the icon glyph alone,\n * not by tinting the title text or stamping a chunky colored block behind\n * the icon. Cleaner read; doesn't compete with the page underneath.\n */\nconst TOAST_CONFIG = {\n success: { Icon: CheckCircleIcon, accent: 'bg-success', icon: 'text-success' },\n error: { Icon: AlertCircleIcon, accent: 'bg-destructive', icon: 'text-destructive' },\n warning: { Icon: AlertTriangleIcon, accent: 'bg-warning', icon: 'text-warning' },\n info: { Icon: InfoIcon, accent: 'bg-info', icon: 'text-info' },\n} as const\n\ninterface ToastItemProps {\n toast: Toast\n onDismiss: () => void\n}\n\nfunction ToastItem({ toast, onDismiss }: ToastItemProps): React.ReactElement {\n const { Icon, accent, icon } = TOAST_CONFIG[toast.type]\n const [exiting, setExiting] = useState(false)\n\n // Animate out before removing.\n useEffect(() => {\n if (exiting) {\n const timer = setTimeout(onDismiss, 150)\n return () => clearTimeout(timer)\n }\n }, [exiting, onDismiss])\n\n return (\n <div\n className={`\n relative flex items-start gap-2.5 min-w-[260px] max-w-[360px]\n overflow-hidden rounded-lg border border-border bg-popover\n text-popover-foreground pl-3.5 pr-2 py-2.5 shadow-lg\n ${exiting\n ? 'animate-out fade-out-0 slide-out-to-right-2 duration-150'\n : 'animate-in fade-in-0 slide-in-from-right-2 duration-200'\n }\n `}\n role=\"alert\"\n >\n {/* Colored left-edge accent — the only chrome that reflects the type. */}\n <span className={`absolute inset-y-0 left-0 w-[3px] ${accent}`} aria-hidden />\n <Icon className={`mt-0.5 h-4 w-4 shrink-0 ${icon}`} />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[13px] font-medium leading-tight\">{toast.title}</p>\n {toast.description && (\n <p className=\"mt-0.5 text-xs leading-snug text-muted-foreground\">\n {toast.description}\n </p>\n )}\n </div>\n <button\n onClick={() => setExiting(true)}\n className=\"-mr-0.5 shrink-0 rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n aria-label=\"Dismiss\"\n >\n <CloseIcon className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n}\n","import React, { ReactNode, JSX } from 'react'\nimport { FileText, Search, Inbox, Plus, FolderOpen, Users, AlertCircle } from 'lucide-react'\nimport { cn } from './utils'\n\n// ============================================================================\n// EmptyState - Customizable empty state component\n// ============================================================================\n\ninterface EmptyStateProps extends React.HTMLAttributes<HTMLDivElement> {\n icon?: ReactNode\n title: string\n description?: string\n action?: {\n label: string\n onClick: () => void\n }\n secondaryAction?: {\n label: string\n onClick: () => void\n }\n}\n\nexport function EmptyState({\n icon,\n title,\n description,\n action,\n secondaryAction,\n className = '',\n ...rest\n}: EmptyStateProps): JSX.Element {\n return (\n <div className={cn('flex flex-col items-center justify-center py-16 px-4 text-center', className)} {...rest}>\n {icon && (\n <div className=\"w-16 h-16 rounded-2xl bg-muted/50 border border-border flex items-center justify-center mb-5\">\n <span className=\"text-muted-foreground\">{icon}</span>\n </div>\n )}\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">{title}</h3>\n {description && (\n <p className=\"text-muted-foreground text-sm max-w-sm mb-6\">{description}</p>\n )}\n {(action || secondaryAction) && (\n <div className=\"flex items-center gap-3\">\n {action && (\n <button\n onClick={action.onClick}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg font-medium text-sm hover:bg-primary/90 shadow-lg shadow-primary/25 transition-all\"\n >\n <Plus className=\"w-4 h-4\" />\n {action.label}\n </button>\n )}\n {secondaryAction && (\n <button\n onClick={secondaryAction.onClick}\n className=\"px-4 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {secondaryAction.label}\n </button>\n )}\n </div>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// Pre-built empty state variants\n// ============================================================================\n\ninterface EmptyStateVariantProps {\n action?: {\n label: string\n onClick: () => void\n }\n className?: string\n}\n\nexport function EmptyItems({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<Inbox className=\"w-8 h-8\" />}\n title=\"No items yet\"\n description=\"Get started by creating your first item.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\ninterface EmptySearchProps extends EmptyStateVariantProps {\n query?: string\n onClear?: () => void\n}\n\nexport function EmptySearch({ query, onClear, className }: EmptySearchProps): JSX.Element {\n return (\n <EmptyState\n icon={<Search className=\"w-8 h-8\" />}\n title=\"No results found\"\n description={query ? `No results for \"${query}\". Try a different search term.` : 'Try adjusting your search or filters.'}\n secondaryAction={onClear ? { label: 'Clear search', onClick: onClear } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyDocuments({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<FileText className=\"w-8 h-8\" />}\n title=\"No documents\"\n description=\"Create a document to start writing.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyProjects({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<FolderOpen className=\"w-8 h-8\" />}\n title=\"No projects\"\n description=\"Create a project to organize your work.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyTeam({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<Users className=\"w-8 h-8\" />}\n title=\"No team members\"\n description=\"Invite people to collaborate with you.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\ninterface EmptyErrorProps extends EmptyStateVariantProps {\n error?: string\n onRetry?: () => void\n}\n\nexport function EmptyError({ error, onRetry, className }: EmptyErrorProps): JSX.Element {\n return (\n <EmptyState\n icon={<AlertCircle className=\"w-8 h-8 text-destructive\" />}\n title=\"Something went wrong\"\n description={error || 'An error occurred. Please try again.'}\n action={onRetry ? { label: 'Try again', onClick: onRetry } : undefined}\n className={className}\n />\n )\n}\n\nexport default EmptyState\n","import * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className\n )}\n {...props}\n />\n))\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100vw-2rem)] sm:max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background/95 backdrop-blur-2xl p-4 sm:p-6 shadow-card-hover duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-2xl',\n className\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n))\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-1.5 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nDialogHeader.displayName = 'DialogHeader'\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nDialogFooter.displayName = 'DialogFooter'\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","import * as React from 'react'\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n inset && 'pl-8',\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto\" />\n </DropdownMenuPrimitive.SubTrigger>\n))\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n))\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] max-w-[calc(100vw-1rem)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n))\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n))\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n 'px-2 py-1.5 text-sm font-semibold',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n))\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn('ml-auto text-xs tracking-widest opacity-60', className)}\n {...props}\n />\n )\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut'\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n}\n","import * as React from 'react'\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\n\nimport { cn } from './utils'\n\nconst TooltipProvider = TooltipPrimitive.Provider\n\nconst Tooltip = TooltipPrimitive.Root\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n))\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","/**\n * Modal / ConfirmModal — backward-compatible wrappers around Dialog primitives.\n *\n * New code should use Dialog directly. These wrappers exist so existing\n * widget code (`<Modal open={...}>`) keeps working without changes.\n */\n\nimport React, { ReactNode, JSX } from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader as DHeader,\n DialogTitle as DTitle,\n DialogDescription as DDescription,\n DialogFooter as DFooter,\n} from './Dialog'\nimport { Button } from './Button'\nimport { cn } from './utils'\n\n// ============================================================================\n// Modal - Accessible modal dialog (wraps Radix Dialog)\n// ============================================================================\n\ninterface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n open: boolean\n onClose: () => void\n children: ReactNode\n size?: 'sm' | 'md' | 'lg' | 'xl'\n}\n\nexport function Modal({\n open,\n onClose,\n children,\n size = 'md',\n className,\n}: ModalProps): JSX.Element {\n const sizes = {\n sm: 'max-w-[calc(100vw-2rem)] sm:max-w-sm',\n md: 'max-w-[calc(100vw-2rem)] sm:max-w-lg',\n lg: 'max-w-[calc(100vw-2rem)] sm:max-w-2xl',\n xl: 'max-w-[calc(100vw-2rem)] sm:max-w-4xl',\n }\n\n return (\n <Dialog open={open} onOpenChange={(v) => { if (!v) onClose() }}>\n <DialogContent aria-describedby={undefined} className={cn(sizes[size], 'flex flex-col max-h-[85vh]', className)}>\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\n// ============================================================================\n// Modal.Header\n// ============================================================================\n\ninterface ModalHeaderProps {\n children: ReactNode\n onClose?: () => void\n className?: string\n}\n\nfunction ModalHeader({ children, className = '' }: ModalHeaderProps): JSX.Element {\n return (\n <DHeader className={className}>\n {children}\n </DHeader>\n )\n}\n\n// ============================================================================\n// Modal.Title\n// ============================================================================\n\ninterface ModalTitleProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalTitle({ children, className = '' }: ModalTitleProps): JSX.Element {\n return (\n <DTitle className={className}>\n {children}\n </DTitle>\n )\n}\n\n// ============================================================================\n// Modal.Description\n// ============================================================================\n\ninterface ModalDescriptionProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalDescription({ children, className = '' }: ModalDescriptionProps): JSX.Element {\n return (\n <DDescription className={className}>\n {children}\n </DDescription>\n )\n}\n\n// ============================================================================\n// Modal.Body - Scrollable content area\n// ============================================================================\n\ninterface ModalBodyProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalBody({ children, className = '' }: ModalBodyProps): JSX.Element {\n return (\n <div className={cn('flex-1 overflow-y-auto py-4', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// Modal.Footer - Action buttons area\n// ============================================================================\n\ninterface ModalFooterProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalFooter({ children, className = '' }: ModalFooterProps): JSX.Element {\n return (\n <DFooter className={className}>\n {children}\n </DFooter>\n )\n}\n\n// ============================================================================\n// ConfirmModal - Pre-built confirmation dialog\n// ============================================================================\n\ninterface ConfirmModalProps {\n open: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n description?: string\n confirmText?: string\n cancelText?: string\n variant?: 'destructive' | 'default'\n loading?: boolean\n}\n\nexport function ConfirmModal({\n open,\n onClose,\n onConfirm,\n title,\n description,\n confirmText = 'Confirm',\n cancelText = 'Cancel',\n variant = 'destructive',\n loading = false,\n}: ConfirmModalProps): JSX.Element {\n return (\n <Modal open={open} onClose={onClose} size=\"sm\">\n <Modal.Header>\n <Modal.Title>{title}</Modal.Title>\n {description && <Modal.Description>{description}</Modal.Description>}\n </Modal.Header>\n <Modal.Footer>\n <Button variant=\"ghost\" onClick={onClose} disabled={loading}>\n {cancelText}\n </Button>\n <Button variant={variant} onClick={onConfirm} loading={loading}>\n {confirmText}\n </Button>\n </Modal.Footer>\n </Modal>\n )\n}\n\n// ============================================================================\n// Attach sub-components\n// ============================================================================\n\nModal.Header = ModalHeader\nModal.Title = ModalTitle\nModal.Description = ModalDescription\nModal.Body = ModalBody\nModal.Footer = ModalFooter\n\nexport default Modal\n","import * as React from 'react'\nimport { Search, X } from 'lucide-react'\nimport { cn } from './utils'\nimport { Input } from './Input'\n\ninterface SearchInputProps extends Omit<React.ComponentProps<'input'>, 'type'> {\n onClear?: () => void\n}\n\nconst SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(\n ({ className, onClear, value, ...props }, ref) => {\n return (\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n ref={ref}\n type=\"search\"\n className={cn('pl-9 pr-9', className)}\n value={value}\n {...props}\n />\n {value && onClear && (\n <button\n type=\"button\"\n onClick={onClear}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n )\n }\n)\nSearchInput.displayName = 'SearchInput'\n\nexport { SearchInput }\n"],"mappings":";AAsCA,IAAM,aAAgC;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAChB;AAEA,IAAM,cAAiC;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc;AAChB;AAMA,IAAI,oBAAwC;AAE5C,SAAS,SAAS,OAA+C;AAC/D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI,MAAM,YAAY;AAC5B,MAAI,MAAM,SAAS,MAAM,cAAe,QAAO;AAC/C,MAAI,MAAM,UAAU,MAAM,aAAc,QAAO;AAC/C,SAAO;AACT;AAEO,SAAS,oBAAiC;AAC/C,MAAI,kBAAmB,QAAO;AAG9B,MAAI,OAAO,sBAAsB,aAAa;AAC5C,UAAM,MAAM,SAAS,iBAAiB;AACtC,QAAI,KAAK;AACP,0BAAoB;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,YAAa,OAA0C;AAC7D,UAAM,MAAM,SAAS,SAAS;AAC9B,QAAI,KAAK;AACP,0BAAoB;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,QAAI;AACF,YAAM,MAAM,SAAS,QAAQ,IAAI,aAAa;AAC9C,UAAI,KAAK;AACP,4BAAoB;AACpB,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,4BAAoB;AACpB,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,WAAW,OAAO,SAAS;AAEjC,QACE,aAAa,eACb,aAAa,eACb,SAAS,WAAW,UAAU,GAC9B;AACA,0BAAoB;AACpB,aAAO;AAAA,IACT;AAGA,QACE,aAAa,eACb,SAAS,SAAS,YAAY,KAC9B,aAAa,gBACb,SAAS,SAAS,aAAa,GAC/B;AACA,0BAAoB;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,sBAAoB;AACpB,SAAO;AACT;AAEO,SAAS,uBAA0C;AACxD,QAAM,MAAM,kBAAkB;AAC9B,SAAO,QAAQ,QAAQ,aAAa;AACtC;AAMO,SAAS,YAAoB;AAClC,SAAO,qBAAqB,EAAE;AAChC;AAEO,SAAS,uBAA+B;AAC7C,SAAO,qBAAqB,EAAE;AAChC;AAEO,SAAS,aAAqB;AACnC,SAAO,qBAAqB,EAAE;AAChC;AAEO,SAAS,aAAsB;AACpC,SAAO,kBAAkB,MAAM;AACjC;AAEO,SAAS,eAAwB;AACtC,SAAO,kBAAkB,MAAM;AACjC;AAGO,SAAS,wBAA8B;AAC5C,sBAAoB;AACtB;AAMO,IAAM,MAAM;AAAA,EACjB,IAAI,UAAU;AACZ,WAAO,kBAAkB;AAAA,EAC3B;AAAA,EACA,IAAI,SAAS;AACX,WAAO,qBAAqB;AAAA,EAC9B;AAAA,EACA,IAAI,SAAS;AACX,WAAO,UAAU;AAAA,EACnB;AAAA,EACA,IAAI,oBAAoB;AACtB,WAAO,qBAAqB;AAAA,EAC9B;AAAA,EACA,IAAI,UAAU;AACZ,WAAO,WAAW;AAAA,EACpB;AAAA,EACA,IAAI,UAAU;AACZ,WAAO,WAAW;AAAA,EACpB;AAAA,EACA,IAAI,SAAS;AACX,WAAO,aAAa;AAAA,EACtB;AACF;;;ACpMO,IAAM,QAAQ;AAAA,EACnB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AACT;AAIO,IAAM,cAA0F;AAAA,EACrG,QAAQ,EAAE,OAAO,UAAU,cAAc,aAAa,aAAa,mBAAmB;AAAA,EACtF,QAAQ,EAAE,OAAO,UAAU,cAAc,WAAW,aAAa,kCAAkC;AAAA,EACnG,OAAO,EAAE,OAAO,SAAS,cAAc,WAAW,aAAa,8BAA8B;AAC/F;;;ACTA,YAAY,OAAO;AAGZ,IAAM,WAAW;AACjB,IAAM,gBAAgB;AAGtB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAMxB,SAAS,gBAAoC;AAClD,SAAO,EAAE,MAAM,CAAC,EAAE;AACpB;AAEO,SAAS,aAAa,SAAyC;AACpE,SAAO,IAAI,WAAW,QAAQ,IAAI;AACpC;AAEO,SAAS,aAAa,SAA6B,KAAmB;AAC3E,SAAO,MAAM,KAAM;AACjB,YAAQ,KAAK,KAAM,MAAM,MAAQ,GAAI;AACrC,UAAM,KAAK,MAAM,MAAM,GAAG;AAAA,EAC5B;AACA,UAAQ,KAAK,KAAK,MAAM,GAAI;AAC9B;AAEO,SAAS,mBAAmB,SAA6B,KAAuB;AACrF,eAAa,SAAS,IAAI,MAAM;AAChC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAQ,KAAK,KAAK,IAAI,CAAC,CAAC;AAAA,EAC1B;AACF;AAEO,SAAS,cAAc,MAAqD;AACjF,SAAO,EAAE,MAAM,KAAK,EAAE;AACxB;AAEO,SAAS,YAAY,SAAoD;AAC9E,MAAI,MAAM;AACV,MAAI,OAAO;AACX,QAAM,MAAM,QAAQ,KAAK;AACzB,SAAO,QAAQ,MAAM,KAAK;AACxB,UAAM,OAAO,QAAQ,KAAK,QAAQ,KAAK;AACvC,YAAQ,OAAO,OAAQ;AACvB,YAAQ;AACR,QAAI,OAAO,KAAM;AACf,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI,MAAM,0BAA0B;AAC5C;AAEO,SAAS,kBAAkB,SAAwD;AACxF,QAAM,MAAM,YAAY,OAAO;AAC/B,QAAM,MAAM,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,MAAM,GAAG;AAChE,UAAQ,OAAO;AACf,SAAO;AACT;AAEO,SAAS,WAAW,SAAqD;AAC9E,SAAO,QAAQ,MAAM,QAAQ,KAAK;AACpC;AASO,SAAS,gBAAgB,KAAwB;AACtD,QAAM,UAAU,cAAc;AAC9B,eAAa,SAAS,QAAQ;AAC9B,eAAa,SAAS,cAAc;AACpC,qBAAmB,SAAW,oBAAkB,GAAG,CAAC;AACpD,SAAO,aAAa,OAAO;AAC7B;AAKO,SAAS,gBAAgB,KAAY,aAAqC;AAC/E,QAAM,UAAU,cAAc;AAC9B,eAAa,SAAS,QAAQ;AAC9B,eAAa,SAAS,cAAc;AACpC,qBAAmB,SAAW,sBAAoB,KAAK,WAAW,CAAC;AACnE,SAAO,aAAa,OAAO;AAC7B;AAKO,SAAS,aAAa,QAAgC;AAC3D,QAAM,UAAU,cAAc;AAC9B,eAAa,SAAS,QAAQ;AAC9B,eAAa,SAAS,eAAe;AACrC,qBAAmB,SAAS,MAAM;AAClC,SAAO,aAAa,OAAO;AAC7B;AAaO,SAAS,kBAAkB,KAAY,MAA8B;AAC1E,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,cAAc,YAAY,OAAO;AAEvC,MAAI,gBAAgB,UAAU;AAC5B,UAAM,IAAI,MAAM,0BAA0B,QAAQ,UAAU,WAAW,EAAE;AAAA,EAC3E;AAEA,QAAM,WAAW,YAAY,OAAO;AAEpC,UAAQ,UAAU;AAAA,IAChB,KAAK,gBAAgB;AAEnB,YAAM,cAAc,kBAAkB,OAAO;AAC7C,YAAM,WAAW,gBAAgB,KAAK,WAAW;AACjD,aAAO,EAAE,MAAM,SAAS,UAAU,YAAY;AAAA,IAChD;AAAA,IAEA,KAAK,gBAAgB;AAEnB,YAAM,SAAS,kBAAkB,OAAO;AACxC,MAAE,cAAY,KAAK,MAAM;AACzB,aAAO,EAAE,MAAM,SAAS,OAAO;AAAA,IACjC;AAAA,IAEA,KAAK,iBAAiB;AAEpB,YAAM,SAAS,kBAAkB,OAAO;AACxC,MAAE,cAAY,KAAK,MAAM;AACzB,aAAO,EAAE,MAAM,UAAU,OAAO;AAAA,IAClC;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,sBAAsB,QAAQ,EAAE;AAAA,EACpD;AACF;AAiBO,IAAM,YAAN,MAAgB;AAAA,EACrB;AAAA,EACA;AAAA,EACA,SAAsC,oBAAI,IAAI;AAAA,EACtC,OAA4D,oBAAI,IAAI;AAAA,EACpE,kBAAqG,oBAAI,IAAI;AAAA,EAC7G,kBAAqG,oBAAI,IAAI;AAAA,EAErH,YAAY,KAAY;AACtB,SAAK,MAAM;AACX,SAAK,WAAW,IAAI;AAAA,EACtB;AAAA,EAEA,YAAyC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,gBAAuC;AACrC,WAAO,KAAK,OAAO,IAAI,KAAK,QAAQ,KAAK;AAAA,EAC3C;AAAA,EAEA,cAAc,OAAoC;AAChD,UAAM,WAAW,KAAK;AACtB,UAAM,YAAY,KAAK,OAAO,IAAI,QAAQ;AAE1C,QAAI,UAAU,MAAM;AAClB,WAAK,OAAO,OAAO,QAAQ;AAC3B,WAAK,KAAK,OAAO,QAAQ;AACzB,UAAI,WAAW;AACb,aAAK,KAAK,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;AAAA,MAC3D;AAAA,IACF,OAAO;AACL,YAAM,OAAO,KAAK,KAAK,IAAI,QAAQ,KAAK,EAAE,OAAO,GAAG,aAAa,KAAK,IAAI,EAAE;AAC5E,WAAK;AACL,WAAK,cAAc,KAAK,IAAI;AAC5B,WAAK,KAAK,IAAI,UAAU,IAAI;AAC5B,WAAK,OAAO,IAAI,UAAU,KAAK;AAC/B,WAAK,KAAK;AAAA,QACR,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ;AAAA,QACjC,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC;AAAA,QACnC,SAAS,CAAC;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,mBAAmB,OAAe,OAAsB;AACtD,UAAM,QAAQ,KAAK,cAAc,KAAK,CAAC;AACvC,UAAM,KAAK,IAAI;AACf,SAAK,cAAc,KAAK;AAAA,EAC1B;AAAA,EAEA,GAAG,OAA4B,SAA6F;AAC1H,QAAI,UAAU,UAAU;AACtB,WAAK,gBAAgB,IAAI,OAAO;AAAA,IAClC,WAAW,UAAU,UAAU;AAC7B,WAAK,gBAAgB,IAAI,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,IAAI,OAA4B,SAA6F;AAC3H,QAAI,UAAU,UAAU;AACtB,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC,WAAW,UAAU,UAAU;AAC7B,WAAK,gBAAgB,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA,EAEQ,KAAK,SAA0E;AACrF,eAAW,WAAW,KAAK,iBAAiB;AAC1C,cAAQ,OAAO;AAAA,IACjB;AACA,QAAI,QAAQ,MAAM,SAAS,KAAK,QAAQ,QAAQ,SAAS,KAAK,QAAQ,QAAQ,SAAS,GAAG;AACxF,iBAAW,WAAW,KAAK,iBAAiB;AAC1C,gBAAQ,OAAO;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAAkC;AAC7C,UAAM,MAAM,aAAa,MAAM,KAAK,KAAK,OAAO,KAAK,CAAC;AACtD,UAAM,UAAU,cAAc;AAC9B,iBAAa,SAAS,IAAI,MAAM;AAEhC,eAAW,YAAY,KAAK;AAC1B,YAAM,QAAQ,KAAK,OAAO,IAAI,QAAQ;AACtC,YAAM,OAAO,KAAK,KAAK,IAAI,QAAQ,KAAK,EAAE,OAAO,GAAG,aAAa,KAAK,IAAI,EAAE;AAE5E,mBAAa,SAAS,QAAQ;AAC9B,mBAAa,SAAS,KAAK,KAAK;AAEhC,YAAM,WAAW,QAAQ,KAAK,UAAU,KAAK,IAAI;AACjD,YAAM,aAAa,IAAI,YAAY,EAAE,OAAO,QAAQ;AACpD,yBAAmB,SAAS,UAAU;AAAA,IACxC;AAEA,WAAO,aAAa,OAAO;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAA6E;AACvF,UAAM,UAAU,cAAc,IAAI;AAClC,UAAM,MAAM,YAAY,OAAO;AAE/B,UAAM,QAAkB,CAAC;AACzB,UAAM,UAAoB,CAAC;AAC3B,UAAM,UAAoB,CAAC;AAE3B,aAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,YAAM,WAAW,YAAY,OAAO;AACpC,YAAM,QAAQ,YAAY,OAAO;AACjC,YAAM,aAAa,kBAAkB,OAAO;AAC5C,YAAM,WAAW,IAAI,YAAY,EAAE,OAAO,UAAU;AACpD,YAAM,QAAQ,aAAa,SAAS,OAAO,KAAK,MAAM,QAAQ;AAE9D,YAAM,WAAW,KAAK,KAAK,IAAI,QAAQ;AACvC,YAAM,YAAY,KAAK,OAAO,IAAI,QAAQ;AAG1C,UAAI,CAAC,YAAY,SAAS,QAAQ,OAAO;AACvC,aAAK,KAAK,IAAI,UAAU,EAAE,OAAO,aAAa,KAAK,IAAI,EAAE,CAAC;AAE1D,YAAI,UAAU,MAAM;AAClB,eAAK,OAAO,OAAO,QAAQ;AAC3B,cAAI,WAAW;AACb,oBAAQ,KAAK,QAAQ;AAAA,UACvB;AAAA,QACF,OAAO;AACL,eAAK,OAAO,IAAI,UAAU,KAAK;AAC/B,cAAI,WAAW;AACb,oBAAQ,KAAK,QAAQ;AAAA,UACvB,OAAO;AACL,kBAAM,KAAK,QAAQ;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,KAAK,QAAQ,SAAS,KAAK,QAAQ,SAAS,GAAG;AAChE,WAAK,KAAK,EAAE,OAAO,SAAS,QAAQ,CAAC;AAAA,IACvC;AAEA,WAAO,EAAE,OAAO,SAAS,QAAQ;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAA2B;AACtC,UAAM,UAAoB,CAAC;AAC3B,eAAW,YAAY,WAAW;AAChC,UAAI,KAAK,OAAO,IAAI,QAAQ,GAAG;AAC7B,aAAK,OAAO,OAAO,QAAQ;AAC3B,aAAK,KAAK,OAAO,QAAQ;AACzB,gBAAQ,KAAK,QAAQ;AAAA,MACvB;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,KAAK,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,GAAG,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACF;AACF;AAKO,SAAS,uBAAuB,WAAsB,WAAkC;AAC7F,QAAM,UAAU,cAAc;AAC9B,eAAa,SAAS,aAAa;AACnC,qBAAmB,SAAS,UAAU,aAAa,SAAS,CAAC;AAC7D,SAAO,aAAa,OAAO;AAC7B;AAKO,SAAS,uBACd,WACA,MAC2D;AAC3D,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,cAAc,YAAY,OAAO;AAEvC,MAAI,gBAAgB,eAAe;AACjC,UAAM,IAAI,MAAM,+BAA+B,aAAa,UAAU,WAAW,EAAE;AAAA,EACrF;AAEA,QAAM,SAAS,kBAAkB,OAAO;AACxC,SAAO,UAAU,YAAY,MAAM;AACrC;AAKO,SAAS,eAAe,MAA0B;AACvD,QAAM,UAAU,cAAc,IAAI;AAClC,SAAO,YAAY,OAAO;AAC5B;;;ACpWO,IAAM,MAAM;AAAA;AAAA,EAEjB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,cAAc;AAAA,EACd,eAAe;AAAA,EACf,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,OAAO;AAAA;AAAA,EAGP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AAAA;AAAA,EAGb,UAAU;AAAA,EACV,WAAW;AAAA;AAAA,EAGX,KAAK;AAAA,EACL,cAAc;AAAA,EACd,aAAa;AAAA;AAAA,EAGb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA;AAAA,EAGX,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAGb,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAMb,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,YAAY;AAAA;AAAA,EAGZ,eAAe;AAAA,EACf,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,iBAAiB;AAAA;AAAA,EAGjB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,gBAAgB;AAClB;AAcO,IAAM,eAAe;AAErB,IAAM,oBAAoB;AAQ1B,IAAM,iBAAiB;AAEvB,IAAM,eAAe;AAErB,IAAM,aAAa;;;AC7B1B,IAAM,QAAsB,OAAO,OAAO,CAAC,CAAC;AAuOrC,IAAM,cAAc;AAAA;AAAA,EAEzB,WAAW,CAAC,gBAAwB,WACjC,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,gBAAgB,MAAM,EAAE;AAAA,EAC7D,aAAa,CAAC,oBACX,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,eAAe,EAAE;AAAA,EACxD,KAAK,CACH,YACA,UACA,MACA,eAEC;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,YAAY,UAAU,MAAM,UAAU;AAAA,EACnD;AAAA,EACF,QAAQ,CAAC,YAAoB,UAAkB,eAC5C,EAAE,MAAM,IAAI,QAAQ,SAAS,EAAE,YAAY,UAAU,UAAU,EAAE;AAAA;AAAA,EAEpE,UAAU,OAAO,EAAE,MAAM,IAAI,WAAW,SAAS,MAAM;AAAA,EACvD,SAAS,CAAC,QAAgB,UACvB,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,QAAQ,KAAK,EAAE;AAAA,EACnD,YAAY,OAAO,EAAE,MAAM,IAAI,aAAa,SAAS,MAAM;AAAA,EAC3D,aAAa,OAAO,EAAE,MAAM,IAAI,cAAc,SAAS,MAAM;AAAA;AAAA,EAE7D,SAAS,CAAC,YAAoB,UAAkB,eAC7C,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,YAAY,UAAU,UAAU,EAAE;AAAA,EACtE,UAAU,CAAC,YAAoB,UAAkB,eAC9C,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,YAAY,UAAU,UAAU,EAAE;AAAA;AAAA,EAEvE,WAAW,CAAC,QAAgB,OAAgC,CAAC,OAC1D,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,QAAQ,KAAK,EAAE;AAAA,EACrD,iBAAiB,OAAO,EAAE,MAAM,IAAI,mBAAmB,SAAS,MAAM;AAAA,EACtE,WAAW,OAAO,EAAE,MAAM,IAAI,YAAY,SAAS,MAAM;AAAA,EACzD,SAAS,OAAO,EAAE,MAAM,IAAI,UAAU,SAAS,MAAM;AAAA;AAAA;AAAA,EAGrD,WAAW,CAAC,WACT,EAAE,MAAM,IAAI,YAAY,SAAS,MAAM;AAAA,EAC1C,YAAY,CAAC,SAAiB,GAAW,OACtC,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,SAAS,GAAG,EAAE,EAAE;AAAA,EACvD,cAAc,CACZ,SACA,OACA,QACA,GACA,OAEC,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,SAAS,OAAO,QAAQ,GAAG,EAAE,EAAE;AAAA,EACxE,cAAc,CAAC,aACZ,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,QAAQ,EAAE;AAAA,EACnD,cAAc,CAAC,SAAiB,WAC7B,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,SAAS,MAAM,EAAE;AAAA,EAC1D,gBAAgB,CAAC,cACd,EAAE,MAAM,IAAI,iBAAiB,SAAS,SAAS;AAAA,EAClD,YAAY,OAAO,EAAE,MAAM,IAAI,aAAa,SAAS,MAAM;AAAA,EAC3D,YAAY,OAAO,EAAE,MAAM,IAAI,aAAa,SAAS,MAAM;AAAA;AAAA,EAE3D,aAAa,CAAC,cACX,EAAE,MAAM,IAAI,cAAc,SAAS,EAAE,SAAS,EAAE;AAAA,EACnD,WAAW,CAAC,cACT,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,SAAS,EAAE;AAAA,EACjD,YAAY,CAAC,cACV,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,SAAS,EAAE;AAAA;AAAA,EAElD,YAAY,CACV,WACA,MACA,SACA,iBAEC;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,WAAW,MAAM,SAAS,YAAY;AAAA,EACnD;AAAA,EACF,WAAW,CAAC,WACT,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,EAAE;AAAA,EAC9C,UAAU,CAAC,WACR,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,MAAM,EAAE;AAAA;AAAA,EAE7C,gBAAgB,CAAC,WACd,EAAE,MAAM,IAAI,iBAAiB,SAAS,MAAM;AAAA;AAAA,EAE/C,gBAAgB,CAAC,WAAmB,aACjC,EAAE,MAAM,IAAI,kBAAkB,SAAS,EAAE,WAAW,QAAQ,EAAE;AAAA,EACjE,mBAAmB,CAAC,WAAmB,aACpC,EAAE,MAAM,IAAI,qBAAqB,SAAS,EAAE,WAAW,QAAQ,EAAE;AAAA,EACpE,gBAAgB,CAAC,WACd,EAAE,MAAM,IAAI,kBAAkB,SAAS,EAAE,MAAM,EAAE;AACtD;AAOO,IAAM,cAAc;AAAA;AAAA,EAEzB,aAAa,CAAC,gBAAwB,aACnC,EAAE,MAAM,IAAI,cAAc,SAAS,EAAE,gBAAgB,QAAQ,EAAE;AAAA,EAClE,cAAc,CACZ,YACA,QACA,gBAEC,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,YAAY,QAAQ,WAAW,EAAE;AAAA,EAC1E,OAAO,CAAC,OAAe,oBACpB,EAAE,MAAM,IAAI,OAAO,SAAS,EAAE,OAAO,eAAe,EAAE;AAAA,EACzD,YAAY,CAAC,WAAmB,cAC7B;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,WAAW,SAAS,MAAe,SAAS;AAAA,EACzD;AAAA,EACF,YAAY,CAAC,WAAmB,WAC7B;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,WAAW,SAAS,OAAgB,MAAM;AAAA,EACvD;AAAA,EACF,aAAa,OAAO,EAAE,MAAM,IAAI,aAAa,SAAS,MAAM;AAAA,EAC5D,SAAS,CAAC,aACP,EAAE,MAAM,IAAI,cAAc,SAAS,EAAE,QAAQ,EAAE;AAAA;AAAA,EAElD,UAAU,CAAC,UACR,EAAE,MAAM,IAAI,WAAW,SAAS,KAAK;AAAA,EACxC,UAAU,CAAC,WACR,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,MAAM,EAAE;AAAA;AAAA,EAE7C,SAAS,CAAC,YAAoB,UAAkB,WAAmB,cAChE;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,YAAY,UAAU,WAAW,SAAS;AAAA,EACvD;AAAA;AAAA,EAEF,WAAW,CAAC,OAAgB,MAAc,SAAoB,aAC3D,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,SAAS,QAAQ,EAAE;AAAA,EACtE,UAAU,CAAC,OAAgB,UACxB,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,OAAO,KAAK,EAAE;AAAA,EACnD,WAAW,CAAC,OAAgB,UACzB,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,EAAE;AAAA,EACpD,SAAS,CAAC,OAAgB,UACvB,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,OAAO,KAAK,EAAE;AAAA,EAClD,gBAAgB,CAAC,YACd,EAAE,MAAM,IAAI,kBAAkB,SAAS,EAAE,OAAO,EAAE;AAAA,EACrD,iBAAiB,CAAC,YACf,EAAE,MAAM,IAAI,mBAAmB,SAAS,EAAE,OAAO,EAAE;AAAA,EACtD,iBAAiB,CAAC,YACf,EAAE,MAAM,IAAI,mBAAmB,SAAS,EAAE,OAAO,EAAE;AAAA;AAAA,EAEtD,cAAc,CAAC,QAAmB,eAC/B,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,QAAQ,UAAU,EAAE;AAAA,EAC7D,WAAW,CAAC,WACT,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,EAAE;AAAA,EAC9C,YAAY,CAAC,SAAiB,GAAW,OACtC,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,SAAS,GAAG,EAAE,EAAE;AAAA,EACvD,cAAc,CACZ,SACA,OACA,QACA,GACA,OAEC,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,SAAS,OAAO,QAAQ,GAAG,EAAE,EAAE;AAAA,EACxE,cAAc,CAAC,aACZ,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,QAAQ,EAAE;AAAA,EACnD,cAAc,CAAC,SAAiB,WAC7B,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,SAAS,MAAM,EAAE;AAAA,EAC1D,gBAAgB,CAAC,cACd,EAAE,MAAM,IAAI,iBAAiB,SAAS,EAAE,SAAS,EAAE;AAAA,EACtD,uBAAuB,CAAC,YACrB;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,QAAQ,SAAS,KAAc;AAAA,EAC5C;AAAA;AAAA,EAEF,WAAW,CAAC,WACT,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,EAAE;AAAA,EAC9C,aAAa,CAAC,aACX,EAAE,MAAM,IAAI,cAAc,SAAS,EAAE,QAAQ,EAAE;AAAA,EAClD,YAAY,CAAC,OAAgB,mBAC1B,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,OAAO,cAAc,EAAE;AAAA;AAAA,EAE9D,aAAa,CAAC,UACX,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,YAAqB,KAAK,EAAE;AAAA,EACxE,aAAa,CAAC,KAAc,eACzB;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,MAAM,YAAqB,KAAK,UAAU;AAAA,EACvD;AAAA,EACF,aAAa,CAAC,SACX,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,YAAqB,IAAI,EAAE;AAAA,EACvE,cAAc,CAAC,SACZ,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,aAAsB,IAAI,EAAE;AAAA,EACxE,WAAW,CAAC,SACT,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,UAAmB,IAAI,EAAE;AAAA,EACrE,aAAa,CAAC,SACX,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,YAAqB,IAAI,EAAE;AAAA,EACvE,YAAY,CAAC,SACV,EAAE,MAAM,IAAI,YAAY,SAAS,EAAE,MAAM,WAAoB,IAAI,EAAE;AAAA;AAAA,EAEtE,cAAc,CAAC,WACZ,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,MAAM,EAAE;AAAA,EACjD,cAAc,CAAC,UACZ,EAAE,MAAM,IAAI,eAAe,SAAS,EAAE,KAAK,EAAE;AAAA,EAChD,eAAe,CAAC,YACb,EAAE,MAAM,IAAI,gBAAgB,SAAS,EAAE,OAAO,EAAE;AAAA,EACnD,gBAAgB,CAAC,QAAgB,WAC9B,EAAE,MAAM,IAAI,iBAAiB,SAAS,EAAE,QAAQ,MAAM,EAAE;AAAA;AAAA,EAE3D,cAAc,CAAC,WAAmB,SAAiB,WAChD;AAAA,IACC,MAAM,IAAI;AAAA,IACV,SAAS,EAAE,WAAW,SAAS,MAAM;AAAA,EACvC;AAAA,EACF,cAAc,CAAC,UACZ,EAAE,MAAM,IAAI,gBAAgB,SAAS,KAAK;AAC/C;AAyDO,SAAS,SACd,KACA,UACS;AACT,MAAI;AACJ,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI;AACF,YAAM,KAAK,MAAM,GAAG;AAAA,IACtB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,WAAW,OAAO,OAAO,QAAQ,UAAU;AACzC,UAAM;AAAA,EACR,OAAO;AACL,WAAO;AAAA,EACT;AACA,MAAI,OAAO,IAAI,SAAS,SAAU,QAAO;AACzC,QAAM,UAAW,SACf,IAAI,IACN;AACA,MAAI,CAAC,QAAS,QAAO;AACrB,UAAQ,IAAI,OAAO;AACnB,SAAO;AACT;AAQO,SAAS,OAA+C,SAAoB;AACjF,SAAO,KAAK,UAAU,OAAO;AAC/B;;;ACjnBA,SAAgB,WAAW,cAAc;;;ACAzC,SAAS,wBAAwB;AACjC,SAAS,oBAAoB,uBAAuB;;;ACEpD,IAAI,cAA6B;AACjC,IAAI,cAAc;AAElB,SAAS,cAAc,OAAuB;AAC5C,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,UAAM,UAAU,KAAK,MAAM,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,CAAC,CAAC;AAC/E,YAAQ,QAAQ,OAAO,KAAK;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASA,eAAsB,eAAuC;AAC3D,MAAI,OAAO,WAAW,YAAa,QAAO;AAG1C,MAAI,eAAe,KAAK,IAAI,IAAI,cAAc,KAAQ;AACpD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,mBAAmB;AAAA,MACzC,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAChD,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,oBAAc;AACd,oBAAc;AACd,aAAO;AAAA,IACT;AAEA,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAI,CAAC,KAAK,OAAO;AACf,oBAAc;AACd,oBAAc;AACd,aAAO;AAAA,IACT;AAEA,kBAAc,KAAK;AACnB,kBAAc,cAAc,KAAK,KAAK;AACtC,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,iBAAuB;AACrC,gBAAc;AACd,gBAAc;AAChB;;;ADxDA,SAAS,aAAqB;AAC5B,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,SAAS;AAAA,EACzB;AACA,SAAO;AACT;AAEO,IAAM,aAAa,iBAAiB;AAAA,EACzC,SAAS,WAAW;AAAA,EACpB,SAAS,CAAC,mBAAmB,GAAG,gBAAgB,CAAC;AACnD,CAAC;AAEM,IAAM;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,IAAI;AAEJ,eAAsB,WACjB,MACsD;AACzD,MAAI;AACF,WAAO,MAAM,WAAW,QAAQ,GAAG,IAAI;AAAA,EACzC,UAAE;AACA,mBAAe;AAAA,EACjB;AACF;;;ADEI,mBACE,KADF;AA7BJ,SAAS,aAAa;AACpB,QAAM,UAAU,WAAW;AAC3B,QAAM,aAAa,CAAC,CAAC,QAAQ,MAAM;AACnC,QAAM,eAAe,OAAuB,IAAI;AAEhD,YAAU,MAAM;AACd,QAAI,QAAQ,UAAW;AACvB,QAAI,aAAa,YAAY,YAAY;AACvC,UAAI,YAAY;AACd,gBAAQ,IAAI,0BAA0B,QAAQ,MAAM,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,EAAE;AAAA,MAC5F,WAAW,aAAa,YAAY,MAAM;AACxC,gBAAQ,IAAI,sBAAsB;AAAA,MACpC;AACA,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,YAAY,QAAQ,WAAW,QAAQ,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,EAAE,CAAC;AAEpF,SAAO;AACT;AASO,SAAS,sBAAsB,EAAE,SAAS,GAA+B;AAC9E,SACE,iCACE;AAAA,wBAAC,cAAW;AAAA,IACX;AAAA,KACH;AAEJ;;;AGtCO,SAAS,UAAU;AACxB,QAAM,UAAU,WAAW;AAE3B,QAAM,aAAa,CAAC,CAAC,QAAQ,MAAM;AACnC,QAAM,SAAS,QAAQ,MAAM,MAAM,MAAM;AAEzC,SAAO;AAAA,IACL,UAAU,CAAC,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,MAAM,SAAS,MAAM;AAAA,EAC1C;AACF;AAKO,SAAS,cAAc;AAC5B,QAAM,UAAU,WAAW;AAC3B,QAAM,OAAO,QAAQ,MAAM,QAAQ;AAEnC,SAAO;AAAA,IACL,UAAU,CAAC,QAAQ;AAAA,IACnB,YAAY,CAAC,CAAC;AAAA,IACd,MAAM,OACF;AAAA,MACE,IAAI,KAAK;AAAA,MACT,UAAU,KAAK,QAAQ;AAAA,MACvB,WAAW,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MACvC,UAAU,KAAK,MAAM,MAAM,GAAG,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK;AAAA,MACtD,gBAAgB,KAAK,QACjB,CAAC,EAAE,cAAc,KAAK,MAAM,CAAC,IAC7B,CAAC;AAAA,MACL,UAAU,KAAK,SAAS;AAAA,MACxB,qBAAqB,KAAK,QACtB,EAAE,cAAc,KAAK,MAAM,IAC3B;AAAA,IACN,IACA;AAAA,EACN;AACF;;;AC5CA,SAAgB,gBAAgB;AA+C5B,qBAAAA,WACE,OAAAC,MA+CI,QAAAC,aAhDN;AApCG,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,YAAY,CAAC,UAAU,QAAQ;AACjC,IAAsB,CAAC,GAA8B;AACnD,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AACzC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,EAAE;AAC3C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,MAAI,CAAC,YAAY,WAAY,QAAO;AAEpC,QAAM,eAAe,CAAC,aAAkC;AACtD,eAAW,IAAI;AACf,WAAO,SAAS,OAAO,sCAAsC,QAAQ;AAAA,EACvE;AAEA,QAAM,oBAAoB,OAAO,MAAuB;AACtD,MAAE,eAAe;AACjB,aAAS,EAAE;AACX,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,MAAM,EAAE,OAAO,SAAS,CAAC;AACrD,UAAI,OAAO,OAAO;AAChB,iBAAS,OAAO,MAAM,WAAW,gBAAgB;AACjD,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF,SAAS,KAAU;AACjB,eAAS,IAAI,WAAW,sBAAsB;AAC9C,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE,gBAAAA,MAAAF,WAAA,EACE;AAAA,oBAAAC,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SASN;AAAA,IAEF,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,eAAY;AAAA,QACZ,SAAS,UAAU,CAAC,MAAM;AAAE,cAAI,EAAE,WAAW,EAAE,cAAe,SAAQ;AAAA,QAAE,IAAI;AAAA,QAC5E,WAAU;AAAA,QACV,OAAO;AAAA,UACL,SAAS;AAAA,UACT,WAAW;AAAA,QACb;AAAA,QAEA,0BAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,SAAS;AAAA,cACT,WAAW;AAAA,YACb;AAAA,YAEC;AAAA,yBACC,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAY;AAAA,kBACZ,SAAS;AAAA,kBACT,cAAW;AAAA,kBACX,WAAU;AAAA,kBACX;AAAA;AAAA,cAED;AAAA,cAGF,gBAAAA,KAAC,QAAG,WAAU,2DAA0D,kCAExE;AAAA,cAEA,gBAAAA,KAAC,OAAE,WAAU,mDAAkD,2CAE/D;AAAA,cAGA,gBAAAC,MAAC,SAAI,WAAU,uBACZ;AAAA,0BAAU,SAAS,QAAQ,KAC1B,gBAAAD,KAAC,eAAY,SAAS,MAAM,aAAa,QAAQ,GAAG,UAAU,SAAS,MAAM,gBAAAA,KAAC,cAAW,GAAI,kCAE7F;AAAA,gBAED,UAAU,SAAS,QAAQ,KAC1B,gBAAAA,KAAC,eAAY,SAAS,MAAM,aAAa,QAAQ,GAAG,UAAU,SAAS,MAAM,gBAAAA,KAAC,cAAW,GAAI,kCAE7F;AAAA,iBAEJ;AAAA,cAEA,gBAAAA,KAAC,WAAQ;AAAA,cAER,CAAC,gBACA,gBAAAC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,eAAY;AAAA,kBACZ,SAAS,MAAM,iBAAiB,IAAI;AAAA,kBACpC,WAAU;AAAA,kBAEV;AAAA,oCAAAA,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACxJ;AAAA,sCAAAD,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,KAAI;AAAA,sBAChD,gBAAAA,KAAC,UAAK,GAAE,6CAA4C;AAAA,uBACtD;AAAA,oBAAM;AAAA;AAAA;AAAA,cAER,IAEA,gBAAAC,MAAC,UAAK,UAAU,mBAAmB,WAAU,aAC3C;AAAA,gCAAAD;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,aAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,oBACxC,UAAQ;AAAA,oBACR,cAAa;AAAA,oBACb,WAAU;AAAA;AAAA,gBACZ;AAAA,gBACA,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,aAAY;AAAA,oBACZ,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,oBAC3C,UAAQ;AAAA,oBACR,WAAW;AAAA,oBACX,cAAa;AAAA,oBACb,WAAW,6KAA6K,QAAQ,SAAS,MAAM;AAAA;AAAA,gBACjN;AAAA,gBAEC,SACC,gBAAAA,KAAC,SAAI,WAAU,6CAA6C,iBAAM;AAAA,gBAGpE,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,UAAU;AAAA,oBACV,WAAU;AAAA,oBAET,oBAAU,sBAAiB;AAAA;AAAA,gBAC9B;AAAA,iBACF;AAAA,cAGF,gBAAAC,MAAC,SAAI,WAAU,mFACb;AAAA,gCAAAD,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,gBAAe,SAAQ,OAAM,eAAW,MAC3F,0BAAAA,KAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK,GACjC;AAAA,gBAAM;AAAA,iBAER;AAAA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAMA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MAET;AAAA;AAAA,QACA;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,SAAS,UAAU;AACjB,SACE,gBAAAA,MAAC,SAAI,WAAU,8DACb;AAAA,oBAAAD,KAAC,SAAI,WAAU,yBAAwB;AAAA,IAAE;AAAA,IAEzC,gBAAAA,KAAC,SAAI,WAAU,yBAAwB;AAAA,KACzC;AAEJ;AAEA,SAAS,aAAa;AACpB,SACE,gBAAAA,KAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,gBAAe,eAAW,MAC7E,0BAAAA,KAAC,UAAK,GAAE,0jBAAyjB,GACnkB;AAEJ;AAIA,SAAS,aAAa;AACpB,SACE,gBAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,eAAW,MACzD;AAAA,oBAAAD,KAAC,UAAK,MAAK,WAAU,GAAE,oHAAmH;AAAA,IAC1I,gBAAAA,KAAC,UAAK,MAAK,WAAU,GAAE,yIAAwI;AAAA,IAC/J,gBAAAA,KAAC,UAAK,MAAK,WAAU,GAAE,iIAAgI;AAAA,IACvJ,gBAAAA,KAAC,UAAK,MAAK,WAAU,GAAE,uIAAsI;AAAA,KAC/J;AAEJ;;;AC1OA,SAAS,aAAAE,YAAW,UAAAC,eAA8B;AAUzC,qBAAAC,WAAA,OAAAC,YAAA;AAHF,SAAS,SAAS,EAAE,SAAS,GAAuD;AACzF,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AACzC,MAAI,CAAC,YAAY,CAAC,WAAY,QAAO;AACrC,SAAO,gBAAAA,KAAAD,WAAA,EAAG,UAAS;AACrB;AAKO,SAAS,UAAU,EAAE,SAAS,GAAuD;AAC1F,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AACzC,MAAI,CAAC,YAAY,WAAY,QAAO;AACpC,SAAO,gBAAAC,KAAAD,WAAA,EAAG,UAAS;AACrB;AAoBO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,oBAAoB;AACtB,GAA6C;AAC3C,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AACzC,QAAM,cAAcE,QAAO,KAAK;AAChC,MAAI,WAAY,aAAY,UAAU;AAEtC,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,WAAY,QAAO,gBAAAD,KAAAD,WAAA,EAAG,UAAS;AACnC,MAAI,YAAY,QAAS,QAAO,gBAAAC,KAAC,gBAAa,IAAI,mBAAmB;AACrE,MAAI,SAAU,QAAO,gBAAAA,KAAAD,WAAA,EAAG,oBAAS;AACjC,SAAO,gBAAAC,KAAC,eAAY;AACtB;AAIA,SAAS,aAAa,EAAE,GAAG,GAAyB;AAClD,EAAAE,WAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa,QAAO,SAAS,QAAQ,EAAE;AAAA,EAC/D,GAAG,CAAC,EAAE,CAAC;AACP,SAAO;AACT;AAQO,SAAS,iBAAgC;AAC9C,QAAM,EAAE,KAAK,IAAI,YAAY;AAC7B,MAAI,CAAC,KAAM,QAAO;AAClB,SACE,KAAK,YACL,KAAK,aACL,KAAK,qBAAqB,cAAc,MAAM,GAAG,EAAE,CAAC,KACpD;AAEJ;;;ACvEA,SAAgB,aAAAC,YAAW,YAAAC,iBAAgB;AAgDvC,qBAAAC,WACE,OAAAC,MA4CM,QAAAC,aA7CR;AA7CJ,IAAM,sBAAsB;AAC5B,IAAM,kBAAkB;AASjB,SAAS,YAAY;AAAA,EAC1B,UAAU;AAAA,EACV,aAAa;AAAA,EACb;AACF,GAAgD;AAC9C,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AACzC,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,KAAK;AAE5C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,MAAM;AAC/C,QAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAI;AACF,aAAO,eAAe,QAAQ,UAAU,MAAM;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,EAAAC,WAAU,MAAM;AACd,QAAI,YAAY,CAAC,cAAc,CAAC,WAAW;AACzC,4BAAsB,MAAM,WAAW,IAAI,CAAC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,WAAW,UAAU,UAAU,CAAC;AAEpC,MAAI,CAAC,YAAY,cAAc,UAAW,QAAO;AAEjD,QAAM,gBAAgB,MAAY;AAChC,QAAI;AACF,qBAAe,QAAQ,YAAY,GAAG;AAAA,IACxC,QAAQ;AAAA,IAER;AACA,iBAAa,IAAI;AAAA,EACnB;AAEA,SACE,gBAAAF,MAAAF,WAAA,EACE;AAAA,oBAAAC,KAAC,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKN;AAAA,IACF,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,WAAU;AAAA,QACV,OAAO;AAAA,UACL,SAAS,UAAU,IAAI;AAAA,UACvB,WAAW,UACP,oEACA;AAAA,UACJ,eAAe,UAAU,SAAS;AAAA,QACpC;AAAA,QAEA;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,eAAW;AAAA,cACX,WAAU;AAAA;AAAA,UACZ;AAAA,UAEA,gBAAAA,KAAC,UAAK,WAAU,oDACb,mBACH;AAAA,UAEA,gBAAAC,MAAC,SAAI,WAAU,oCACb;AAAA,4BAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,eAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,WAAU;AAAA,gBACX;AAAA;AAAA,YAED;AAAA,YAEA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,eAAY;AAAA,gBACZ,SAAS;AAAA,gBACT,cAAW;AAAA,gBACX,WAAU;AAAA,gBAEV,0BAAAC;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,QAAO;AAAA,oBACP,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,QAAO;AAAA,oBACP,aAAY;AAAA,oBACZ,eAAc;AAAA,oBACd,gBAAe;AAAA,oBACf,eAAW;AAAA,oBAEX;AAAA,sCAAAD,KAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,sBACpC,gBAAAA,KAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA;AAAA;AAAA,gBACtC;AAAA;AAAA,YACF;AAAA,aACF;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;ACjHA;AAAA,EACE,iBAAAI;AAAA,EACA,cAAAC;AAAA,EACA,aAAAC;AAAA,EACA,YAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,OAEK;;;ACFP,IAAM,gBAA8B,CAAC;AAE9B,IAAM,cAAN,MAAkB;AAAA,EACf,UAAU,oBAAI,IAAwB;AAAA,EACtC,YAAY,oBAAI,IAA6B;AAAA;AAAA,EAE7C,YAAY,oBAAI,IAAoB;AAAA;AAAA,EAEpC,sBAAsB,oBAAI,IAAoB;AAAA,EAEtD,UAAU,UAAkB,UAAkC;AAC5D,UAAM,MAAM,KAAK,UAAU,IAAI,QAAQ,KAAK,oBAAI,IAAI;AACpD,QAAI,IAAI,QAAQ;AAChB,SAAK,UAAU,IAAI,UAAU,GAAG;AAChC,WAAO,MAAM;AACX,UAAI,OAAO,QAAQ;AACnB,UAAI,IAAI,SAAS,GAAG;AAClB,aAAK,UAAU,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,UAAgC;AAE1C,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,UAAU,UAAiD;AACzD,WAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG,UAAU;AAAA,EAC/C;AAAA,EAEA,SAAS,UAAsC;AAC7C,WAAO,KAAK,QAAQ,IAAI,QAAQ,GAAG;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,UAA2B;AACnC,UAAM,YAAY,KAAK,UAAU,IAAI,QAAQ,KAAK;AAClD,SAAK,UAAU,IAAI,UAAU,YAAY,CAAC;AAE1C,QAAI,CAAC,KAAK,QAAQ,IAAI,QAAQ,GAAG;AAC/B,WAAK,QAAQ,IAAI,UAAU,EAAE,QAAQ,WAAW,SAAS,CAAC,GAAG,SAAS,EAAE,CAAC;AAAA,IAC3E;AAGA,WAAO,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,UAA2B;AACtC,UAAM,SAAS,KAAK,UAAU,IAAI,QAAQ,KAAK,KAAK;AAEpD,QAAI,SAAS,GAAG;AACd,WAAK,UAAU,OAAO,QAAQ;AAC9B,WAAK,oBAAoB,OAAO,QAAQ;AACxC,aAAO;AAAA,IACT;AAEA,SAAK,UAAU,IAAI,UAAU,KAAK;AAClC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,kBAAkB,UAAkB,gBAA8B;AAChE,SAAK,oBAAoB,IAAI,UAAU,cAAc;AAAA,EACvD;AAAA;AAAA,EAGA,kBAAkB,UAAsC;AACtD,WAAO,KAAK,oBAAoB,IAAI,QAAQ;AAAA,EAC9C;AAAA;AAAA,EAGA,eAAe,UAAkB,SAA6B;AAC5D,UAAM,UAAU,KAAK,QAAQ,IAAI,QAAQ;AAEzC,SAAK,QAAQ,IAAI,UAAU;AAAA,MACzB,QAAQ;AAAA,MACR;AAAA;AAAA,MACA,UAAU,SAAS,WAAW,KAAK;AAAA,IACrC,CAAC;AACD,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA;AAAA,EAGA,UAAU,UAAkB,UAA2B;AACrD,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,MAAM,QAAQ,KAAK,OAAK,EAAE,aAAa,QAAQ;AAAA,EACxD;AAAA;AAAA,EAGA,YACE,UACA,QACA,YACM;AACN,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAEZ,QAAI;AAEJ,QAAI,eAAe,UAAU;AAC3B,mBAAa,MAAM,QAAQ,OAAO,OAAK,EAAE,aAAa,OAAO,QAAQ;AAAA,IACvE,WAAW,eAAe,UAAU;AAElC,YAAM,SAAS,MAAM,QAAQ,KAAK,OAAK,EAAE,aAAa,OAAO,QAAQ;AACrE,UAAI,QAAQ;AAEV,qBAAa,MAAM,QAAQ,IAAI,OAAK,EAAE,aAAa,OAAO,WAAW,SAAS,CAAC;AAAA,MACjF,OAAO;AAEL,qBAAa,CAAC,GAAG,MAAM,SAAS,MAAM;AAAA,MACxC;AAAA,IACF,OAAO;AAEL,mBAAa,MAAM,QAAQ,IAAI,OAAK,EAAE,aAAa,OAAO,WAAW,SAAS,CAAC;AAAA,IACjF;AAEA,SAAK,QAAQ,IAAI,UAAU;AAAA,MACzB,GAAG;AAAA,MACH,SAAS;AAAA,MACT,SAAS,MAAM,UAAU;AAAA,IAC3B,CAAC;AACD,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,UAAwB;AACrC,UAAM,UAAU,KAAK,QAAQ,IAAI,QAAQ;AACzC,QAAI,CAAC,QAAS;AAEd,SAAK,QAAQ,IAAI,UAAU;AAAA,MACzB,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,SAAS,QAAQ,UAAU;AAAA,IAC7B,CAAC;AACD,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,SAAS,UAAkB,OAAqB;AAC9C,UAAM,UAAU,KAAK,QAAQ,IAAI,QAAQ;AACzC,SAAK,QAAQ,IAAI,UAAU;AAAA,MACzB,QAAQ;AAAA,MACR,SAAS,SAAS,WAAW,CAAC;AAAA,MAC9B,UAAU,SAAS,WAAW,KAAK;AAAA,MACnC;AAAA,IACF,CAAC;AACD,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA;AAAA,EAGA,YAAY,UAAwB;AAClC,SAAK,QAAQ,OAAO,QAAQ;AAC5B,SAAK,UAAU,OAAO,QAAQ;AAAA,EAChC;AAAA,EAEQ,OAAO,UAAwB;AACrC,UAAM,MAAM,KAAK,UAAU,IAAI,QAAQ;AACvC,QAAI,KAAK;AACP,UAAI,QAAQ,QAAM,GAAG,CAAC;AAAA,IACxB;AAAA,EACF;AACF;;;ACnLA,SAAS,eAAe,YAAY,aAAa,UAAAC,SAAQ,eAA+B;AA8EpF,gBAAAC,YAAA;AApCJ,IAAM,uBAAuB,cAAyC,IAAI;AAEnE,SAAS,mBAA8C;AAC5D,SAAO,WAAW,oBAAoB;AACxC;AAMO,SAAS,sBAAsB,EAAE,SAAS,GAA4B;AAC3E,QAAM,SAASD,QAAO,oBAAI,IAA0B,CAAC;AAErD,QAAM,WAAW,YAAY,CAAC,SAAiB,aAAuB,UAAsB;AAC1F,eAAW,QAAQ,aAAa;AAC9B,aAAO,QAAQ,IAAI,MAAM,EAAE,SAAS,MAAM,CAAC;AAAA,IAC7C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,aAAa,YAAY,CAAC,SAAiB,gBAA0B;AACzE,eAAW,QAAQ,aAAa;AAC9B,YAAM,WAAW,OAAO,QAAQ,IAAI,IAAI;AAExC,UAAI,UAAU,YAAY,SAAS;AACjC,eAAO,QAAQ,OAAO,IAAI;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,CAAC,eAA0C;AACrE,WAAO,OAAO,QAAQ,IAAI,UAAU,GAAG,SAAS;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,QAAQ,QAAQ,OAAO,EAAE,UAAU,YAAY,QAAQ,IAAI,CAAC,UAAU,YAAY,OAAO,CAAC;AAEhG,SACE,gBAAAC,KAAC,qBAAqB,UAArB,EAA8B,OAC5B,UACH;AAEJ;;;AC7EA,SAAS,mBAAmB,MAAsB;AAChD,SAAO,KACJ,QAAQ,UAAU,EAAE,EACpB,MAAM,MAAM,EACZ,IAAI,OAAK,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,CAAC,EAC/C,KAAK,GAAG;AACb;AAKA,SAAS,aAAa,MAAsB;AAC1C,SAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AACpD;AAMO,SAAS,iBAAiB,OAAgC;AAI/D,QAAM,cAAc,MAAM,MAAM,6CAA6C;AAC7E,MAAI,aAAa;AACf,WAAO;AAAA,MACL,OAAO,GAAG,aAAa,YAAY,CAAC,CAAC,CAAC,gBAAgB,mBAAmB,YAAY,CAAC,CAAC,CAAC;AAAA,MACxF,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,MAAM,6CAA6C;AAC7E,MAAI,aAAa;AACf,WAAO;AAAA,MACL,OAAO,GAAG,aAAa,YAAY,CAAC,CAAC,CAAC,kBAAkB,mBAAmB,YAAY,CAAC,CAAC,CAAC;AAAA,MAC1F,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,MAAM,6CAA6C;AAC7E,MAAI,aAAa;AACf,WAAO;AAAA,MACL,OAAO,GAAG,aAAa,YAAY,CAAC,CAAC,CAAC,kBAAkB,mBAAmB,YAAY,CAAC,CAAC,CAAC;AAAA,MAC1F,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,MAAM,2CAA2C;AACzE,MAAI,WAAW;AACb,WAAO;AAAA,MACL,OAAO,GAAG,aAAa,UAAU,CAAC,CAAC,CAAC,gBAAgB,mBAAmB,UAAU,CAAC,CAAC,CAAC;AAAA,MACpF,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,MAAM,yDAAyD;AACxF,MAAI,YAAY;AACd,WAAO;AAAA,MACL,OAAO,GAAG,aAAa,WAAW,CAAC,CAAC,CAAC,iBAAiB,WAAW,CAAC,CAAC;AAAA,MACnE,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,oBAAoB,MAAM,MAAM,oBAAoB;AAC1D,MAAI,mBAAmB;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,MAAM,0BAA0B;AACxD,MAAI,WAAW;AACb,WAAO;AAAA,MACL,OAAO,UAAU,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,UAAU,CAAC,EAAE,MAAM,CAAC;AAAA,MAClE,QAAQ;AAAA,MACR,mBAAmB;AAAA,IACrB;AAAA,EACF;AAKA,QAAM,gBAAgB,MAAM,MAAM,+BAA+B;AACjE,MAAI,eAAe;AACjB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,IAAI,cAAc,CAAC,CAAC;AAAA,MAC5B,mBAAmB;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,iBAAiB,MAAM,MAAM,sCAAsC;AACzE,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,IAAI,eAAe,CAAC,CAAC;AAAA,MAC7B,mBAAmB;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,iBAAiB,MAAM,MAAM,oCAAoC;AACvE,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,IAAI,eAAe,CAAC,CAAC;AAAA,MAC7B,mBAAmB;AAAA,IACrB;AAAA,EACF;AAIA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,mBAAmB;AAAA,EACrB;AACF;;;AHsXQ,SAmJG,YAAAC,WAnJH,OAAAC,YAAA;AAncD,IAAM,gBAAgBC,eAAyC,IAAI;AAEnE,SAAS,mBAAuC;AACrD,QAAM,MAAMC,YAAW,aAAa;AACpC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO;AACT;AAmBA,IAAM,oBAAoBD,eAA6C,IAAI;AAEpE,SAAS,gBAA+C;AAC7D,SAAOC,YAAW,iBAAiB;AACrC;AAMA,SAAS,mBAAmB,QAAoB,OAA0C;AACxF,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI;AACV,QAAM,OAAO,EAAE;AACf,MAAI,CAAC,KAAM,QAAO;AAKlB,SAAO,OAAO,QAAQ,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,QAAI,OAAO,KAAM,QAAO,KAAK,GAAG,MAAM;AACtC,QAAI,QAAQ,WAAY,QAAO,EAAE,aAAa;AAC9C,QAAI,QAAQ,YAAa,QAAO,EAAE,cAAc;AAChD,WAAO;AAAA,EACT,CAAC;AACH;AAgBA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,cAAc;AAChB,GAAgD;AAE9C,QAAM,CAAC,aAAa,cAAc,IAAIC,UAA6B,IAAI;AACvE,QAAM,CAAC,oBAAoB,qBAAqB,IAAIA,UAAS,IAAI;AAEjE,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,IAAI;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAqB,CAAC,CAAC;AACvD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAA8B,YAAY;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AAIxC,QAAM,uBAAuBC,QAA8D,MAAS;AACpG,QAAM,uBAAuBA,QAA8D,MAAS;AAEpG,QAAM,WAAWA,QAAoB,IAAI,YAAY,CAAC;AACtD,QAAM,QAAQA,QAAyB,IAAI;AAC3C,QAAM,qBAAqBA,QAA4B,oBAAI,IAAI,CAAC;AAChE,QAAM,oBAAoBA,QAAyC,oBAAI,IAAI,CAAC;AAC5E,QAAM,qBAAqBA,QAAsD,oBAAI,IAAI,CAAC;AAC1F,QAAM,qBAAqBA,QAIvB,oBAAI,IAAI,CAAC;AACb,QAAM,sBAAsBA,QAAO,CAAC;AACpC,QAAM,sBAAsBA,QAA6C,IAAI;AAC7E,QAAM,0BAA0BA,QAAO,KAAK;AAC5C,QAAM,iBAAiBA,QAA2B,IAAI;AAEtD,iBAAe,UAAU;AAEzB,QAAM,qBAAqBC,aAAY,YAAY;AACjD,QAAI;AACF,YAAM,UAAU,MAAM,UAAU;AAChC,qBAAe,OAAO;AAAA,IACxB,SAAS,KAAK;AACZ,cAAQ,MAAM,oDAAoD,GAAG;AAAA,IACvE;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAId,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU;AACd,0BAAsB,IAAI;AAC1B,cAAU,EACP,KAAK,aAAW;AAAE,UAAI,QAAS,gBAAe,OAAO;AAAA,IAAE,CAAC,EACxD,QAAQ,MAAM;AAAE,UAAI,QAAS,uBAAsB,KAAK;AAAA,IAAE,CAAC;AAE9D,UAAM,WAAW,YAAY,MAAM;AACjC,UAAI,QAAS,WAAU,EAAE,KAAK,OAAK;AAAE,YAAI,QAAS,gBAAe,CAAC;AAAA,MAAE,CAAC;AAAA,IACvE,GAAG,GAAK;AAER,WAAO,MAAM;AAAE,gBAAU;AAAO,oBAAc,QAAQ;AAAA,IAAE;AAAA,EAC1D,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,gBAAgBD,aAAY,CAAC,UAAwB;AACzD,QAAI,MAAM,gBAAgB,aAAa;AACrC,wBAAkB,QAAQ,QAAQ,aAAW,QAAQ,MAAM,IAAmB,CAAC;AAC/E;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,MAAM,IAAc;AAC3C,YAAM,EAAE,MAAM,QAAQ,IAAI;AAE1B,cAAQ,MAAM;AAAA,QACZ,KAAK,IAAI,WAAW;AAClB,gBAAM,aAAa;AACnB,kBAAQ,IAAI,eAAe,EAAE,QAAQ,MAAM,WAAW,KAAK,CAAC;AAC5D,sBAAY,WAAW,IAAI;AAC3B,mBAAS,IAAI;AACb,8BAAoB,UAAU;AAE9B,gBAAM,KAAK,MAAM;AACjB,cAAI,MAAM,GAAG,eAAe,UAAU,MAAM;AAC1C,eAAG,KAAK,KAAK,UAAU,EAAE,MAAM,IAAI,WAAW,SAAS,CAAC,EAAE,CAAC,CAAC;AAAA,UAC9D;AACA;AAAA,QACF;AAAA,QACA,KAAK,IAAI;AACP,sBAAa,QAAkC,KAAK;AACpD,yBAAe,IAAI;AACnB;AAAA,QACF,KAAK,IAAI,cAAc;AACrB,gBAAM,EAAE,gBAAgB,QAAQ,IAAI;AACpC,qBAAW,CAAC,OAAO,QAAQ,KAAK,mBAAmB,SAAS;AAC1D,gBAAI,UAAU,gBAAgB;AAC5B,uBAAS,QAAQ,eAAe,UAAU,OAAO;AACjD;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAAA,QACA,KAAK,IAAI,eAAe;AACtB,gBAAM,EAAE,YAAY,QAAQ,WAAW,IAAI;AAG3C,qBAAW,CAAC,QAAQ,QAAQ,KAAK,mBAAmB,SAAS;AAC3D,gBAAI;AACF,oBAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,kBAAI,MAAM,eAAe,WAAY;AACrC,oBAAM,UAAU,mBAAmB,QAAQ,MAAM,KAAK;AACtD,oBAAM,SAAS,SAAS,QAAQ,UAAU,UAAU,OAAO,QAAQ;AACnE,kBAAI,eAAe,UAAU;AAC3B,oBAAI,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,cACrE,WAAW,eAAe,UAAU;AAClC,oBAAI,QAAS,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,cACtE,OAAO;AACL,oBAAI,WAAW,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,yBACrE,WAAW,CAAC,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,yBAC3E,CAAC,WAAW,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,cACtF;AAAA,YACF,QAAQ;AAAA,YAAgC;AAAA,UAC1C;AACA;AAAA,QACF;AAAA,QACA,KAAK,IAAI,OAAO;AACd,gBAAM,EAAE,gBAAgB,MAAM,IAAI;AAClC,cAAI,gBAAgB;AAClB,uBAAW,CAAC,OAAO,QAAQ,KAAK,mBAAmB,SAAS;AAC1D,kBAAI,UAAU,gBAAgB;AAAE,yBAAS,QAAQ,SAAS,UAAU,KAAK;AAAG;AAAA,cAAM;AAAA,YACpF;AAAA,UACF,OAAO;AACL,kBAAM,SAAS,iBAAiB,KAAK;AACrC,oBAAQ,MAAM,2BAA2B,KAAK;AAG9C,gBAAI,OAAO,mBAAmB;AAC5B,mCAAqB,UAAU,OAAO,OAAO,OAAO,MAAM;AAAA,YAC5D,OAAO;AACL,mCAAqB,UAAU,OAAO,OAAO,OAAO,MAAM;AAAA,YAC5D;AAAA,UACF;AACA;AAAA,QACF;AAAA,QACA,KAAK,IAAI,UAAU;AACjB,gBAAM,EAAE,YAAY,UAAU,WAAW,SAAS,IAAI;AAGtD,gBAAM,SAAS,GAAG,UAAU,IAAI,QAAQ,IAAI,SAAS;AACrD,6BAAmB,QAAQ,IAAI,MAAM,GAAG,QAAQ,aAAW,QAAQ,QAAQ,CAAC;AAC5E;AAAA,QACF;AAAA,QACA,KAAK,IAAI,KAAK;AACZ,gBAAM,EAAE,WAAW,SAAS,OAAO,GAAG,KAAK,IAAI;AAG/C,gBAAM,UAAU,mBAAmB,QAAQ,IAAI,SAAS;AACxD,cAAI,SAAS;AACX,yBAAa,QAAQ,KAAK;AAC1B,+BAAmB,QAAQ,OAAO,SAAS;AAC3C,gBAAI,QAAS,SAAQ,QAAQ,IAAI;AAAA,gBAC5B,SAAQ,OAAO,IAAI,MAAM,SAAS,mBAAmB,CAAC;AAAA,UAC7D;AACA;AAAA,QACF;AAAA,QACA,KAAK,IAAI,aAAa;AAEpB,gBAAM,KAAK,MAAM;AACjB,cAAI,MAAM,GAAG,eAAe,UAAU,MAAM;AAC1C,uBAAW,CAAC,gBAAgB,QAAQ,KAAK,mBAAmB,SAAS;AACnE,kBAAI;AACF,sBAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,mBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,gBAAgB,MAAM,EAAE,CAAC,CAAC;AAAA,cACrF,QAAQ;AAAA,cAAqB;AAAA,YAC/B;AAAA,UACF;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,cAAQ,MAAM,6CAA6C,CAAC;AAAA,IAC9D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAUA,aAAY,YAAY;AACtC,UAAM,UAAU,eAAe;AAC/B,QAAI,CAAC,WAAW,CAAC,eAAgB;AACjC,QAAI,MAAM,SAAS,eAAe,UAAU,MAAM;AAIhD,UAAI,WAAW,CAAC,wBAAwB,SAAS;AAC/C,gBAAQ,IAAI,uCAAuC,EAAE,OAAO,CAAC;AAC7D,cAAM,QAAQ,UAAU;AACxB,cAAM,QAAQ,MAAM;AACpB,cAAM,UAAU;AAAA,MAClB,OAAO;AACL;AAAA,MACF;AAAA,IACF;AACA,QAAI,MAAM,SAAS,eAAe,UAAU,WAAY;AAExD,QAAI,oBAAoB,SAAS;AAC/B,mBAAa,oBAAoB,OAAO;AACxC,0BAAoB,UAAU;AAAA,IAChC;AAEA,QAAI;AACJ,QAAI,OAAO;AACT,gBAAU,MAAM,QAAQ,SAAS,IAAI;AAAA,IACvC,OAAO;AACL,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,gBAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AAAA,IAChD;AAEA,UAAM,SAAS,IAAI,gBAAgB;AAKnC,QAAI;AACF,YAAM,UAAU,oBAAoB;AACpC,YAAM,QAAQ,MAAM,QAAQ;AAC5B,UAAI,MAAO,QAAO,IAAI,SAAS,KAAK;AAAA,IACtC,QAAQ;AAAA,IAA2B;AAEnC,4BAAwB,UAAU,CAAC,CAAC;AAEpC,UAAM,SAAS,OAAO,MAAM;AAC5B,UAAM,MAAM,GAAG,OAAO,GAAG,MAAM,IAAI,OAAO,SAAS,CAAC;AACpD,YAAQ,IAAI,oBAAoB,EAAE,QAAQ,SAAS,oBAAoB,QAAQ,CAAC;AAChF,UAAM,KAAK,IAAI,UAAU,GAAG;AAC5B,OAAG,aAAa;AAEhB,OAAG,SAAS,MAAM;AAChB,cAAQ,IAAI,mBAAmB,EAAE,OAAO,CAAC;AACzC,gBAAU,WAAW;AAAA,IACvB;AACA,OAAG,YAAY;AACf,OAAG,UAAU,CAAC,UAAU;AACtB,cAAQ,IAAI,gBAAgB,EAAE,QAAQ,MAAM,MAAM,MAAM,QAAQ,MAAM,QAAQ,UAAU,MAAM,SAAS,CAAC;AACxG,gBAAU,cAAc;AACxB,eAAS,KAAK;AACd,YAAM,UAAU;AAChB,iBAAW,CAAC,KAAK,OAAO,KAAK,mBAAmB,SAAS;AACvD,qBAAa,QAAQ,KAAK;AAC1B,gBAAQ,OAAO,IAAI,MAAM,wBAAwB,CAAC;AAAA,MACpD;AACA,yBAAmB,QAAQ,MAAM;AACjC,YAAM,UAAU,oBAAoB;AACpC,YAAM,QAAQ,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAK;AACzD,cAAQ,IAAI,8BAA8B,EAAE,QAAQ,SAAS,SAAS,MAAM,CAAC;AAC7E,0BAAoB,UAAU,UAAU;AACxC,0BAAoB,UAAU,WAAW,SAAS,KAAK;AAAA,IACzD;AACA,OAAG,UAAU,CAAC,MAAM;AAAE,cAAQ,MAAM,eAAe,EAAE,QAAQ,OAAO,EAAE,CAAC;AAAA,IAAE;AACzE,UAAM,UAAU;AAAA,EAClB,GAAG,CAAC,QAAQ,OAAO,eAAe,gBAAgB,gBAAgB,CAAC;AAEnE,EAAAC,WAAU,MAAM;AACd,QAAI,aAAa,GAAI,SAAQ;AAAA,aACpB,kBAAkB,CAAC,mBAAoB,SAAQ;AAAA,EAC1D,GAAG,CAAC,aAAa,IAAI,oBAAoB,gBAAgB,OAAO,CAAC;AAEjE,EAAAA,WAAU,MAAM;AACd,UAAM,yBAAyB,MAAM;AACnC,UAAI,SAAS,oBAAoB,WAAW;AAC1C,cAAM,KAAK,MAAM;AACjB,YAAI,IAAI,eAAe,UAAU,SAAS,eAAe,WAAW,iBAAiB;AACnF,kBAAQ,IAAI,2CAA2C;AACvD,8BAAoB,UAAU;AAC9B,kBAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,sBAAsB;AACpE,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,sBAAsB;AAAA,EACtF,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,EAAAA,WAAU,MAAM;AACd,WAAO,MAAM;AACX,cAAQ,IAAI,6BAA6B,EAAE,OAAO,CAAC;AACnD,UAAI,oBAAoB,QAAS,cAAa,oBAAoB,OAAO;AACzE,YAAM,SAAS,MAAM;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,cAAcD,aAAY,CAAC,YAAgD;AAC/E,UAAM,KAAK,MAAM;AACjB,QAAI,MAAM,GAAG,eAAe,UAAU,KAAM,IAAG,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,QACtE,SAAQ,KAAK,+DAA+D;AAAA,EACnF,GAAG,CAAC,CAAC;AAEL,QAAM,cAAcA,aAAY,CAAC,QAAgB,SAAiB;AAChE,gBAAY,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,QAAQ,KAAK,EAAE,CAAC;AAAA,EAC/D,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,kBAAkBA,aAAY,MAAM;AACxC,gBAAY,EAAE,MAAM,IAAI,WAAW,SAAS,CAAC,EAAE,CAAC;AAAA,EAClD,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,uBAAuBA,aAAY,CAAC,gBAAwB,aAAqB;AACrF,uBAAmB,QAAQ,IAAI,gBAAgB,QAAQ;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyBA,aAAY,CAAC,mBAA2B;AACrE,uBAAmB,QAAQ,OAAO,cAAc;AAAA,EAClD,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA,aAAY,CAAC,SAAqB;AACnD,UAAM,KAAK,MAAM;AACjB,QAAI,MAAM,GAAG,eAAe,UAAU,KAAM,IAAG,KAAK,IAAI;AAAA,EAC1D,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkBA,aAAY,CAAC,YAAyC;AAC5E,sBAAkB,QAAQ,IAAI,OAAO;AACrC,WAAO,MAAM;AAAE,wBAAkB,QAAQ,OAAO,OAAO;AAAA,IAAE;AAAA,EAC3D,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyBA,aAAY,CAAC,QAAgB,YAAyC;AACnG,QAAI,CAAC,mBAAmB,QAAQ,IAAI,MAAM,GAAG;AAC3C,yBAAmB,QAAQ,IAAI,QAAQ,oBAAI,IAAI,CAAC;AAAA,IAClD;AACA,uBAAmB,QAAQ,IAAI,MAAM,EAAG,IAAI,OAAO;AACnD,WAAO,MAAM;AACX,YAAM,WAAW,mBAAmB,QAAQ,IAAI,MAAM;AACtD,UAAI,UAAU;AACZ,iBAAS,OAAO,OAAO;AACvB,YAAI,SAAS,SAAS,EAAG,oBAAmB,QAAQ,OAAO,MAAM;AAAA,MACnE;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA,aAAY,CAChC,SACA,YAAY,QACS;AACrB,UAAM,YAAY,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACzE,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,MAAM;AAC3C,aAAO,QAAQ,OAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,IAC5D;AACA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,QAAQ,WAAW,MAAM;AAC7B,2BAAmB,QAAQ,OAAO,SAAS;AAC3C,eAAO,IAAI,MAAM,iCAAiC,CAAC;AAAA,MACrD,GAAG,SAAS;AACZ,yBAAmB,QAAQ,IAAI,WAAW,EAAE,SAAS,QAAQ,MAAM,CAAC;AACpE,SAAG,KAAK,KAAK,UAAU,EAAE,GAAG,SAAS,SAAS,EAAE,GAAG,QAAQ,SAAS,UAAU,EAAE,CAAC,CAAC;AAAA,IACpF,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,QAA4BE,SAAQ,OAAO;AAAA,IAC/C,OAAO,SAAS;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAoB;AAAA,IAClE;AAAA,IAAU;AAAA,IAAU;AAAA,IAAa;AAAA,IAAQ;AAAA,IACzC;AAAA,IAAa;AAAA,IACb;AAAA,IAAsB;AAAA,IAAwB;AAAA,IAAa;AAAA,IAAY;AAAA,IACvE;AAAA,IAAwB;AAAA,EAC1B,IAAI,CAAC,QAAQ,aAAa,oBAAoB,oBAAoB,UAAU,UAAU,aAAa,QAAQ,OAAO,aAAa,iBAAiB,sBAAsB,wBAAwB,aAAa,YAAY,iBAAiB,wBAAwB,aAAa,CAAC;AAE9Q,QAAM,oBAAoBF,aAAY,CAAC,OAAe,WAAmB;AACvE,yBAAqB,UAAU,OAAO,MAAM;AAAA,EAC9C,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoBA,aAAY,CAAC,OAAe,WAAmB;AACvE,yBAAqB,UAAU,OAAO,MAAM;AAAA,EAC9C,GAAG,CAAC,CAAC;AAEL,QAAM,YAAoCE,SAAQ,OAAO;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,IAAI,CAAC,aAAa,oBAAoB,oBAAoB,gBAAgB,kBAAkB,mBAAmB,iBAAiB,CAAC;AAEjI,SACE,gBAAAP,KAAC,kBAAkB,UAAlB,EAA2B,OAAO,WACjC,0BAAAA,KAAC,yBACC,0BAAAA,KAAC,cAAc,UAAd,EAAuB,OACrB,UACH,GACF,GACF;AAEJ;AAaA,SAAS,uBAAuB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,cAAc;AAChB,GAAoD;AAClD,QAAM,CAAC,aAAa,cAAc,IAAIG,UAA6B,IAAI;AACvE,QAAM,CAAC,oBAAoB,qBAAqB,IAAIA,UAAS,IAAI;AAEjE,QAAM,qBAAqBE,aAAY,YAAY;AACjD,QAAI;AACF,YAAM,UAAU,MAAM,UAAU;AAChC,qBAAe,OAAO;AAAA,IACxB,SAAS,KAAK;AACZ,cAAQ,MAAM,oDAAoD,GAAG;AAAA,IACvE;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAId,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU;AACd,0BAAsB,IAAI;AAC1B,cAAU,EACP,KAAK,aAAW;AAAE,UAAI,QAAS,gBAAe,OAAO;AAAA,IAAE,CAAC,EACxD,QAAQ,MAAM;AAAE,UAAI,QAAS,uBAAsB,KAAK;AAAA,IAAE,CAAC;AAE9D,UAAM,WAAW,YAAY,MAAM;AACjC,UAAI,SAAS;AACX,kBAAU,EAAE,KAAK,OAAK;AAAE,cAAI,QAAS,gBAAe,CAAC;AAAA,QAAE,CAAC;AAAA,MAC1D;AAAA,IACF,GAAG,GAAK;AAER,WAAO,MAAM;AAAE,gBAAU;AAAO,oBAAc,QAAQ;AAAA,IAAE;AAAA,EAC1D,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,YAAoCC,SAAQ,OAAO;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,EAChB,IAAI,CAAC,aAAa,oBAAoB,oBAAoB,gBAAgB,gBAAgB,CAAC;AAE3F,SACE,gBAAAP,KAAC,kBAAkB,UAAlB,EAA2B,OAAO,WACjC,0BAAAA,KAAC,yBACE,UACH,GACF;AAEJ;AA+BO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,UAAU,CAAC;AAAA,EACX;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,cAAc;AAChB,GAOuB;AACrB,QAAM,EAAE,UAAU,WAAW,IAAI,QAAQ;AAIzC,QAAM,YAAYK,aAAY,YAAyC;AACrE,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,QAAQ,MAAM,aAAa;AACjC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI;AACF,YAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,YAAM,UAAU,KAAK,MAAM,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,CAAC,CAAC;AAC/E,aAAO;AAAA,QACL,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ,QAAQ;AAAA,QACtB,OAAO,QAAQ,SAAS;AAAA,QACxB,UAAU,QAAQ,SAAS;AAAA,MAC7B;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAGf,QAAM,iBAAiBA,aAAY,YAAoC;AACrE,QAAI,iBAAkB,QAAO,iBAAiB;AAC9C,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,aAAa;AAAA,EACtB,GAAG,CAAC,kBAAkB,UAAU,CAAC;AAGjC,MAAI,CAAC,UAAU;AACb,WAAO,gBAAAL,KAAAD,WAAA,EAAG,gBAAK;AAAA,EACjB;AAGA,MAAI,CAAC,cAAc,CAAC,gBAAgB;AAClC,WAAO,gBAAAC,KAAAD,WAAA,EAAG,gBAAK;AAAA,EACjB;AAEA,MAAI,QAAQ;AACV,WACE,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QAEb;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MAEb;AAAA;AAAA,EACH;AAEJ;;;AI/pBA;AAAA,EACE,aAAAQ;AAAA,EACA,YAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,OAEK;;;AC3BP,IAAI,cAAc;AAEX,SAAS,MAAM,OAAgE,OAAe;AACnG,MAAI,UAAU,YAAa;AAC3B,MAAI,UAAU,UAAW;AAEzB,UAAQ,IAAI,WAAW,KAAK,WAAM,KAAK,KAAK,WAAW,UAAU;AACnE;;;AD6FI,SA+cA,YAAAC,WA/cA,OAAAC,MA+cA,QAAAC,aA/cA;AAzDJ,SAASC,oBACP,QACA,OACS;AACT,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI;AACV,QAAM,OAAO,EAAE;AACf,MAAI,CAAC,KAAM,QAAO;AAKlB,SAAO,OAAO,QAAQ,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,QAAI,OAAO,KAAM,QAAO,KAAK,GAAG,MAAM;AACtC,QAAI,QAAQ,WAAY,QAAO,EAAE,aAAa;AAC9C,QAAI,QAAQ,YAAa,QAAO,EAAE,cAAc;AAChD,WAAO;AAAA,EACT,CAAC;AACH;AA+BA,SAAS,cAAc,EAAE,QAAQ,SAAS,OAAO,OAAO,aAAa,GAMlE;AACD,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;AAMA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,WAAW;AACb,GAQG;AACD,QAAM,OAAO,cAAc;AAC3B,QAAM,WAAW,iBAAiB;AAElC,QAAM,aAAaG,QAAO,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE;AAGzF,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAwB,IAAI;AAC5D,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAqB,CAAC,CAAC;AACvD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAA8B,YAAY;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AACxC,QAAM,CAAC,mBAAmB,oBAAoB,IAAIA,UAA6B,CAAC,CAAC;AAGjF,QAAM,WAAWD,QAAoB,IAAI,YAAY,CAAC;AACtD,QAAM,QAAQA,QAAyB,IAAI;AAC3C,QAAM,qBAAqBA,QAA4B,oBAAI,IAAI,CAAC;AAChE,QAAM,oBAAoBA,QAAyC,oBAAI,IAAI,CAAC;AAC5E,QAAM,qBAAqBA,QAAsD,oBAAI,IAAI,CAAC;AAC1F,QAAM,qBAAqBA,QAIvB,oBAAI,IAAI,CAAC;AACb,QAAM,sBAAsBA,QAAO,CAAC;AACpC,QAAM,sBAAsBA,QAA6C,IAAI;AAG7E,QAAM,iBAAiBA,QAAO,MAAM,eAAe,IAAI;AACvD,iBAAe,UAAU,MAAM,eAAe;AAC9C,QAAM,kBAAkBA,QAAO,MAAM,gBAAgB,IAAI;AACzD,kBAAgB,UAAU,MAAM,gBAAgB;AAChD,QAAM,mBAAmBA,QAAO;AAAA,IAC9B,mBAAmB,MAAM;AAAA,IACzB,mBAAmB,MAAM;AAAA,EAC3B,CAAC;AACD,mBAAiB,QAAQ,oBAAoB,MAAM;AACnD,mBAAiB,QAAQ,oBAAoB,MAAM;AACnD,QAAM,iBAAiB,MAAM,kBAAkB;AAI/C,QAAM,gBAAgBE,aAAY,CAAC,UAAwB;AACzD,QAAI,MAAM,gBAAgB,aAAa;AACrC,wBAAkB,QAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAmB,CAAC;AACrE;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,KAAK,MAAM,MAAM,IAAc;AAAA,IACvC,QAAQ;AACN,cAAQ,MAAM,uCAAuC;AACrD;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI;AAE1B,YAAQ,MAAM;AAAA,MACZ,KAAK,IAAI,WAAW;AAClB,cAAM,EAAE,KAAK,IAAI;AACjB,oBAAY,IAAI;AAChB,iBAAS,IAAI;AACb,4BAAoB,UAAU;AAC9B,cAAM,KAAK,MAAM;AACjB,YAAI,IAAI,eAAe,UAAU,MAAM;AACrC,aAAG,KAAK,KAAK,UAAU,EAAE,MAAM,IAAI,WAAW,SAAS,CAAC,EAAE,CAAC,CAAC;AAAA,QAC9D;AACA;AAAA,MACF;AAAA,MAEA,KAAK,IAAI;AACP,oBAAa,QAAkC,KAAK;AACpD,uBAAe,IAAI;AACnB;AAAA,MAEF,KAAK,IAAI,cAAc;AACrB,cAAM,EAAE,gBAAgB,QAAQ,IAAI;AACpC,mBAAW,CAAC,OAAO,QAAQ,KAAK,mBAAmB,SAAS;AAC1D,cAAI,UAAU,gBAAgB;AAC5B,qBAAS,QAAQ,eAAe,UAAU,OAAO;AACjD;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,eAAe;AACtB,cAAM,EAAE,YAAY,QAAQ,WAAW,IAAI;AAG3C,mBAAW,CAAC,EAAE,QAAQ,KAAK,mBAAmB,SAAS;AACrD,cAAI;AACF,kBAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,gBAAI,MAAM,eAAe,WAAY;AACrC,kBAAM,UAAUH,oBAAmB,QAAQ,MAAM,KAAK;AACtD,kBAAM,SAAS,SAAS,QAAQ,UAAU,UAAU,OAAO,QAAQ;AACnE,gBAAI,eAAe,UAAU;AAC3B,kBAAI,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,YACrE,WAAW,eAAe,UAAU;AAClC,kBAAI,QAAS,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,YACtE,OAAO;AACL,kBAAI,WAAW,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,uBACrE,WAAW,CAAC,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,uBAC3E,CAAC,WAAW,OAAQ,UAAS,QAAQ,YAAY,UAAU,QAAQ,QAAQ;AAAA,YACtF;AAAA,UACF,QAAQ;AAAA,UAAgC;AAAA,QAC1C;AACA;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,OAAO;AACd,cAAM,EAAE,gBAAgB,MAAM,IAAI;AAClC,YAAI,gBAAgB;AAClB,qBAAW,CAAC,OAAO,QAAQ,KAAK,mBAAmB,SAAS;AAC1D,gBAAI,UAAU,gBAAgB;AAC5B,uBAAS,QAAQ,SAAS,UAAU,KAAK;AACzC;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAM,SAAS,iBAAiB,KAAK;AACrC,cAAI,OAAO,mBAAmB;AAC5B,6BAAiB,QAAQ,oBAAoB,OAAO,OAAO,OAAO,MAAM;AAAA,UAC1E,OAAO;AACL,6BAAiB,QAAQ,oBAAoB,OAAO,OAAO,OAAO,MAAM;AAAA,UAC1E;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,UAAU;AACjB,cAAM,EAAE,YAAY,UAAU,WAAW,SAAS,IAAI;AAGtD,cAAM,SAAS,GAAG,UAAU,IAAI,QAAQ,IAAI,SAAS;AACrD,2BAAmB,QAAQ,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;AAClE;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,KAAK;AACZ,cAAM,EAAE,WAAW,SAAS,OAAO,GAAG,KAAK,IAAI;AAG/C,cAAM,UAAU,mBAAmB,QAAQ,IAAI,SAAS;AACxD,YAAI,SAAS;AACX,uBAAa,QAAQ,KAAK;AAC1B,6BAAmB,QAAQ,OAAO,SAAS;AAC3C,oBAAU,QAAQ,QAAQ,IAAI,IAAI,QAAQ,OAAO,IAAI,MAAM,SAAS,mBAAmB,CAAC;AAAA,QAC1F;AACA;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,cAAc;AACrB,cAAM,EAAE,SAAS,KAAK,IAAI;AAC1B,6BAAqB,QAAQ,CAAC,CAAC;AAC/B;AAAA,MACF;AAAA,MAEA,KAAK,IAAI,aAAa;AACpB,cAAM,KAAK,MAAM;AACjB,YAAI,IAAI,eAAe,UAAU,MAAM;AACrC,qBAAW,CAAC,gBAAgB,QAAQ,KAAK,mBAAmB,SAAS;AACnE,gBAAI;AACF,oBAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,iBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,gBAAgB,MAAM,EAAE,CAAC,CAAC;AAAA,YACrF,QAAQ;AAAA,YAAa;AAAA,UACvB;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAIX,QAAM,UAAUG,aAAY,YAAY;AACtC,UAAM,UAAU,eAAe;AAC/B,UAAM,mBAAmB,CAAC,CAAC,gBAAgB;AAC3C,QAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,eAAgB;AAEtD,QAAI,MAAM,SAAS,eAAe,UAAU,QAAQ,MAAM,SAAS,eAAe,UAAU,WAAY;AAExG,QAAI,oBAAoB,SAAS;AAC/B,mBAAa,oBAAoB,OAAO;AACxC,0BAAoB,UAAU;AAAA,IAChC;AAEA,UAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,UAAM,UAAU,OAAO,QAAQ,SAAS,IAAI,KAAK,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACrF,UAAM,SAAS,IAAI,gBAAgB;AAKnC,QAAI;AACF,YAAM,UAAU,gBAAgB,WAAW;AAC3C,YAAM,QAAQ,MAAM,QAAQ;AAC5B,UAAI,MAAO,QAAO,IAAI,SAAS,KAAK;AAAA,IACtC,QAAQ;AAAA,IAAyD;AAEjE,WAAO,IAAI,SAAS,KAAK;AAEzB,UAAM,MAAM,GAAG,OAAO,GAAG,YAAY,IAAI,MAAM,IAAI,OAAO,SAAS,CAAC;AACpE,UAAM,cAAc,MAAM;AAC1B,UAAM,KAAK,IAAI,UAAU,GAAG;AAC5B,OAAG,aAAa;AAChB,UAAM,UAAU;AAEhB,OAAG,SAAS,MAAM;AAChB,YAAM,aAAa,MAAM;AACzB,gBAAU,WAAW;AAErB,iBAAW,CAAC,gBAAgB,QAAQ,KAAK,mBAAmB,SAAS;AACnE,YAAI;AACF,gBAAM,QAAQ,KAAK,MAAM,QAAQ;AACjC,aAAG,KAAK,KAAK,UAAU,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,gBAAgB,MAAM,EAAE,CAAC,CAAC;AAAA,QACrF,QAAQ;AAAA,QAAa;AAAA,MACvB;AAAA,IACF;AAEA,OAAG,YAAY;AAEf,OAAG,UAAU,MAAM;AACjB,YAAM,gBAAgB,MAAM;AAC5B,gBAAU,cAAc;AACxB,eAAS,KAAK;AACd,YAAM,UAAU;AAChB,iBAAW,CAAC,EAAE,QAAQ,KAAK,mBAAmB,QAAS,UAAS,QAAQ,eAAe,QAAQ;AAC/F,iBAAW,CAAC,EAAE,OAAO,KAAK,mBAAmB,SAAS;AACpD,qBAAa,QAAQ,KAAK;AAC1B,gBAAQ,OAAO,IAAI,MAAM,wBAAwB,CAAC;AAAA,MACpD;AACA,yBAAmB,QAAQ,MAAM;AACjC,YAAM,UAAU,oBAAoB;AACpC,YAAM,QAAQ,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,OAAO,GAAG,GAAK;AACzD,0BAAoB,UAAU,UAAU;AACxC,0BAAoB,UAAU,WAAW,SAAS,KAAK;AAAA,IACzD;AAEA,OAAG,UAAU,MAAM;AAAA,IAAC;AAAA,EACtB,GAAG,CAAC,QAAQ,OAAO,cAAc,eAAe,gBAAgB,KAAK,CAAC;AAItE,QAAM,aAAaA,aAAY,MAAM;AACnC,QAAI,oBAAoB,SAAS;AAC/B,mBAAa,oBAAoB,OAAO;AACxC,0BAAoB,UAAU;AAAA,IAChC;AACA,UAAM,KAAK,MAAM;AACjB,QAAI,IAAI;AACN,YAAM,WAAW,MAAM;AACvB,SAAG,UAAU;AACb,SAAG,YAAY;AACf,SAAG,UAAU;AACb,SAAG,MAAM;AACT,YAAM,UAAU;AAAA,IAClB;AACA,cAAU,YAAY;AACtB,aAAS,KAAK;AACd,wBAAoB,UAAU;AAAA,EAChC,GAAG,CAAC,MAAM,CAAC;AAMX,QAAM,gBAAgB,MAAM,aAAa,MAAM;AAC/C,QAAM,qBAAqB,MAAM,sBAAsB;AAEvD,EAAAC,WAAU,MAAM;AAEd,QAAI,mBAAoB;AAGxB,eAAW;AAGX,QAAI,iBAAiB,gBAAgB;AACnC,cAAQ;AAAA,IACV;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,eAAe,oBAAoB,gBAAgB,SAAS,UAAU,CAAC;AAG3E,EAAAA,WAAU,MAAM;AACd,UAAM,YAAY,MAAM;AACtB,UAAI,SAAS,oBAAoB,aAAa,MAAM,SAAS,eAAe,UAAU,MAAM;AAC1F,4BAAoB,UAAU;AAC9B,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,SAAS;AACvD,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,SAAS;AAAA,EACzE,GAAG,CAAC,OAAO,CAAC;AAIZ,QAAM,cAAcD,aAAY,CAAC,YAAgD;AAC/E,UAAM,KAAK,MAAM;AACjB,QAAI,IAAI,eAAe,UAAU,KAAM,IAAG,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,EACxE,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA,aAAY,CAAC,SAAqB;AACnD,UAAM,KAAK,MAAM;AACjB,QAAI,IAAI,eAAe,UAAU,KAAM,IAAG,KAAK,IAAI;AAAA,EACrD,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAkBA,aAAY,CAAC,YAAyC;AAC5E,sBAAkB,QAAQ,IAAI,OAAO;AACrC,WAAO,MAAM;AAAE,wBAAkB,QAAQ,OAAO,OAAO;AAAA,IAAE;AAAA,EAC3D,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyBA,aAAY,CAAC,QAAgB,YAAyC;AACnG,QAAI,CAAC,mBAAmB,QAAQ,IAAI,MAAM,EAAG,oBAAmB,QAAQ,IAAI,QAAQ,oBAAI,IAAI,CAAC;AAC7F,uBAAmB,QAAQ,IAAI,MAAM,EAAG,IAAI,OAAO;AACnD,WAAO,MAAM;AACX,YAAM,WAAW,mBAAmB,QAAQ,IAAI,MAAM;AACtD,UAAI,UAAU;AAAE,iBAAS,OAAO,OAAO;AAAG,YAAI,SAAS,SAAS,EAAG,oBAAmB,QAAQ,OAAO,MAAM;AAAA,MAAE;AAAA,IAC/G;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA,aAAY,CAChC,SACA,YAAY,QACS;AACrB,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM,QAAO,QAAQ,OAAO,IAAI,MAAM,yBAAyB,CAAC;AACvG,UAAM,YAAY,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AACzE,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,QAAQ,WAAW,MAAM;AAC7B,2BAAmB,QAAQ,OAAO,SAAS;AAC3C,eAAO,IAAI,MAAM,iCAAiC,CAAC;AAAA,MACrD,GAAG,SAAS;AACZ,yBAAmB,QAAQ,IAAI,WAAW,EAAE,SAAS,QAAQ,MAAM,CAAC;AACpE,SAAG,KAAK,KAAK,UAAU,EAAE,GAAG,SAAS,SAAS,EAAE,GAAG,QAAQ,SAAS,UAAU,EAAE,CAAC,CAAC;AAAA,IACpF,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,cAAcA,aAAY,CAAC,QAAgB,SAAiB;AAChE,gBAAY,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,QAAQ,KAAK,EAAE,CAAC;AAAA,EAC/D,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,kBAAkBA,aAAY,MAAM;AACxC,gBAAY,EAAE,MAAM,IAAI,WAAW,SAAS,CAAC,EAAE,CAAC;AAAA,EAClD,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,uBAAuBA,aAAY,CAAC,gBAAwB,aAAqB;AACrF,uBAAmB,QAAQ,IAAI,gBAAgB,QAAQ;AAAA,EACzD,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyBA,aAAY,CAAC,mBAA2B;AACrE,uBAAmB,QAAQ,OAAO,cAAc;AAAA,EAClD,GAAG,CAAC,CAAC;AAGL,EAAAC,WAAU,MAAM;AACd,QAAI,MAAO,aAAY,EAAE,MAAM,IAAI,cAAc,SAAS,CAAC,EAAE,CAAC;AAAA,EAChE,GAAG,CAAC,OAAO,WAAW,CAAC;AAIvB,QAAM,gBAAgBH,QAA0B,IAAI;AACpD,MAAI,CAAC,cAAc,SAAS;AAC1B,kBAAc,UAAU;AAAA,MACtB,OAAO,SAAS;AAAA,MAAS;AAAA,MAAa;AAAA,MACtC;AAAA,MAAsB;AAAA,MAAwB;AAAA,MAAY;AAAA,MAC1D;AAAA,MAAwB;AAAA,MAAO;AAAA,IACjC;AAAA,EACF;AACA,gBAAc,QAAQ,QAAQ;AAC9B,gBAAc,QAAQ,SAAS;AAE/B,QAAM,uBAAuBA,QAAkC,IAAI;AACnE,MAAI,CAAC,YAAY,YAAY,YAAY,qBAAqB,SAAS;AACrE,QAAI,qBAAqB,SAAS;AAChC,eAAS,WAAW,WAAW,SAAS,qBAAqB,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,IACzF;AACA,UAAM,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI;AACvC,QAAI,MAAM,SAAS,EAAG,UAAS,SAAS,WAAW,SAAS,OAAO,cAAc,OAAQ;AACzF,yBAAqB,UAAU;AAAA,EACjC;AAEA,EAAAG,WAAU,MAAM;AACd,QAAI,YAAY,CAAC,SAAU;AAC3B,WAAO,MAAM;AACX,YAAM,SAAS,qBAAqB,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI;AACpE,UAAI,MAAM,SAAS,EAAG,UAAS,WAAW,WAAW,SAAS,KAAK;AAAA,IACrE;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,MAAM,CAAC;AAI/B,QAAM,wBAAwBC,SAAQ,MAAM,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;AAE1F,QAAM,QAA4BA,SAAQ,OAAO;AAAA,IAC/C,OAAO,SAAS;AAAA,IAAS;AAAA,IAAQ;AAAA,IACjC,aAAa,MAAM,eAAe;AAAA,IAClC,oBAAoB,MAAM,sBAAsB;AAAA,IAChD,oBAAoB,MAAM,uBAAuB,YAAY;AAAA,IAAC;AAAA,IAC9D;AAAA,IAAU;AAAA,IAAU;AAAA,IAAa;AAAA,IAAQ;AAAA,IAAO;AAAA,IAChD;AAAA,IAAa;AAAA,IAAiB;AAAA,IAAsB;AAAA,IACpD;AAAA,IAAa;AAAA,IAAY;AAAA,IAAiB;AAAA,IAAwB;AAAA,EACpE,IAAI;AAAA,IACF;AAAA,IAAQ;AAAA,IAAuB,MAAM;AAAA,IAAa,MAAM;AAAA,IACxD,MAAM;AAAA,IAAoB;AAAA,IAAU;AAAA,IAAU;AAAA,IAAa;AAAA,IAAQ;AAAA,IACnE;AAAA,IAAmB;AAAA,IAAa;AAAA,IAAiB;AAAA,IACjD;AAAA,IAAwB;AAAA,IAAa;AAAA,IAAY;AAAA,IACjD;AAAA,IAAwB;AAAA,EAC1B,CAAC;AAED,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,gBAAAP,KAAC,cAAc,UAAd,EAAuB,OAAe,UAAS;AACzD;AAMO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,WAAW;AACb,GAAqB;AACnB,SACE,gBAAAC,MAAAF,WAAA,EACG;AAAA,kBAAc,IAAI,CAAC,WAClB,gBAAAC;AAAA,MAAC;AAAA;AAAA,QAEC,QAAQ,OAAO;AAAA,QACf,SAAS,OAAO;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA;AAAA,MALK,OAAO;AAAA,IAMd,CACD;AAAA,IACD,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QAEC;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;;;AExkBA,SAAS,WAAAQ,gBAAe;AA6BjB,SAAS,UAId;AACA,QAAM,EAAE,aAAa,oBAAoB,oBAAoB,SAAS,IAAI,iBAAiB;AAG3F,QAAM,OAAOC,SAAQ,MAAmB;AACtC,QAAI,CAAC,YAAa,QAAO;AACzB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,YAAY;AAAA;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,aAAa,QAAQ,CAAC;AAE1B,SAAO,EAAE,MAAM,WAAW,oBAAoB,SAAS,mBAAmB;AAC5E;;;AC5CA,SAAS,aAAAC,YAAW,eAAAC,cAAa,UAAAC,SAAQ,WAAAC,UAAS,cAAAC,aAAY,4BAA4B;AAmBnF,SAAS,SACd,YACA,SAUA;AAEA,QAAM,WAAW,iBAAiB;AAClC,QAAM,YAAYC,YAAW,aAAa;AAE1C,QAAM,aAAa,UAAU,QAAQ,UAAU,KAAK;AAGpD,QAAM,cAAc,WAAW,uBAAuB,IAAI,UAAU,KAAK;AACzE,QAAM,QAAQ,cAAc,UAAW,QAAS,YAAY,SAAS,WAAW;AAChF,QAAM,cAAc,cAAc,UAAW,cAAe,YAAY,eAAe,WAAW;AAClG,QAAM,cAAc,cAAc,UAAW,uBAAwB,YAAY,wBAAwB,WAAW;AACpH,QAAM,gBAAgB,cAAc,UAAW,yBAA0B,YAAY,0BAA0B,WAAW;AAE1H,MAAI,CAAC,SAAS,CAAC,eAAe,CAAC,eAAe,CAAC,eAAe;AAC5D,UAAM,IAAI;AAAA,MACR,aAAa,UAAU;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,aAAa,KAAK,UAAU,WAAW,IAAI;AAEjD,QAAM,QAAeC;AAAA,IACnB,OAAO;AAAA,MACL;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA;AAAA,IAElB;AAAA,IACA,CAAC,YAAY,UAAU;AAAA,EACzB;AAEA,QAAM,WAAWA,SAAQ,MAAM,KAAK,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC;AAE7D,QAAM,oBAAoBC;AAAA,IACxB,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,EAC1D;AAEA,EAAAC,WAAU,MAAM;AACd,UAAM,iBAAiB,kBAAkB;AAEzC,UAAM,UAAU,MAAM,UAAU,QAAQ;AAExC,QAAI,SAAS;AACX,YAAM,kBAAkB,UAAU,cAAc;AAChD,kBAAY,gBAAgB,QAAQ;AACpC,kBAAY,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,gBAAgB,MAAM,EAAE,CAAC;AAAA,IACzE;AAEA,WAAO,MAAM;AACX,YAAM,cAAc,MAAM,kBAAkB,QAAQ,KAAK;AACzD,YAAM,SAAS,MAAM,aAAa,QAAQ;AAE1C,UAAI,QAAQ;AACV,oBAAY,EAAE,MAAM,IAAI,aAAa,SAAS,EAAE,gBAAgB,YAAY,EAAE,CAAC;AAC/E,sBAAc,WAAW;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,OAAO,OAAO,aAAa,aAAa,eAAe,UAAU,CAAC;AAEhF,QAAM,YAAYC;AAAA,IAChB,CAAC,kBAA8B,MAAM,UAAU,UAAU,aAAa;AAAA,IACtE,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,cAAcA;AAAA,IAClB,MAAM,MAAM,YAAY,QAAQ;AAAA,IAChC,CAAC,OAAO,QAAQ;AAAA,EAClB;AAEA,QAAM,UAAU,qBAAqB,WAAW,aAAa,WAAW;AACxE,QAAM,SAAS,MAAM,UAAU,QAAQ;AACvC,QAAM,QAAQ,MAAM,SAAS,QAAQ;AAIrC,SAAOH,SAAQ,OAAO,EAAE,SAAS,QAAQ,MAAM,IAAI,CAAC,SAAS,QAAQ,KAAK,CAAC;AAC7E;;;AC9GA,SAAS,eAAAI,cAAa,cAAAC,aAAY,WAAAC,gBAAe;AA4B1C,SAAS,aAA0B,YAOxC;AAEA,QAAM,WAAW,iBAAiB;AAClC,QAAM,YAAYC,YAAW,aAAa;AAE1C,QAAM,aAAa,UAAU,QAAQ,UAAU,KAAK;AAGpD,QAAM,cAAc,WAAW,uBAAuB,IAAI,UAAU,KAAK;AACzE,QAAM,cAAc,cAAc,UAAW,cAAe,YAAY,eAAe,WAAW;AAClG,QAAM,gBAAgB,cAAc,UAAW,gBAAiB,YAAY,iBAAiB,WAAW;AAExG,MAAI,CAAC,eAAe,CAAC,eAAe;AAClC,UAAM,IAAI;AAAA,MACR,iBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,SAASC;AAAA,IACb,OAAO,SAA6B;AAClC,YAAM,WAAW,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACzE,kBAAY,EAAE,MAAM,IAAI,KAAK,SAAS,EAAE,YAAY,UAAU,KAAK,EAAE,CAAC;AACtE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,aAAa,UAAU;AAAA,EAC1B;AAEA,QAAM,MAAMA;AAAA,IACV,OAAO,UAAkB,SAAoC;AAC3D,kBAAY,EAAE,MAAM,IAAI,KAAK,SAAS,EAAE,YAAY,UAAU,KAAK,EAAE,CAAC;AAAA,IACxE;AAAA,IACA,CAAC,aAAa,UAAU;AAAA,EAC1B;AAEA,QAAM,SAASA;AAAA,IACb,OAAO,aAAoC;AACzC,kBAAY,EAAE,MAAM,IAAI,QAAQ,SAAS,EAAE,YAAY,SAAS,EAAE,CAAC;AAAA,IACrE;AAAA,IACA,CAAC,aAAa,UAAU;AAAA,EAC1B;AAEA,QAAM,kBAAkBA;AAAA,IACtB,OAAO,SAA6B;AAClC,YAAM,WAAW,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACzE,YAAM,cAAc;AAAA,QAClB,MAAM,IAAI;AAAA,QACV,SAAS,EAAE,YAAY,UAAU,KAAsC;AAAA,MACzE,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,eAAe,UAAU;AAAA,EAC5B;AAEA,QAAM,eAAeA;AAAA,IACnB,OAAO,UAAkB,SAAoC;AAC3D,YAAM,cAAc;AAAA,QAClB,MAAM,IAAI;AAAA,QACV,SAAS,EAAE,YAAY,UAAU,KAAsC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,IACA,CAAC,eAAe,UAAU;AAAA,EAC5B;AAEA,QAAM,kBAAkBA;AAAA,IACtB,OAAO,aAAoC;AACzC,YAAM,cAAc,EAAE,MAAM,IAAI,QAAQ,SAAS,EAAE,YAAY,SAAS,EAAE,CAAC;AAAA,IAC7E;AAAA,IACA,CAAC,eAAe,UAAU;AAAA,EAC5B;AAMA,SAAOC;AAAA,IACL,OAAO,EAAE,QAAQ,KAAK,QAAQ,iBAAiB,cAAc,gBAAgB;AAAA,IAC7E,CAAC,QAAQ,KAAK,QAAQ,iBAAiB,cAAc,eAAe;AAAA,EACtE;AACF;;;AClHA,SAAS,aAAAC,YAAW,WAAAC,gBAAe;AAI5B,SAAS,WAKd;AACA,QAAM,EAAE,UAAU,aAAa,aAAa,iBAAiB,MAAM,IAAI,iBAAiB;AAExF,EAAAC,WAAU,MAAM;AACd,QAAI,MAAO,iBAAgB;AAAA,EAC7B,GAAG,CAAC,OAAO,eAAe,CAAC;AAE3B,QAAM,QAAQC,SAAQ,MAAM,UAAU,CAAC,QAAQ,CAAC;AAEhD,SAAO,EAAE,OAAO,aAAa,SAAS,aAAa,SAAS,gBAAgB;AAC9E;;;ACpBA,SAAS,YAAAC,WAAU,aAAAC,YAAW,eAAAC,cAAa,UAAAC,eAAc;AACzD,YAAYC,QAAO;AA6CZ,SAAS,YACd,YACA,UACA,WACmB;AACnB,QAAM,EAAE,aAAa,YAAY,iBAAiB,wBAAwB,MAAM,IAAI,iBAAiB;AACrG,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,CAAC;AAChD,QAAM,cAAcC,QAAO,KAAK;AAGhC,QAAM,SAASA,QAAqB,IAAI;AACxC,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,UAAU,IAAM,OAAI;AAAA,EAC7B;AACA,QAAM,MAAM,OAAO;AAGnB,QAAM,eAAeA,QAAyB,IAAI;AAClD,MAAI,CAAC,aAAa,SAAS;AACzB,iBAAa,UAAU,IAAI,UAAU,GAAG;AAAA,EAC1C;AACA,QAAM,YAAY,aAAa;AAE/B,QAAM,SAAS,GAAG,UAAU,IAAI,QAAQ,IAAI,SAAS;AAGrD,EAAAC,WAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,QAAQ,CAAC;AAGb,EAAAA,WAAU,MAAM;AACd,WAAO,uBAAuB,QAAQ,WAAW;AAAA,EACnD,GAAG,CAAC,QAAQ,sBAAsB,CAAC;AAGnC,EAAAA,WAAU,MAAM;AACd,UAAM,sBAAsB,CAAC,SAAsB;AACjD,YAAM,UAAU,cAAc,IAAI,WAAW,IAAI,CAAC;AAClD,YAAM,cAAc,YAAY,OAAO;AAGvC,UAAI,gBAAgB,mBAAmB;AACrC,cAAMC,aAAY,IAAI,YAAY,EAAE,OAAO,kBAAkB,OAAO,CAAC;AACrE,YAAIA,eAAc,OAAQ;AAC1B,cAAMC,WAAU,kBAAkB,OAAO;AACzC,kBAAU,YAAYA,QAAO;AAC7B;AAAA,MACF;AAEA,UAAI,gBAAgB,aAAc;AAElC,YAAM,YAAY,IAAI,YAAY,EAAE,OAAO,kBAAkB,OAAO,CAAC;AACrE,UAAI,cAAc,OAAQ;AAE1B,YAAM,WAAW,YAAY,OAAO;AACpC,YAAM,UAAU,kBAAkB,OAAO;AAEzC,cAAQ,UAAU;AAAA,QAChB,KAAK,gBAAgB;AAEnB,gBAAM,UAAY,uBAAoB,KAAK,OAAO;AAClD,gBAAM,UAAU,cAAc;AAC9B,uBAAa,SAAS,YAAY;AAClC,6BAAmB,SAAS,IAAI,YAAY,EAAE,OAAO,MAAM,CAAC;AAC5D,uBAAa,SAAS,cAAc;AACpC,6BAAmB,SAAS,OAAO;AACnC,qBAAW,aAAa,OAAO,CAAC;AAChC,oBAAU,IAAI;AACd;AAAA,QACF;AAAA,QACA,KAAK,gBAAgB;AAEnB,UAAE,eAAY,KAAK,SAAS,QAAQ;AACpC,oBAAU,IAAI;AACd;AAAA,QACF;AAAA,QACA,KAAK,iBAAiB;AAEpB,UAAE,eAAY,KAAK,SAAS,QAAQ;AACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,gBAAgB,mBAAmB;AAAA,EAC5C,GAAG,CAAC,KAAK,WAAW,QAAQ,YAAY,eAAe,CAAC;AAGxD,EAAAF,WAAU,MAAM;AACd,QAAI,CAAC,MAAO;AAEZ,UAAM,wBAAwB,CAAC,EAAE,OAAO,SAAS,QAAQ,MAAiE;AACxH,YAAM,iBAAiB,MAAM,OAAO,OAAO,EAAE,OAAO,OAAO;AAC3D,UAAI,eAAe,WAAW,EAAG;AAEjC,YAAM,UAAU,cAAc;AAC9B,mBAAa,SAAS,iBAAiB;AACvC,yBAAmB,SAAS,IAAI,YAAY,EAAE,OAAO,MAAM,CAAC;AAC5D,yBAAmB,SAAS,UAAU,aAAa,cAAc,CAAC;AAClE,iBAAW,aAAa,OAAO,CAAC;AAAA,IAClC;AAEA,cAAU,GAAG,UAAU,qBAAqB;AAC5C,WAAO,MAAM;AAAE,gBAAU,IAAI,UAAU,qBAAqB;AAAA,IAAE;AAAA,EAChE,GAAG,CAAC,WAAW,QAAQ,YAAY,KAAK,CAAC;AAGzC,EAAAA,WAAU,MAAM;AACd,QAAI,CAAC,OAAO;AAEV,cAAQ,IAAI,+BAA+B,MAAM;AACjD,gBAAU,KAAK;AACf,kBAAY,KAAK;AACjB;AAAA,IACF;AAEA,YAAQ,IAAI,kBAAkB,MAAM;AACpC,gBAAY,EAAE,MAAM,IAAI,UAAU,SAAS,EAAE,YAAY,UAAU,UAAU,EAAE,CAAC;AAEhF,WAAO,MAAM;AAEX,gBAAU,cAAc,IAAI;AAC5B,cAAQ,IAAI,kBAAkB,MAAM;AACpC,kBAAY,EAAE,MAAM,IAAI,WAAW,SAAS,EAAE,YAAY,UAAU,UAAU,EAAE,CAAC;AAAA,IACnF;AAAA,EACF,GAAG,CAAC,OAAO,YAAY,UAAU,WAAW,aAAa,QAAQ,SAAS,CAAC;AAG3E,EAAAA,WAAU,MAAM;AACd,UAAM,eAAe,CAAC,QAAoB,WAAoB;AAC5D,qBAAe,OAAK,IAAI,CAAC;AAGzB,UAAI,WAAW,YAAY,CAAC,YAAY,QAAS;AAEjD,YAAM,UAAU,cAAc;AAC9B,mBAAa,SAAS,YAAY;AAClC,yBAAmB,SAAS,IAAI,YAAY,EAAE,OAAO,MAAM,CAAC;AAC5D,mBAAa,SAAS,eAAe;AACrC,yBAAmB,SAAS,MAAM;AAClC,iBAAW,aAAa,OAAO,CAAC;AAAA,IAClC;AAEA,QAAI,GAAG,UAAU,YAAY;AAC7B,WAAO,MAAM;AAAE,UAAI,IAAI,UAAU,YAAY;AAAA,IAAE;AAAA,EACjD,GAAG,CAAC,KAAK,QAAQ,UAAU,CAAC;AAG5B,SAAO,EAAE,KAAK,WAAW,QAAQ,SAAS,QAAQ,UAAU,YAAY;AAC1E;AAoCO,SAAS,WACd,YACA,UACA,WACkB;AAClB,QAAM,EAAE,KAAK,QAAQ,UAAU,YAAY,IAAI,YAAY,YAAY,UAAU,SAAS;AAC1F,QAAM,CAAC,MAAM,YAAY,IAAIF,UAAS,EAAE;AACxC,QAAM,WAAWC,QAAsB,IAAI;AAC3C,QAAM,mBAAmBA,QAAO,KAAK;AAGrC,EAAAC,WAAU,MAAM;AACd,aAAS,UAAU,IAAI,QAAQ,SAAS;AAAA,EAC1C,GAAG,CAAC,KAAK,SAAS,CAAC;AAGnB,EAAAA,WAAU,MAAM;AACd,QAAI,SAAS,WAAW,UAAU,CAAC,iBAAiB,SAAS;AAC3D,mBAAa,SAAS,QAAQ,SAAS,CAAC;AAAA,IAC1C;AACA,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,QAAQ,WAAW,CAAC;AAGxB,QAAM,UAAUG,aAAY,CAAC,UAAkB;AAC7C,iBAAa,KAAK;AAElB,QAAI,SAAS,WAAW,UAAU;AAChC,uBAAiB,UAAU;AAC3B,UAAI,SAAS,MAAM;AACjB,cAAM,QAAQ,SAAS;AACvB,cAAM,OAAO,GAAG,MAAM,MAAM;AAC5B,cAAM,OAAO,GAAG,KAAK;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,KAAK,QAAQ,CAAC;AAElB,SAAO,EAAE,MAAM,SAAS,QAAQ,SAAS;AAC3C;;;AC7QA,SAAS,WAAAC,UAAS,eAAAC,oBAAmB;AAyB9B,SAAS,gBAAgB;AAC9B,QAAM,EAAE,OAAO,YAAY,IAAI,SAAS;AAGxC,QAAM,UAAUC,SAAQ,MAAM;AAC5B,UAAM,MAAM,oBAAI,IAAsB;AACtC,eAAW,QAAQ,OAAO;AACxB,UAAI,IAAI,KAAK,IAAI;AAAA,QACf,IAAI,KAAK;AAAA,QACT,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,MACb,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT,GAAG,CAAC,KAAK,CAAC;AAKV,QAAM,UAAUC,aAAY,CAAC,WAAoC;AAC/D,WAAO,QAAQ,IAAI,MAAM,KAAK;AAAA,EAChC,GAAG,CAAC,OAAO,CAAC;AAKZ,QAAM,WAAWA,aAAY,CAAC,WAAkC;AAC9D,WAAO,QAAQ,IAAI,MAAM,GAAG,SAAS;AAAA,EACvC,GAAG,CAAC,OAAO,CAAC;AAKZ,QAAM,UAAUA,aAAY,CAAC,WAAkC;AAC7D,WAAO,QAAQ,IAAI,MAAM,GAAG,QAAQ;AAAA,EACtC,GAAG,CAAC,OAAO,CAAC;AAEZ,SAAO;AAAA;AAAA,IAEL;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AACF;;;AC7EA,SAAS,aAAAC,YAAW,eAAAC,cAAa,YAAAC,iBAAgB;AAMjD,IAAM,qBAAqB,IAAI,KAAK;AACpC,IAAM,wBAAwB,KAAK;AACnC,IAAM,mBAAmB,KAAK;AAMvB,SAAS,YAAY,MAA2B;AACrD,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,QAAM,EAAE,aAAa,MAAM,IAAI,iBAAiB;AAChD,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAS,CAAC;AAElC,QAAM,YAAY,MAAM,aAAa;AAGrC,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,QAAQ,CAAC,MAAO;AACrB,UAAM,WAAW,YAAY,MAAM;AACjC,kBAAY,EAAE,MAAM,IAAI,aAAa,SAAS,CAAC,EAAE,CAAC;AAAA,IACpD,GAAG,qBAAqB;AACxB,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,MAAM,OAAO,WAAW,CAAC;AAG7B,EAAAA,WAAU,MAAM;AACd,UAAM,WAAW,YAAY,MAAM;AACjC,cAAQ,CAAC,MAAM,IAAI,CAAC;AAAA,IACtB,GAAG,gBAAgB;AACnB,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,QAAM,WAAWC;AAAA,IACf,CAAC,WAA4B;AAE3B,WAAK;AACL,YAAM,IAAI,MAAM,KAAK,CAACC,OAAMA,GAAE,OAAO,MAAM;AAC3C,UAAI,CAAC,GAAG,WAAY,QAAO;AAC3B,aAAO,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,UAAU,EAAE,QAAQ,IAAI;AAAA,IACzD;AAAA,IACA,CAAC,OAAO,WAAW,IAAI;AAAA,EACzB;AAEA,QAAM,cAAcD;AAAA,IAClB,CAAC,WAAkC;AACjC,YAAM,IAAI,MAAM,KAAK,CAACC,OAAMA,GAAE,OAAO,MAAM;AAC3C,aAAO,GAAG,cAAc;AAAA,IAC1B;AAAA,IACA,CAAC,KAAK;AAAA,EACR;AAEA,SAAO,EAAE,UAAU,aAAa,MAAM;AACxC;;;ACxDA,SAAS,YAAAC,WAAU,aAAAC,aAAW,eAAAC,cAAa,UAAAC,SAAQ,WAAAC,gBAAe;AAClE,YAAYC,QAAO;AA8CZ,SAAS,WAAW,OAAe,WAAqC;AAC7E,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,KAAK;AAC9C,QAAM,CAAC,MAAM,YAAY,IAAIA,UAAS,EAAE;AACxC,QAAM,CAAC,EAAE,cAAc,IAAIA,UAAS,CAAC;AAErC,QAAM,SAASC,QAAqB,IAAI;AACxC,MAAI,CAAC,OAAO,QAAS,QAAO,UAAU,IAAM,OAAI;AAChD,QAAM,MAAM,OAAO;AAEnB,QAAM,eAAeA,QAAyB,IAAI;AAClD,MAAI,CAAC,aAAa,QAAS,cAAa,UAAU,IAAI,UAAU,GAAG;AACnE,QAAM,YAAY,aAAa;AAE/B,QAAM,QAAQA,QAAyB,IAAI;AAC3C,QAAM,aAAaA,QAAO,KAAK;AAC/B,QAAM,6BAA6BA,QAAO,KAAK;AAE/C,QAAM,QAAQC,SAAQ,MAAM,IAAI,QAAQ,SAAS,GAAG,CAAC,KAAK,SAAS,CAAC;AAGpE,EAAAC,YAAU,MAAM;AACd,UAAM,WAAW,MAAM;AACrB,UAAI,WAAW,QAAS;AACxB,mBAAa,MAAM,SAAS,CAAC;AAAA,IAC/B;AACA,UAAM,QAAQ,QAAQ;AACtB,WAAO,MAAM,MAAM,UAAU,QAAQ;AAAA,EACvC,GAAG,CAAC,KAAK,CAAC;AAGV,EAAAA,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,WAAW,mBAAmB,KAAK,CAAC,IAAI,OAAO;AACnE,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,YAAM,cAAc,OAAO,KAAK,EAAE;AAClC,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,SAAG,aAAa;AAChB,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM;AAChB,cAAM,aAAa,OAAO,KAAK,EAAE;AACjC,kBAAU,KAAK;AAAA,MACjB;AAEA,SAAG,YAAY,CAAC,UAAU;AACxB,YAAI,OAAO,MAAM,SAAS,UAAU;AAClC,cAAI;AACF,kBAAM,MAAM,KAAK,MAAM,MAAM,IAAI;AACjC,gBAAI,IAAI,SAAS,UAAU,OAAO,IAAI,aAAa,UAAW,aAAY,IAAI,QAAQ;AAAA,UACxF,QAAQ;AAAA,UAER;AACA;AAAA,QACF;AAEA,cAAM,OAAO,IAAI,WAAW,MAAM,IAAmB;AACrD,cAAM,UAAU,cAAc,IAAI;AAClC,cAAM,cAAc,YAAY,OAAO;AAEvC,YAAI,gBAAgB,UAAU;AAC5B,gBAAM,WAAW,YAAY,OAAO;AACpC,gBAAM,UAAU,kBAAkB,OAAO;AAEzC,kBAAQ,UAAU;AAAA,YAChB,KAAK,gBAAgB;AACnB,oBAAM,OAAS,uBAAoB,KAAK,OAAO;AAC/C,oBAAM,MAAM,cAAc;AAC1B,2BAAa,KAAK,QAAQ;AAC1B,2BAAa,KAAK,cAAc;AAChC,iCAAmB,KAAK,IAAI;AAC5B,kBAAI,KAAK,aAAa,GAAG,EAAE,MAAM;AACjC,wBAAU,IAAI;AACd;AAAA,YACF;AAAA,YACA,KAAK,gBAAgB;AACnB,cAAE,eAAY,KAAK,SAAS,QAAQ;AACpC,2BAAa,MAAM,SAAS,CAAC;AAC7B,wBAAU,IAAI;AACd;AAAA,YACF;AAAA,YACA,KAAK,iBAAiB;AACpB,cAAE,eAAY,KAAK,SAAS,QAAQ;AACpC,6BAAe,CAAC,MAAM,IAAI,CAAC;AAC3B;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAEA,YAAI,gBAAgB,eAAe;AACjC,qCAA2B,UAAU;AACrC,cAAI;AACF,mCAAuB,WAAW,IAAI;AAAA,UACxC,UAAE;AACA,uCAA2B,UAAU;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,gBAAgB,OAAO,KAAK,EAAE;AACpC,cAAM,UAAU;AAChB,kBAAU,KAAK;AACf,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,YAAM,WAAW,OAAO,KAAK,EAAE;AAC/B,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,UAAI,IAAI;AACN,WAAG,UAAU;AACb,WAAG,YAAY;AACf,WAAG,UAAU;AACb,WAAG,MAAM;AAAA,MACX;AACA,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,KAAK,WAAW,OAAO,KAAK,CAAC;AAGjC,EAAAA,YAAU,MAAM;AACd,UAAM,UAAU,CAAC,EAAE,OAAO,SAAS,QAAQ,MAAiE;AAC1G,UAAI,2BAA2B,QAAS;AACxC,YAAM,iBAAiB,MAAM,OAAO,OAAO,EAAE,OAAO,OAAO;AAC3D,UAAI,eAAe,WAAW,EAAG;AAEjC,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAE7C,SAAG,KAAK,uBAAuB,WAAW,cAAc,EAAE,MAAM;AAAA,IAClE;AAEA,cAAU,GAAG,UAAU,OAAO;AAC9B,WAAO,MAAM;AACX,gBAAU,IAAI,UAAU,OAAO;AAC/B,gBAAU,cAAc,IAAI;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAGd,EAAAA,YAAU,MAAM;AACd,UAAM,UAAU,CAAC,QAAoB,WAAoB;AACvD,UAAI,WAAW,SAAU;AACzB,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAE7C,YAAM,MAAM,cAAc;AAC1B,mBAAa,KAAK,QAAQ;AAC1B,mBAAa,KAAK,eAAe;AACjC,yBAAmB,KAAK,MAAM;AAC9B,SAAG,KAAK,aAAa,GAAG,EAAE,MAAM;AAAA,IAClC;AAEA,QAAI,GAAG,UAAU,OAAO;AACxB,WAAO,MAAM;AAAE,UAAI,IAAI,UAAU,OAAO;AAAA,IAAE;AAAA,EAC5C,GAAG,CAAC,GAAG,CAAC;AAGR,QAAM,UAAUC,aAAY,CAAC,UAAkB;AAC7C,iBAAa,KAAK;AAClB,QAAI,CAAC,SAAU;AAEf,eAAW,UAAU;AACrB,QAAI,SAAS,MAAM;AACjB,YAAM,OAAO,GAAG,MAAM,MAAM;AAC5B,YAAM,OAAO,GAAG,KAAK;AAAA,IACvB,CAAC;AACD,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,KAAK,OAAO,QAAQ,CAAC;AAEzB,SAAO,EAAE,KAAK,WAAW,MAAM,SAAS,QAAQ,SAAS;AAC3D;;;ACxOA,SAAS,YAAAC,WAAU,aAAAC,aAAW,eAAAC,eAAa,UAAAC,eAAc;AAwClD,SAAS,YAAY,QAAmC;AAC7D,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAkC,CAAC,CAAC;AACtE,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,CAAC;AAClC,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAuB,CAAC,CAAC;AACvD,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,KAAK;AAC5C,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAChD,QAAM,QAAQC,QAAyB,IAAI;AAE3C,EAAAC,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,YAAY,mBAAmB,MAAM,CAAC,IAAI,OAAO;AACrE,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,YAAM,cAAc,QAAQ,MAAM,EAAE;AACpC,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM;AAChB,cAAM,aAAa,QAAQ,MAAM,EAAE;AACnC,qBAAa,IAAI;AAAA,MACnB;AAEA,SAAG,YAAY,CAAC,UAAU;AACxB,iBAAwB,MAAM,MAAM;AAAA,UAClC,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM;AACvB,yBAAa,EAAE,KAAgC;AAC/C,oBAAQ,EAAE,IAAI;AACd,uBAAW,EAAE,OAAuB;AACpC,uBAAW,EAAE,OAAO;AAAA,UACtB;AAAA,UACA,CAAC,IAAI,SAAS,GAAG,CAAC,MAAM;AACtB,yBAAa,EAAE,KAAgC;AAC/C,oBAAQ,EAAE,IAAI;AAAA,UAChB;AAAA,UACA,CAAC,IAAI,gBAAgB,GAAG,CAAC,MAAM;AAC7B,kBAAM,SAAS,EAAE;AACjB,uBAAW,CAAC,SAAS,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO,MAAM,GAAG,MAAM,CAAC;AAAA,UAClF;AAAA,UACA,CAAC,IAAI,iBAAiB,GAAG,CAAC,MAAM;AAC9B,uBAAW,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;AAAA,UAChE;AAAA,UACA,CAAC,IAAI,iBAAiB,GAAG,CAAC,MAAM;AAC9B;AAAA,cAAW,CAAC,SACV,KAAK,IAAI,CAAC,MAAO,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,KAAK,IAAI,CAAE;AAAA,YACrE;AAAA,UACF;AAAA,UACA,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM;AACvB,uBAAW,IAAI;AACf,yBAAa,EAAE,KAAgC;AAC/C,oBAAQ,EAAE,IAAI;AAAA,UAChB;AAAA,UACA,CAAC,IAAI,QAAQ,GAAG,CAAC,MAAM;AACrB,uBAAW,KAAK;AAChB,yBAAa,EAAE,KAAgC;AAAA,UACjD;AAAA,QACF,CAAC;AAAA,MACH;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,gBAAgB,QAAQ,MAAM,EAAE;AACtC,cAAM,UAAU;AAChB,qBAAa,KAAK;AAClB,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,YAAM,WAAW,QAAQ,MAAM,EAAE;AACjC,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,UAAI,IAAI;AACN,WAAG,UAAU;AACb,WAAG,YAAY;AACf,WAAG,UAAU;AACb,WAAG,MAAM;AAAA,MACX;AACA,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAYC,cAAY,CAAC,QAAgB,OAAgC,CAAC,MAAM;AACpF,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,OAAG,KAAK,OAAO,YAAY,UAAU,QAAQ,IAAI,CAAC,CAAC;AAAA,EACrD,GAAG,CAAC,CAAC;AAEL,QAAM,WAAWA,cAAY,MAAM;AACjC,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,OAAG,KAAK,OAAO,YAAY,gBAAgB,CAAC,CAAC;AAAA,EAC/C,GAAG,CAAC,CAAC;AAEL,QAAM,YAAYA,cAAY,MAAM;AAClC,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,OAAG,KAAK,OAAO,YAAY,UAAU,CAAC,CAAC;AAAA,EACzC,GAAG,CAAC,CAAC;AAEL,QAAM,UAAUA,cAAY,MAAM;AAChC,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,OAAG,KAAK,OAAO,YAAY,QAAQ,CAAC,CAAC;AAAA,EACvC,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,OAAO,WAAW,MAAM,SAAS,SAAS,WAAW,WAAW,UAAU,WAAW,QAAQ;AACxG;;;ACrKA,SAAS,YAAAC,WAAU,aAAAC,aAAW,eAAAC,eAAa,UAAAC,gBAAc;AA2DlD,SAAS,UAAU,QAAiC;AACzD,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAA8B,CAAC,CAAC;AAC5D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAA2B,CAAC,CAAC;AAC/D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAChD,QAAM,QAAQC,SAAyB,IAAI;AAE3C,EAAAC,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,cAAc,mBAAmB,MAAM,CAAC,IAAI,OAAO;AACvE,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,YAAM,cAAc,UAAU,MAAM,EAAE;AACtC,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM;AAChB,cAAM,aAAa,UAAU,MAAM,EAAE;AACrC,qBAAa,IAAI;AAAA,MACnB;AAEA,SAAG,YAAY,CAAC,UAAU;AAOxB,iBAAwB,MAAM,MAAM;AAAA,UAClC,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B,sBAAU,EAAE,MAA6B;AACzC,yBAAa,EAAE,SAA6B;AAAA,UAC9C;AAAA,UACA,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM;AACvB,kBAAM,QAAQ,EAAE;AAChB,sBAAU,CAAC,SAAS,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,GAAG,KAAK,CAAC;AAAA,UACvE;AAAA,UACA,CAAC,IAAI,WAAW,GAAG,CAAC,MAAM;AACxB;AAAA,cAAU,CAAC,SACT,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,IAAI,CAAE;AAAA,YACrE;AAAA,UACF;AAAA,UACA,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B;AAAA,cAAU,CAAC,SACT,KAAK,IAAI,CAAC,MAAM;AACd,oBAAI,EAAE,OAAO,EAAE,QAAS,QAAO;AAC/B,sBAAM,UAAU,EAAE,GAAG,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO;AACzD,oBAAI,EAAE,MAAM,OAAW,SAAQ,IAAI,EAAE;AACrC,oBAAI,EAAE,MAAM,OAAW,SAAQ,IAAI,EAAE;AACrC,uBAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B,sBAAU,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;AAAA,UAC5D;AAAA,UACA,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B;AAAA,cAAU,CAAC,SACT,KAAK;AAAA,gBAAI,CAAC,MACR,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAAA,cACrE;AAAA,YACF;AAAA,UACF;AAAA,UACA,CAAC,IAAI,eAAe,GAAG,CAAC,MAAM;AAG5B,gBAAI,aAAa,GAAG;AAClB,oBAAM,UAAU;AAChB,2BAAa,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,MAAM,CAAC;AAAA,YACxE,OAAO;AACL,oBAAM,WAAW,EAAE;AACnB,2BAAa,CAAC,SAAS;AAAA,gBACrB,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,MAAM;AAAA,gBAClD;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,gBAAgB,UAAU,MAAM,EAAE;AACxC,cAAM,UAAU;AAChB,qBAAa,KAAK;AAClB,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,YAAM,WAAW,UAAU,MAAM,EAAE;AACnC,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,UAAI,IAAI;AACN,WAAG,UAAU;AACb,WAAG,YAAY;AACf,WAAG,UAAU;AACb,WAAG,MAAM;AAAA,MACX;AACA,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAKX,QAAM,YAAYC;AAAA,IAChB,CAA+C,YAAe;AAC5D,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,SAAG,KAAK,OAAO,OAAO,CAAC;AAAA,IACzB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,WAAWA;AAAA,IACf,CAAC,UAAsC,UAAU,YAAY,UAAU,KAAK,CAAC;AAAA,IAC7E,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,YAAYA;AAAA,IAChB,CAAC,SAAiB,GAAW,MAC3B,UAAU,YAAY,WAAW,SAAS,GAAG,CAAC,CAAC;AAAA,IACjD,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,cAAcA;AAAA,IAClB,CAAC,SAAiB,OAAe,QAAgB,GAAY,MAC3D,UAAU,YAAY,aAAa,SAAS,OAAO,QAAQ,GAAG,CAAC,CAAC;AAAA,IAClE,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,cAAcA;AAAA,IAClB,CAAC,YAAoB,UAAU,YAAY,aAAa,OAAO,CAAC;AAAA,IAChE,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,cAAcA;AAAA,IAClB,CAAC,SAAiB,UAChB,UAAU,YAAY,aAAa,SAAS,KAAK,CAAC;AAAA,IACpD,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,cAAcA;AAAA,IAClB,CAAC,aACC,UAAU,YAAY,eAAe,QAAQ,CAAC;AAAA,IAChD,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,OAAOA,cAAY,MAAM,UAAU,YAAY,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;AAC/E,QAAM,OAAOA,cAAY,MAAM,UAAU,YAAY,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC;AAE/E,SAAO,EAAE,QAAQ,WAAW,WAAW,UAAU,WAAW,aAAa,aAAa,aAAa,aAAa,MAAM,KAAK;AAC7H;;;AC/NA,SAAS,YAAAC,YAAU,aAAAC,aAAW,eAAAC,eAAa,UAAAC,gBAAc;AA4ClD,SAAS,eAAe,QAAsC;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAA0B,CAAC,CAAC;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIA,WAA6B,CAAC,CAAC;AAC7D,QAAM,CAAC,WAAW,YAAY,IAAIA,WAAS,KAAK;AAChD,QAAM,QAAQC,SAAyB,IAAI;AAE3C,EAAAC,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,YAAY,mBAAmB,MAAM,CAAC,IAAI,OAAO;AACrE,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM,aAAa,IAAI;AAEnC,SAAG,YAAY,CAAC,UAAU;AACxB,iBAAwB,MAAM,MAAM;AAAA,UAClC,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM;AACvB,qBAAS,EAAE,KAAwB;AAAA,UACrC;AAAA,UACA,CAAC,IAAI,YAAY,GAAG,CAAC,MAAM;AACzB,uBAAW,EAAE,OAA6B;AAAA,UAC5C;AAAA,UACA,CAAC,IAAI,WAAW,GAAG,CAAC,MAAM;AACxB,qBAAS,EAAE,KAAwB;AACnC,uBAAW,EAAE,aAAmC;AAAA,UAClD;AAAA,QACF,CAAC;AAAA,MACH;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,UAAU;AAChB,qBAAa,KAAK;AAClB,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,UAAI,MAAM;AACV,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAYC;AAAA,IAChB,CAA+C,YAAe;AAC5D,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,SAAG,KAAK,OAAO,OAAO,CAAC;AAAA,IACzB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,UAAUA;AAAA,IACd,CAAC,aAAqB,UAAU,YAAY,YAAY,QAAQ,CAAC;AAAA,IACjE,CAAC,SAAS;AAAA,EACZ;AACA,QAAM,QAAQA;AAAA,IACZ,CAAC,aAAqB,UAAU,YAAY,UAAU,QAAQ,CAAC;AAAA,IAC/D,CAAC,SAAS;AAAA,EACZ;AACA,QAAM,SAASA;AAAA,IACb,CAAC,aAAqB,UAAU,YAAY,WAAW,QAAQ,CAAC;AAAA,IAChE,CAAC,SAAS;AAAA,EACZ;AAEA,SAAO,EAAE,OAAO,SAAS,WAAW,SAAS,OAAO,OAAO;AAC7D;;;ACjHA,SAAS,YAAAC,YAAU,aAAAC,aAAW,eAAAC,eAAa,UAAAC,gBAAc;AAWzD,IAAM,qBAAqB;AAgEpB,SAAS,QACd,QACqB;AACrB,QAAM,CAAC,MAAM,OAAO,IAAIC,WAA0B,CAAC,CAAC;AACpD,QAAM,CAAC,WAAW,YAAY,IAAIA,WAAS,KAAK;AAChD,QAAM,QAAQC,SAAyB,IAAI;AAM3C,QAAM,oBAAoBA,SAAoC,oBAAI,IAAI,CAAC;AAEvE,EAAAC,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,SAAS,CAAC,SAAwB;AACtC,cAAQ,CAAC,SAAS;AAChB,cAAM,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE;AAClD,YAAI,QAAQ,GAAI,QAAO,CAAC,MAAM,GAAG,IAAI;AACrC,cAAM,OAAO,KAAK,MAAM;AACxB,aAAK,GAAG,IAAI;AACZ,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,UAAM,mBAAmB,CAAC,QAAe;AACvC,iBAAW,CAAC,IAAI,OAAO,KAAK,kBAAkB,QAAQ,QAAQ,GAAG;AAC/D,qBAAa,QAAQ,KAAK;AAC1B,gBAAQ,OAAO,GAAG;AAClB,0BAAkB,QAAQ,OAAO,EAAE;AAAA,MACrC;AAAA,IACF;AAEA,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,YAAY,mBAAmB,MAAM,CAAC,IAAI,OAAO;AACrE,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM,aAAa,IAAI;AAEnC,SAAG,YAAY,CAAC,UAAU;AACxB,iBAAwB,MAAM,MAAM;AAAA,UAClC,CAAC,IAAI,UAAU,GAAG,CAAC,MAAM;AACvB,gBAAI,EAAE,SAAS,cAAc,MAAM,QAAQ,EAAE,IAAI,GAAG;AAClD,sBAAQ,EAAE,IAAuB;AACjC;AAAA,YACF;AACA,kBAAM,MAAM,EAAE;AACd,gBAAI,CAAC,IAAK;AACV,mBAAO,GAAG;AAEV,gBAAI,EAAE,SAAS,cAAc,OAAO,EAAE,cAAc,UAAU;AAC5D,oBAAM,UAAU,kBAAkB,QAAQ,IAAI,EAAE,SAAS;AACzD,kBAAI,SAAS;AACX,6BAAa,QAAQ,KAAK;AAC1B,kCAAkB,QAAQ,OAAO,EAAE,SAAS;AAC5C,wBAAQ,QAAQ,IAAI,EAAE;AAAA,cACxB;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,UAAU;AAChB,qBAAa,KAAK;AAClB,yBAAiB,IAAI,MAAM,0BAA0B,CAAC;AACtD,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,uBAAiB,IAAI,MAAM,mBAAmB,CAAC;AAC/C,UAAI,MAAM;AACV,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,UAAUC;AAAA,IACd,CAAC,MAAc,SAAa,YAAuC;AACjE,aAAO,IAAI,QAAgB,CAAC,SAAS,WAAW;AAC9C,cAAM,KAAK,MAAM;AACjB,YAAI,CAAC,MAAM,GAAG,eAAe,UAAU,MAAM;AAC3C,iBAAO,IAAI,MAAM,iCAAiC,CAAC;AACnD;AAAA,QACF;AACA,cAAM,YAAY,OAAO,WAAW;AACpC,cAAM,QAAQ,WAAW,MAAM;AAC7B,4BAAkB,QAAQ,OAAO,SAAS;AAC1C;AAAA,YACE,IAAI;AAAA,cACF,mDAAmD,kBAAkB;AAAA,YACvE;AAAA,UACF;AAAA,QACF,GAAG,kBAAkB;AACrB,0BAAkB,QAAQ,IAAI,WAAW,EAAE,SAAS,QAAQ,MAAM,CAAC;AAKnE,YAAI;AACF,aAAG;AAAA,YACD,OAAO,YAAY,WAAW,WAAW,MAAM,SAAS,SAAS,WAAW,CAAC;AAAA,UAC/E;AAAA,QACF,SAAS,GAAG;AACV,uBAAa,KAAK;AAClB,4BAAkB,QAAQ,OAAO,SAAS;AAC1C,iBAAO,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,YAAYA;AAAA,IAChB,CAA+C,YAAqB;AAClE,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,SAAG,KAAK,OAAO,OAAO,CAAC;AAAA,IACzB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,UAAkB,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;AAAA,IAClD,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,UAAkB,UAAU,YAAY,UAAU,KAAK,CAAC;AAAA,IACzD,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,QAAQA;AAAA,IACZ,CAAC,UAAkB,UAAU,YAAY,SAAS,KAAK,CAAC;AAAA,IACxD,CAAC,SAAS;AAAA,EACZ;AAEA,SAAO,EAAE,MAAM,WAAW,SAAS,QAAQ,QAAQ,MAAM;AAC3D;;;ACrOA,SAAS,YAAAC,YAAU,aAAAC,aAAW,eAAAC,eAAa,UAAAC,gBAAc;AAqClD,SAAS,gBAAgB,SAAwC;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAA+B,CAAC,CAAC;AAC3D,QAAM,CAAC,WAAW,YAAY,IAAIA,WAAS,KAAK;AAChD,QAAM,QAAQC,SAAyB,IAAI;AAE3C,EAAAC,YAAU,MAAM;AACd,QAAI,KAAuB;AAC3B,QAAI,iBAAuD;AAC3D,QAAI,QAAQ;AAEZ,UAAM,UAAU,YAAY;AAC1B,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,MAAM,aAAa;AACjC,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,UAAU,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI;AACpD,YAAM,MAAM,IAAI,IAAI,gBAAgB,mBAAmB,OAAO,CAAC,IAAI,OAAO;AAC1E,UAAI,MAAO,KAAI,aAAa,IAAI,SAAS,KAAK;AAE9C,YAAM,cAAc,YAAY,OAAO,EAAE;AACzC,WAAK,IAAI,UAAU,IAAI,SAAS,CAAC;AACjC,YAAM,UAAU;AAEhB,SAAG,SAAS,MAAM;AAChB,cAAM,aAAa,YAAY,OAAO,EAAE;AACxC,qBAAa,IAAI;AAAA,MACnB;AAEA,SAAG,YAAY,CAAC,UAAU;AACxB,iBAAwB,MAAM,MAAM;AAAA,UAClC,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B,qBAAS,EAAE,KAA6B;AAAA,UAC1C;AAAA,UACA,CAAC,IAAI,aAAa,GAAG,CAAC,MAAM;AAC1B,kBAAM,OAAO,EAAE;AACf,qBAAS,CAAC,SAAS,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,GAAG,IAAI,CAAC;AAAA,UAC5E;AAAA,UACA,CAAC,IAAI,cAAc,GAAG,CAAC,MAAM;AAC3B,qBAAS,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;AAAA,UAC9D;AAAA,UACA,CAAC,IAAI,eAAe,GAAG,CAAC,MAAM;AAC5B;AAAA,cAAS,CAAC,SACR,KAAK;AAAA,gBAAI,CAAC,MACR,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAAA,cACxE;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,SAAG,UAAU,MAAM;AACjB,cAAM,gBAAgB,YAAY,OAAO,EAAE;AAC3C,cAAM,UAAU;AAChB,qBAAa,KAAK;AAClB,YAAI,MAAO,kBAAiB,WAAW,SAAS,GAAI;AAAA,MACtD;AAEA,SAAG,UAAU,MAAM,IAAI,MAAM;AAAA,IAC/B;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,YAAM,WAAW,YAAY,OAAO,EAAE;AACtC,cAAQ;AACR,UAAI,eAAgB,cAAa,cAAc;AAC/C,UAAI,IAAI;AACN,WAAG,UAAU;AACb,WAAG,YAAY;AACf,WAAG,UAAU;AACb,WAAG,MAAM;AAAA,MACX;AACA,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,cAAcC,cAAY,CAAC,UAAmC;AAClE,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,GAAG,eAAe,UAAU,KAAM;AAC7C,OAAG,KAAK,OAAO,YAAY,eAAe,KAAK,CAAC,CAAC;AAAA,EACnD,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,OAAO,WAAW,YAAY;AACzC;;;AChIO,SAAS,mBAAmB,aAAuC;AACxE,MAAI,gBAAgB,QAAS,QAAO;AACpC,MAAI,gBAAgB,QAAS,QAAO;AACpC,SAAO;AACT;;;ACFA,SAAS,eAAAC,eAAa,YAAAC,YAAU,WAAAC,iBAAe;AA2F/C,SAAS,YAAY,WAA2E;AAC9F,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO,EAAE,KAAK,WAAW,MAAM,OAAU;AAAA,EAC3C;AACA,SAAO,EAAE,KAAK,UAAU,KAAK,MAAM,UAAU,aAAa;AAC5D;AAMO,SAAS,WAAW,SAAqC;AAC9D,QAAM,CAAC,aAAa,cAAc,IAAIC,WAAS,KAAK;AAGpD,QAAM,cAAcC,UAAQ,MAAM;AAChC,UAAM,SAAS,IAAI,gBAAgB;AACnC,WAAO,IAAI,SAAS,MAAM;AAC1B,WAAO,OAAO,SAAS;AAAA,EACzB,GAAG,CAAC,CAAC;AAGL,QAAM,cAAcC,cAAY,YAA6C;AAC3E,UAAM,QAAQ,MAAM,aAAa;AACjC,QAAI,OAAO;AACT,aAAO,EAAE,eAAe,UAAU,KAAK,GAAG;AAAA,IAC5C;AACA,WAAO,CAAC;AAAA,EACV,GAAG,CAAC,CAAC;AAEL,QAAM,SAASA,cAAY,OAAO,MAAmB,SAA2C;AAC9F,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,YAAY;AAClC,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,OAAO,QAAQ,IAAI;AAC5B,UAAI,KAAM,UAAS,OAAO,QAAQ,IAAI;AAEtC,YAAM,WAAW,MAAM,MAAM,qBAAqB,WAAW,IAAI;AAAA,QAC/D,QAAQ;AAAA,QACR;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AACD,aAAO,MAAM,SAAS,KAAK;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,gBAAgB;AAAA,IACvF,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,eAAeA,cAAY,OAAO,YAAoB,MAAc,aAA+C;AACvH,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,UAAU,MAAM,YAAY;AAClC,YAAM,WAAW,MAAM,MAAM,qBAAqB,WAAW,IAAI;AAAA,QAC/D,QAAQ;AAAA,QACR,SAAS,EAAE,GAAG,SAAS,gBAAgB,mBAAmB;AAAA,QAC1D,MAAM,KAAK,UAAU,EAAE,MAAM,YAAY,MAAM,SAAS,CAAC;AAAA,MAC3D,CAAC;AACD,aAAO,MAAM,SAAS,KAAK;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,gBAAgB;AAAA,IACvF,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,aAAaA,cAAY,OAAO,cAAkF;AACtH,UAAM,EAAE,IAAI,IAAI,YAAY,SAAS;AACrC,QAAI;AACF,YAAM,UAAU,MAAM,YAAY;AAClC,YAAM,WAAW,MAAM,MAAM,cAAc,GAAG,IAAI,WAAW,IAAI,EAAE,QAAQ,UAAU,QAAQ,CAAC;AAC9F,aAAO,MAAM,SAAS,KAAK;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,gBAAgB;AAAA,IACvF;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,OAAOA,cAAY,OAAO,WAA2C;AACzE,QAAI;AACF,YAAM,UAAU,MAAM,YAAY;AAClC,YAAM,SAAS,IAAI,gBAAgB,WAAW;AAC9C,UAAI,OAAQ,QAAO,IAAI,UAAU,MAAM;AACvC,YAAM,WAAW,MAAM,MAAM,cAAc,OAAO,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC;AAC3E,YAAM,SAAS,MAAM,SAAS,KAAK;AACnC,aAAO,OAAO,SAAS,CAAC;AAAA,IAC1B,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,eAAeA,cAAY,OAAO,WAAgC,aAAqE;AAC3I,UAAM,EAAE,KAAK,MAAM,SAAS,IAAI,YAAY,SAAS;AACrD,QAAI;AACF,YAAM,UAAU,MAAM,YAAY;AAClC,YAAM,WAAW,MAAM,MAAM,cAAc,GAAG,IAAI,WAAW,IAAI,EAAE,QAAQ,CAAC;AAE5E,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACnD,eAAO,EAAE,SAAS,OAAO,OAAO,MAAM,SAAS,oBAAoB,SAAS,MAAM,IAAI;AAAA,MACxF;AAGA,YAAM,cAAc,SAAS,QAAQ,IAAI,qBAAqB;AAC9D,YAAM,kBAAkB,aAAa,MAAM,kBAAkB,IAAI,CAAC;AAClE,YAAM,eAAe,IAAI,MAAM,GAAG,EAAE,IAAI,KAAK;AAC7C,YAAM,eAAe,YAAY,YAAY,mBAAmB;AAEhE,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,UAAU,IAAI,gBAAgB,IAAI;AAExC,YAAM,SAAS,SAAS,cAAc,GAAG;AACzC,aAAO,OAAO;AACd,aAAO,WAAW;AAClB,eAAS,KAAK,YAAY,MAAM;AAChC,aAAO,MAAM;AAGb,eAAS,KAAK,YAAY,MAAM;AAChC,UAAI,gBAAgB,OAAO;AAE3B,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB,SAAS,KAAK;AACZ,aAAO,EAAE,SAAS,OAAO,OAAO,eAAe,QAAQ,IAAI,UAAU,kBAAkB;AAAA,IACzF;AAAA,EACF,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,WAAWA,cAAY,OAAO,cAAsD;AACxF,UAAM,EAAE,IAAI,IAAI,YAAY,SAAS;AACrC,UAAM,UAAU,MAAM,YAAY;AAClC,UAAM,WAAW,MAAM,MAAM,cAAc,GAAG,IAAI,WAAW,IAAI,EAAE,QAAQ,CAAC;AAC5E,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,YAAM,IAAI,MAAM,wBAAwB,SAAS,MAAM,MAAM,IAAI,EAAE;AAAA,IACrE;AACA,WAAO;AAAA,EACT,GAAG,CAAC,aAAa,WAAW,CAAC;AAE7B,QAAM,SAASA,cAAY,CAAC,cAA2C;AACrE,UAAM,EAAE,IAAI,IAAI,YAAY,SAAS;AACrC,WAAO,cAAc,GAAG,IAAI,WAAW;AAAA,EACzC,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO,EAAE,QAAQ,cAAc,YAAY,cAAc,UAAU,MAAM,QAAQ,YAAY;AAC/F;;;ACjPA,IAAM,sBAAsB,CAAC,QAAQ;AAE9B,SAAS,YAAY,UAA2B;AACrD,SAAO,oBAAoB,KAAK,YAAU,SAAS,WAAW,MAAM,CAAC;AACvE;AAEO,SAAS,eAAe,OAAuB;AACpD,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,MAAI,QAAQ,OAAO,OAAO,KAAM,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC5E,SAAO,IAAI,SAAS,OAAO,OAAO,OAAO,QAAQ,CAAC,CAAC;AACrD;;;AClBO,IAAM,sBAAsB;AAAA,EACjC;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EACjC;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AAAA,EACjC;AAAA,EAAW;AAAA,EAAW;AAAA,EAAW;AACnC;AAEO,SAAS,aAAa,QAAgB,UAA6B,qBAA6B;AACrG,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAS,QAAQ,KAAK,OAAO,OAAO,WAAW,CAAC,IAAK;AAAA,EACvD;AACA,SAAO,QAAQ,KAAK,IAAI,IAAI,IAAI,QAAQ,MAAM;AAChD;;;ACbA,SAAS,eAAAC,eAAa,WAAAC,iBAAe;AAO9B,SAAS,YACd,WACA,SACA;AACA,QAAM,QAAQC,UAAQ,MAAM;AAC1B,QAAI,CAAC,UAAW,QAAO,EAAE,WAAW,WAAW;AAC/C,UAAM,IAA6B,EAAE,UAAU;AAC/C,QAAI,SAAS,oBAAoB,QAAW;AAC1C,QAAE,kBAAkB,QAAQ;AAAA,IAC9B;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,SAAS,eAAe,CAAC;AAExC,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,EAAE,SAAS,QAAQ,MAAM,IAAI,SAAkB,YAAY;AAAA,IAC/D;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,EAAE,QAAQ,KAAK,QAAQ,eAAe,IAAI,aAAsB,UAAU;AAEhF,QAAM,OAAOC;AAAA,IACX,CAAC,SAAiB,oBAA6B;AAC7C,UAAI,CAAC,aAAa,CAAC,KAAM;AACzB,YAAM,OAAgC,EAAE,WAAW,SAAS,UAAU,KAAK,IAAI,QAAQ,MAAM;AAC7F,UAAI,gBAAiB,MAAK,kBAAkB;AAC5C,aAAO,OAAO,IAA0B;AAAA,IAC1C;AAAA,IACA,CAAC,WAAW,MAAM;AAAA,EACpB;AAEA,QAAM,OAAOA;AAAA,IACX,CAAC,WAAmB,eAAuB;AACzC,UAAI,WAAW,EAAE,SAAS,YAAY,QAAQ,KAAK,CAAuB;AAAA,IAC5E;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAGA,QAAM,SAASA;AAAA,IACb,CAAC,cAAsB;AAAE,qBAAe,SAAS;AAAA,IAAE;AAAA,IACnD,CAAC,cAAc;AAAA,EACjB;AAOA,QAAM,aAAaA;AAAA,IACjB,CAAC,cAAsB;AACrB,UAAI,WAAW,EAAE,SAAS,KAAK,CAAuB;AAAA,IACxD;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAEA,SAAO,EAAE,UAAU,SAAkC,QAAQ,OAAO,MAAM,MAAM,QAAQ,WAAW;AACrG;;;AClEA,SAAS,eAAAC,qBAAmB;AAOrB,SAAS,cAAc;AAC5B,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,EAAE,SAAS,QAAQ,MAAM,IAAI,SAAkB,YAAY;AAAA,IAC/D,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,EAAE,QAAQ,gBAAgB,KAAK,OAAO,IAAI,aAAsB,UAAU;AAEhF,QAAM,SAASC;AAAA,IACb,CAAC,SAAwE;AACvE,aAAO,eAAe;AAAA,QACpB,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,aAAa,KAAK,eAAe;AAAA,QACjC,WAAW,MAAM,MAAM;AAAA,QACvB,UAAU;AAAA,MACZ,CAAuB;AAAA,IACzB;AAAA,IACA,CAAC,cAAc;AAAA,EACjB;AAEA,QAAM,UAAUA;AAAA,IACd,CAAC,cAAsB;AAAE,UAAI,WAAW,EAAE,UAAU,KAAK,CAAuB;AAAA,IAAE;AAAA,IAClF,CAAC,GAAG;AAAA,EACN;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,WAAmB,SAAyD;AAC3E,UAAI,WAAW,IAA0B;AAAA,IAC3C;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAEA,SAAO,EAAE,UAAU,SAAkC,QAAQ,OAAO,QAAQ,SAAS,QAAQ,OAAO;AACtG;;;AC1CA,SAAS,eAAAC,qBAAmB;AAQrB,SAAS,aAAa,WAA+B;AAC1D,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,EAAE,SAAS,QAAQ,MAAM,IAAI,SAAmB,aAAa;AAAA,IACjE,OAAO,YAAY,EAAE,UAAU,IAAI,EAAE,WAAW,WAAW;AAAA,EAC7D,CAAC;AAED,QAAM,EAAE,QAAQ,QAAQ,eAAe,IAAI,aAAuB,WAAW;AAE7E,QAAM,yBAAyBC;AAAA,IAC7B,CAAC,cAAyC;AACxC,YAAM,mBAAmB,QAAQ,OAAO,CAAC,MAAM,EAAE,KAAK,cAAc,SAAS;AAC7E,YAAM,UAAU,oBAAI,IAAsB;AAE1C,iBAAW,KAAK,kBAAkB;AAChC,YAAI,CAAC,QAAQ,IAAI,EAAE,KAAK,KAAK,EAAG,SAAQ,IAAI,EAAE,KAAK,OAAO,CAAC,CAAC;AAC5D,gBAAQ,IAAI,EAAE,KAAK,KAAK,EAAG,KAAK,EAAE,KAAK,MAAM;AAAA,MAC/C;AAEA,aAAO,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,OAAO,OAAO;AAAA,QAC9D;AAAA,QACA,OAAO,QAAQ;AAAA,QACf;AAAA,QACA,oBAAoB,OAAO,QAAQ,SAAS,KAAK,EAAE,IAAI;AAAA,MACzD,EAAE;AAAA,IACJ;AAAA,IACA,CAAC,SAAS,IAAI;AAAA,EAChB;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,WAAmB,UAAkB;AACpC,UAAI,CAAC,aAAa,CAAC,KAAM;AACzB,YAAM,WAAW,QAAQ;AAAA,QACvB,CAAC,MAAM,EAAE,KAAK,cAAc,aAAa,EAAE,KAAK,UAAU,SAAS,EAAE,KAAK,WAAW,KAAK;AAAA,MAC5F;AACA,UAAI,UAAU;AACZ,uBAAe,SAAS,QAAQ;AAAA,MAClC,OAAO;AACL,eAAO,EAAE,WAAW,WAAW,OAAO,QAAQ,KAAK,GAAG,CAAwB;AAAA,MAChF;AAAA,IACF;AAAA,IACA,CAAC,WAAW,MAAM,SAAS,QAAQ,cAAc;AAAA,EACnD;AAEA,SAAO,EAAE,WAAW,SAAmC,QAAQ,OAAO,wBAAwB,OAAO;AACvG;;;ACrDA,SAAS,eAAAC,qBAAmB;AAOrB,SAAS,kBAAkB,WAA+B;AAC/D,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,EAAE,SAAS,QAAQ,MAAM,IAAI,SAAwB,mBAAmB;AAAA,IAC5E,OAAO,YAAY,EAAE,UAAU,IAAI,EAAE,WAAW,WAAW;AAAA,EAC7D,CAAC;AAED,QAAM,EAAE,QAAQ,QAAQ,eAAe,IAAI,aAA4B,iBAAiB;AAExF,QAAM,OAAOC,cAAY,MAAM;AAC7B,QAAI,CAAC,aAAa,CAAC,KAAM;AACzB,UAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK,WAAW,KAAK,EAAE;AAC9D,QAAI,SAAU;AACd,WAAO,EAAE,WAAW,QAAQ,KAAK,IAAI,WAAU,oBAAI,KAAK,GAAE,YAAY,EAAE,CAA6B;AAAA,EACvG,GAAG,CAAC,WAAW,MAAM,SAAS,MAAM,CAAC;AAErC,QAAM,QAAQA,cAAY,MAAM;AAC9B,QAAI,CAAC,aAAa,CAAC,KAAM;AACzB,UAAM,aAAa,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK,WAAW,KAAK,EAAE;AAChE,QAAI,WAAY,gBAAe,WAAW,QAAQ;AAAA,EACpD,GAAG,CAAC,WAAW,MAAM,SAAS,cAAc,CAAC;AAE7C,QAAM,WAAW,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK,WAAW,KAAK,EAAE,IAAI;AAEzE,SAAO,EAAE,SAAS,SAAwC,QAAQ,OAAO,MAAM,OAAO,SAAS;AACjG;;;AChCA,SAAS,eAAAC,qBAAmB;AAOrB,SAAS,kBAAkB;AAChC,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,EAAE,SAAS,QAAQ,MAAM,IAAI,SAAsB,iBAAiB;AAAA,IACxE,OAAO,OAAO,EAAE,QAAQ,KAAK,GAAG,IAAI,EAAE,QAAQ,WAAW;AAAA,EAC3D,CAAC;AAED,QAAM,EAAE,QAAQ,IAAI,IAAI,aAA0B,eAAe;AAEjE,QAAM,aAAaC;AAAA,IACjB,CAAC,cAAsB;AACrB,UAAI,CAAC,KAAM;AACX,YAAM,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK,cAAc,SAAS;AACnE,YAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAI,UAAU;AACZ,YAAI,SAAS,UAAU,EAAE,YAAY,IAAI,CAA2B;AAAA,MACtE,OAAO;AACL,eAAO,EAAE,WAAW,QAAQ,KAAK,IAAI,YAAY,IAAI,CAA2B;AAAA,MAClF;AAAA,IACF;AAAA,IACA,CAAC,MAAM,SAAS,QAAQ,GAAG;AAAA,EAC7B;AAEA,QAAM,iBAAiBA;AAAA,IACrB,CAAC,WAAmB,aAA4C;AAC9D,YAAM,UAAU,QAAQ,KAAK,CAAC,MAAM,EAAE,KAAK,cAAc,SAAS;AAClE,UAAI,CAAC,QAAS,QAAO,SAAS;AAC9B,YAAM,aAAa,IAAI,KAAK,QAAQ,KAAK,UAAU,EAAE,QAAQ;AAC7D,aAAO,SAAS,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,UAAU,EAAE;AAAA,IAC9E;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,SAAO,EAAE,UAAU,SAAsC,QAAQ,OAAO,YAAY,eAAe;AACrG;;;ACrCA,SAAS,eAAAC,eAAa,WAAAC,iBAAe;AAY9B,SAAS,gBAAgB,MAAmD;AACjF,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,EAAE,MAAM,IAAI,iBAAiB;AAEnC,QAAM,EAAE,SAAS,YAAY,IAAI,SAA0B,iBAAiB,EAAE,SAAS,cAAc,CAAC;AACtG,QAAM,EAAE,SAAS,aAAa,IAAI,SAA2B,gBAAgB;AAC7E,QAAM,EAAE,SAAS,QAAQ,IAAI,SAAyB,cAAc;AAEpE,QAAM,aAAa,aAA8B,eAAe;AAChE,QAAM,cAAc,aAA+B,gBAAgB;AAEnE,QAAM,OAAOC;AAAA,IACX,CAAC,SAAiB,iBAA0B,aAAsB,aAAuC;AACvG,iBAAW,OAAO;AAAA,QAChB,SAAS;AAAA,QACT,UAAU,MAAM,MAAM;AAAA,QACtB,UAAU,mBAAmB;AAAA,QAC7B,QAAQ;AAAA,QACR,aAAa,eAAe;AAAA,QAC5B,UAAU,WAAW,KAAK,UAAU,QAAQ,IAAI;AAAA,MAClD,CAAC;AACD,YAAM,gBAAgB,SAAS,eAAe;AAAA,IAChD;AAAA,IACA,CAAC,YAAY,MAAM,IAAI,MAAM,aAAa;AAAA,EAC5C;AAEA,QAAM,OAAOA;AAAA,IACX,CAAC,UAAkB,YAAoB;AACrC,YAAM,WAAW,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAChE,UAAI,CAAC,SAAU;AACf,iBAAW,IAAI,UAAU,EAAE,GAAG,SAAS,MAAM,SAAS,SAAS,QAAQ,EAAE,CAAC;AAAA,IAC5E;AAAA,IACA,CAAC,YAAY,WAAW;AAAA,EAC1B;AAEA,QAAM,SAASA;AAAA,IACb,CAAC,aAAqB;AACpB,YAAM,WAAW,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAChE,UAAI,CAAC,SAAU;AACf,iBAAW,IAAI,UAAU;AAAA,QACvB,GAAG,SAAS;AAAA,QACZ,SAAS;AAAA,QACT,aAAa;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,IACA,CAAC,YAAY,WAAW;AAAA,EAC1B;AAEA,QAAM,iBAAiBA;AAAA,IACrB,CAAC,WAAmB,UAAkB;AACpC,YAAM,WAAW,aAAa;AAAA,QAC5B,CAAC,MAAM,EAAE,KAAK,cAAc,aAAa,EAAE,KAAK,UAAU,SAAS,EAAE,KAAK,WAAW,MAAM;AAAA,MAC7F;AACA,UAAI,UAAU;AACZ,oBAAY,OAAO,SAAS,QAAQ;AAAA,MACtC,OAAO;AACL,oBAAY,OAAO,EAAE,WAAW,WAAW,OAAO,OAAO,QAAQ,MAAM,MAAM,GAAG,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,IACA,CAAC,aAAa,cAAc,MAAM,EAAE;AAAA,EACtC;AAEA,SAAOC;AAAA,IACL,OAAO;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX;AAAA,MACA,QAAQ,QAAS,cAAyB;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,aAAa,cAAc,SAAS,OAAO,MAAM,MAAM,QAAQ,cAAc;AAAA,EAChF;AACF;;;AC1FO,SAAS,yBACd,WACA,WACA,eACmB;AACnB,QAAM,aAAa,UAAU,OAAO,CAAC,MAAM,EAAE,KAAK,cAAc,SAAS;AACzE,QAAM,SAAS,oBAAI,IAA+E;AAElG,aAAW,KAAK,YAAY;AAC1B,UAAM,WAAW,OAAO,IAAI,EAAE,KAAK,KAAK,KAAK,EAAE,OAAO,GAAG,oBAAoB,OAAO,SAAS,CAAC,EAAE;AAChG,aAAS;AACT,aAAS,QAAQ,KAAK,EAAE,KAAK,MAAM;AACnC,QAAI,EAAE,KAAK,WAAW,cAAe,UAAS,qBAAqB;AACnE,WAAO,IAAI,EAAE,KAAK,OAAO,QAAQ;AAAA,EACnC;AAEA,SAAO,MAAM,KAAK,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,OAAO;AAAA,IAC1D;AAAA,IACA,OAAO,KAAK;AAAA,IACZ,oBAAoB,KAAK;AAAA,IACzB,SAAS,KAAK;AAAA,EAChB,EAAE;AACJ;AAGA,IAAM,wBAAwB,IAAI,KAAK;AAMhC,SAAS,oBACd,SACA,UACA,SACS;AACT,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,YAAa,QAAO;AACjC,MAAI,SAAS,KAAK,aAAa,QAAQ,KAAK,SAAU,QAAO;AAC7D,QAAM,WAAW,IAAI,KAAK,QAAQ,SAAS,EAAE,QAAQ,IAAI,IAAI,KAAK,SAAS,SAAS,EAAE,QAAQ;AAC9F,SAAO,YAAY,SAAS,eAAe;AAC7C;AAKO,SAAS,gBAAgB,UAAgD;AAC9E,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,KAAK,UAAU;AACnB,aAAO,IAAI,EAAE,KAAK,WAAW,OAAO,IAAI,EAAE,KAAK,QAAQ,KAAK,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,kBAAkB,SAAyB;AACzD,SAAO,IAAI,KAAK,OAAO,EAAE,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AACxF;AAMO,SAAS,oBAAoB,SAAyB;AAC3D,QAAM,OAAO,IAAI,KAAK,OAAO;AAC7B,QAAM,WAAW,KAAK,mBAAmB,CAAC,GAAG,EAAE,OAAO,SAAS,KAAK,WAAW,MAAM,UAAU,CAAC;AAChG,QAAM,WAAW,KAAK,mBAAmB,CAAC,GAAG,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AACnF,SAAO,GAAG,QAAQ,OAAO,QAAQ;AACnC;;;ACxDO,SAAS,2BACd,cACA,eACA,SACQ;AACR,QAAM,EAAE,MAAM,MAAM,eAAe,IAAI,aAAa;AAEpD,MAAI,SAAS,QAAQ,SAAS,SAAS;AACrC,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,MAAM,8BAA8B,cAAc,aAAa;AAErE,MAAI,IAAI,WAAW,EAAG,QAAO;AAE7B,MAAI,SAAS,MAAM;AACjB,UAAM,QAAQ,QAAQ,IAAI,CAAC,CAAC;AAC5B,WAAO,OAAO,QAAQ;AAAA,EACxB;AAGA,QAAM,YAAY;AAClB,QAAM,QAAkB,CAAC;AACzB,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,QAAQ,SAAS,GAAG,KAAK;AACxD,UAAM,IAAI,QAAQ,IAAI,CAAC,CAAC;AACxB,UAAM,KAAK,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,SAAS;AAAA,EAChD;AACA,QAAM,YAAY,IAAI,SAAS;AAC/B,MAAI,YAAY,GAAG;AACjB,WAAO,GAAG,MAAM,KAAK,IAAI,CAAC,MAAM,SAAS;AAAA,EAC3C;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKO,SAAS,iBAAiB,MAAuB;AACtD,SAAO,SAAS,QAAQ,SAAS;AACnC;AAMO,SAAS,8BACd,cACA,eACU;AACV,MAAI,MAAgB,CAAC;AAGrB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,aAAa,KAAK,cAAc;AAC1D,QAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AAC9C,YAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,IAAI,WAAW,KAAK,aAAa,KAAK,iBAAiB;AACzD,UAAM,aAAa,KAAK,gBAAgB,MAAM,GAAG;AAAA,EACnD;AAEA,MAAI,eAAe;AACjB,WAAO,IAAI,OAAO,CAAC,OAAO,OAAO,aAAa;AAAA,EAChD;AACA,SAAO;AACT;;;ACzFO,SAAS,qBAAqB,KAA8C;AACjF,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,MAAI,OAAO,QAAQ,UAAU;AAC3B,QAAI;AAAE,aAAO,KAAK,MAAM,GAAG;AAAA,IAAE,QAAQ;AAAE,aAAO;AAAA,IAAK;AAAA,EACrD;AACA,SAAO;AACT;;;ACAA,SAAS,eAAAC,eAAa,WAAAC,WAAS,UAAAC,gBAAc;AAOtC,SAAS,mBAAmB;AACjC,QAAM,EAAE,SAAS,eAAe,OAAO,IAAI,SAAoC,eAAe;AAC9F,QAAM,EAAE,QAAQ,IAAI,IAAI,aAAwC,eAAe;AAC/E,QAAM,EAAE,SAAS,aAAa,IAAI,SAAgC,oBAAoB;AACtF,QAAM,WAAW,aAAoC,oBAAoB;AACzE,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,QAAQ,WAAW;AAEzB,QAAM,qBAAqBC,SAAO,oBAAI,IAAuC,CAAC;AAC9E,aAAW,CAAC,EAAE,KAAK,mBAAmB,SAAS;AAC7C,QAAI,cAAc,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG;AAChD,yBAAmB,QAAQ,OAAO,EAAE;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,eAAeC;AAAA,IACnB,MAAM,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,CAAC,CAAC;AAAA,IACjF,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,sBAAsBA;AAAA,IAC1B,MAAM,IAAI,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,gBAAgB,EAAE,KAAK,wBAAwB,CAAC,CAAC,CAAC;AAAA,IAChG,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,aAAaA;AAAA,IACjB,MAAM,IAAI,IAAI,aAAa,OAAO,CAAC,MAAM,EAAE,KAAK,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,cAAc,CAAC;AAAA,IAC1F,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,cAAcA;AAAA,IAClB,MAAM,IAAI,IAAI,aAAa,OAAO,CAAC,MAAM,EAAE,KAAK,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,cAAc,CAAC;AAAA,IAC3F,CAAC,YAAY;AAAA,EACf;AAGA,QAAM,uBAAuBC;AAAA,IAC3B,CAAC,mBAA8D;AAC7D,aAAO,aAAa,KAAK,CAAC,MAAM,EAAE,KAAK,mBAAmB,cAAc,GAAG;AAAA,IAC7E;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,oBAAoB;AAAA,IACxB,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,cAAc;AAAA,EAChB;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,MAAc,gBAAyB;AAC5C,YAAM,WAAW,cAAc,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,QAAQ,EAAE,KAAK,SAAS,IAAI;AACvF,UAAI,SAAU,QAAO,SAAS;AAE9B,YAAM,WAAW,MAAM,OAAO;AAAA,QAC5B,MAAM;AAAA,QACN,aAAa,eAAe;AAAA,QAC5B,MAAM;AAAA,QACN,WAAW,MAAM,MAAM;AAAA,QACvB,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,QACf,oBAAoB;AAAA,QACpB,mBAAmB;AAAA,QACnB,GAAG;AAAA,MACL,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,MAAM,IAAI,aAAa;AAAA,EAClC;AAEA,QAAM,WAAWA;AAAA,IACf,OAAO,gBAAwB;AAC7B,UAAI,CAAC,MAAM,GAAI,QAAO;AACtB,YAAM,OAAO,CAAC,KAAK,IAAI,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG;AAEnD,YAAM,WAAW,cAAc,KAAK,CAAC,MAAM,EAAE,KAAK,oBAAoB,IAAI;AAC1E,UAAI,SAAU,QAAO,SAAS;AAE9B,YAAM,OAAkC;AAAA,QACtC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,iBAAiB;AAAA,QACjB,gBAAgB,KAAK,UAAU,CAAC,KAAK,IAAI,WAAW,CAAC;AAAA,QACrD,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe;AAAA,QACf,oBAAoB;AAAA,QACpB,mBAAmB;AAAA,QACnB,cAAc;AAAA,MAChB;AACA,YAAM,WAAW,MAAM,OAAO,IAAI;AAClC,yBAAmB,QAAQ,IAAI,UAAU,IAAI;AAC7C,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,MAAM,IAAI,aAAa;AAAA,EAClC;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,mBAA6B;AAClC,UAAI,CAAC,MAAM,GAAI,QAAO;AAEtB,YAAM,SAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,KAAK,IAAI,GAAG,cAAc,CAAC,CAAC;AACxD,UAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,YAAM,OAAO,OAAO,KAAK,EAAE,KAAK,GAAG;AAEnC,YAAM,WAAW,cAAc,KAAK,CAAC,MAAM,EAAE,KAAK,oBAAoB,IAAI;AAC1E,UAAI,SAAU,QAAO,SAAS;AAE9B,YAAM,OAAkC;AAAA,QACtC,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,WAAW,KAAK;AAAA,QAChB,iBAAiB;AAAA,QACjB,gBAAgB,KAAK,UAAU,MAAM;AAAA,QACrC,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,eAAe;AAAA,QACf,oBAAoB;AAAA,QACpB,mBAAmB;AAAA,QACnB,cAAc;AAAA,MAChB;AACA,YAAM,WAAW,MAAM,OAAO,IAAI;AAClC,yBAAmB,QAAQ,IAAI,UAAU,IAAI;AAC7C,aAAO;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,MAAM,IAAI,aAAa;AAAA,EAClC;AAEA,QAAM,eAAeA;AAAA,IACnB,CAAC,SAAiB;AAChB,YAAM,QAAQ,cAAc,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,IAAI;AAC5D,aAAO,OAAO,YAAY;AAAA,IAC5B;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,gBAAwB,SAAiB,aAAsB;AAC9D,YAAM,OAAO,cAAc,KAAK,CAAC,MAAM,EAAE,aAAa,cAAc;AACpE,YAAM,WAAW,MAAM,QAAQ,mBAAmB,QAAQ,IAAI,cAAc;AAC5E,UAAI,CAAC,SAAU;AACf,YAAM,cAAc;AAAA,QAClB,GAAG;AAAA,QACH,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,QACtC,oBAAoB,QAAQ,MAAM,GAAG,GAAG;AAAA,QACxC,mBAAmB,YAAY,SAAS;AAAA,QACxC,eAAe,SAAS,gBAAgB,KAAK;AAAA,MAC/C;AACA,UAAI,gBAAgB,WAAW;AAC/B,UAAI,mBAAmB,QAAQ,IAAI,cAAc,GAAG;AAClD,2BAAmB,QAAQ,IAAI,gBAAgB,WAAW;AAAA,MAC5D;AAAA,IACF;AAAA,IACA,CAAC,KAAK,aAAa;AAAA,EACrB;AAGA,QAAM,cAAcA;AAAA,IAClB,CAAC,gBAAwB,YAA4C;AACnE,UAAI,CAAC,MAAM,GAAI;AACf,YAAM,WAAW,aAAa;AAAA,QAC5B,CAAC,MAAM,EAAE,KAAK,mBAAmB,kBAAkB,EAAE,KAAK,WAAW,KAAK;AAAA,MAC5E;AACA,YAAM,OAA8B,UAAU,QAAQ;AAAA,QACpD,gBAAgB;AAAA,QAChB,QAAQ,KAAK;AAAA,QACb,YAAY;AAAA,QACZ,sBAAsB;AAAA,QACtB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AACA,YAAM,WAAW,UAAU,YAAY,SAAS,KAAK,EAAE,IAAI,cAAc;AACzE,eAAS,IAAI,UAAU,EAAE,GAAG,MAAM,GAAG,QAAQ,CAAC;AAAA,IAChD;AAAA,IACA,CAAC,UAAU,cAAc,MAAM,EAAE;AAAA,EACnC;AAEA,QAAM,WAAWA;AAAA,IACf,CAAC,mBAA2B;AAC1B,YAAM,OAAO,cAAc,KAAK,CAAC,MAAM,EAAE,aAAa,cAAc;AACpE,YAAM,WAAW,MAAM,KAAK,gBAAgB,mBAAmB,QAAQ,IAAI,cAAc,GAAG,gBAAgB;AAC5G,kBAAY,gBAAgB;AAAA,QAC1B,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,QACnC,sBAAsB;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,aAAa,aAAa;AAAA,EAC7B;AAEA,QAAM,aAAaA;AAAA,IACjB,CAAC,mBAA2B;AAC1B,YAAM,YAAY,WAAW,IAAI,cAAc;AAC/C,kBAAY,gBAAgB,EAAE,SAAS,YAAY,IAAI,EAAE,CAAC;AAAA,IAC5D;AAAA,IACA,CAAC,aAAa,UAAU;AAAA,EAC1B;AAEA,QAAM,cAAcA;AAAA,IAClB,CAAC,gBAAwB,aAAsB;AAC7C,kBAAY,gBAAgB,EAAE,UAAU,WAAW,IAAI,EAAE,CAAC;AAAA,IAC5D;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,aAAaA;AAAA,IACjB,CAAC,gBAAwB,YAAqB;AAC5C,kBAAY,gBAAgB,EAAE,SAAS,UAAU,IAAI,EAAE,CAAC;AAAA,IAC1D;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,YAAYA;AAAA,IAChB,CAAC,gBAAwB,WAAqB;AAC5C,kBAAY,gBAAgB,EAAE,QAAQ,KAAK,UAAU,MAAM,EAAE,CAAC;AAAA,IAChE;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,YAAYA;AAAA,IAChB,CAAC,gBAAwB,WAAmB;AAC1C,kBAAY,gBAAgB,EAAE,QAAQ,OAAO,CAAC;AAAA,IAChD;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5QA,SAAS,eAAAC,eAAa,WAAAC,iBAAe;AAO9B,SAAS,iBAAiB;AAC/B,QAAM,EAAE,SAAS,aAAa,OAAO,IAAI,SAAiC,aAAa;AACvF,QAAM,eAAe,aAAqC,aAAa;AACvE,QAAM,EAAE,SAAS,YAAY,IAAI,SAAkC,aAAa;AAChF,QAAM,gBAAgB,aAAsC,aAAa;AACzE,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,QAAQ,WAAW;AAEzB,QAAM,gBAAgBC,UAAQ,MAAM;AAClC,UAAM,MAAM,oBAAI,IAAuC;AACvD,eAAW,KAAK,aAAa;AAC3B,YAAM,OAAO,IAAI,IAAI,EAAE,KAAK,WAAW,KAAK,CAAC;AAC7C,WAAK,KAAK,EAAE,IAAI;AAChB,UAAI,IAAI,EAAE,KAAK,aAAa,IAAI;AAAA,IAClC;AACA,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,gBAAgBA;AAAA,IACpB,MAAM,IAAI;AAAA,MACR,YACG,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,MAAM,EAAE,EACxC,IAAI,CAAC,MAAM,EAAE,KAAK,WAAW;AAAA,IAClC;AAAA,IACA,CAAC,aAAa,MAAM,EAAE;AAAA,EACxB;AAEA,QAAM,kBAAkBC;AAAA,IACtB,OAAO,MAAc,SAAwF;AAC3G,YAAM,WAAW,YAAY,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,IAAI;AAC7D,UAAI,SAAU,QAAO,SAAS;AAE9B,YAAM,WAAW,MAAM,aAAa,OAAO;AAAA,QACzC,MAAM;AAAA,QACN,aAAa,MAAM,eAAe;AAAA,QAClC,WAAW,MAAM,MAAM;AAAA,QACvB,MAAM,MAAM,QAAQ;AAAA,QACpB,YAAY,MAAM,cAAc;AAAA,QAChC,aAAa;AAAA,QACb,OAAO,MAAM,SAAS;AAAA,QACtB,SAAS;AAAA,QACT,UAAU;AAAA,MACZ,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,cAAc,MAAM,IAAI,WAAW;AAAA,EACtC;AAEA,QAAM,kBAAkBA;AAAA,IACtB,CAAC,aAAqB,YAA6C;AACjE,YAAM,WAAW,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,WAAW;AACnE,UAAI,CAAC,SAAU;AACf,mBAAa,IAAI,aAAa,EAAE,GAAG,SAAS,MAAM,GAAG,QAAQ,CAAC;AAAA,IAChE;AAAA,IACA,CAAC,cAAc,WAAW;AAAA,EAC5B;AAEA,QAAM,gBAAgBA;AAAA,IACpB,OAAO,aAAqB,aAAqB;AAC/C,UAAI,CAAC,MAAM,GAAI,QAAO;AACtB,YAAM,WAAW,YAAY;AAAA,QAC3B,CAAC,MAAM,EAAE,KAAK,gBAAgB,eAAe,EAAE,KAAK,WAAW,KAAK;AAAA,MACtE;AACA,UAAI,SAAU,QAAO,SAAS;AAE9B,YAAM,WAAW,MAAM,cAAc,OAAO;AAAA,QAC1C,aAAa;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,UAAU;AAAA,QACV,MAAM;AAAA,QACN,WAAU,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,eAAe,aAAa,MAAM,EAAE;AAAA,EACvC;AAEA,QAAM,iBAAiBA;AAAA,IACrB,CAAC,gBAAwB;AACvB,UAAI,CAAC,MAAM,GAAI;AACf,YAAM,aAAa,YAAY;AAAA,QAC7B,CAAC,MAAM,EAAE,KAAK,gBAAgB,eAAe,EAAE,KAAK,WAAW,KAAK;AAAA,MACtE;AACA,UAAI,YAAY;AACd,sBAAc,OAAO,WAAW,QAAQ;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,CAAC,eAAe,aAAa,MAAM,EAAE;AAAA,EACvC;AAEA,QAAM,eAAeA;AAAA,IACnB,CAAC,gBAAmD;AAClD,aAAO,cAAc,IAAI,WAAW,KAAK,CAAC;AAAA,IAC5C;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,eAAeA;AAAA,IACnB,CAAC,SAAiB;AAChB,YAAM,QAAQ,YAAY,KAAK,CAAC,MAAM,EAAE,KAAK,SAAS,IAAI;AAC1D,aAAO,OAAO,YAAY;AAAA,IAC5B;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC9HA,SAAS,eAAAC,qBAAmB;AAOrB,SAAS,SAAS,MAAiC;AACxD,QAAM,EAAE,SAAS,UAAU,OAAO,IAAI,SAA4B,OAAO;AACzE,QAAM,UAAU,aAAgC,OAAO;AACvD,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,QAAM,QAAQ,WAAW;AAEzB,QAAM,QAAQ,MAAM,cAChB,SAAS,OAAO,CAAC,MAAM,EAAE,KAAK,gBAAgB,KAAK,WAAW,IAC9D;AAEJ,QAAM,aAAaC;AAAA,IACjB,OAAO,SAQD;AACJ,YAAM,WAAW,MAAM,QAAQ,OAAO;AAAA,QACpC,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd,UAAU,MAAM,MAAM;AAAA,QACtB,MAAM,KAAK,QAAQ;AAAA,QACnB,aAAa,KAAK,eAAe;AAAA,QACjC,UAAU,KAAK,YAAY;AAAA,QAC3B,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,MAAM,KAAK,OAAO,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,QAC9C,SAAS,KAAK,WAAW;AAAA,MAC3B,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,CAAC,SAAS,MAAM,EAAE;AAAA,EACpB;AAEA,QAAM,aAAaA;AAAA,IACjB,CAAC,QAAgB,YAAwC;AACvD,YAAM,WAAW,SAAS,KAAK,CAAC,MAAM,EAAE,aAAa,MAAM;AAC3D,UAAI,CAAC,SAAU;AACf,cAAQ,IAAI,QAAQ,EAAE,GAAG,SAAS,MAAM,GAAG,QAAQ,CAAC;AAAA,IACtD;AAAA,IACA,CAAC,SAAS,QAAQ;AAAA,EACpB;AAEA,QAAM,aAAaA;AAAA,IACjB,CAAC,WAAmB;AAClB,cAAQ,OAAO,MAAM;AAAA,IACvB;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,oBAAoBA;AAAA,IACxB,CAAC,QAAgB,mBAA2B;AAC1C,iBAAW,QAAQ,EAAE,gBAAgB,eAAe,CAAC;AAAA,IACvD;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACpFA,SAAgB,aAAAC,mBAAiC;;;ACIjD,SAAS,IAAI,OAAe,KAAa,OAAO,eAAuB;AACrE,SAAO,sBAAsB,KAAK,IAAI,KAAK,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI;AACvE;AAKO,SAAS,YAAY,OAAwB;AAClD,QAAM,IAAI,MAAM,KAAK;AAGrB,QAAM,WAAW,EAAE,MAAM,mDAAmD;AAC5E,MAAI,UAAU;AACZ,UAAMC,KAAI,WAAW,SAAS,CAAC,CAAC,IAAI;AACpC,UAAMC,KAAI,WAAW,SAAS,CAAC,CAAC,IAAI;AACpC,UAAMC,KAAI,WAAW,SAAS,CAAC,CAAC,IAAI;AACpC,WAAO,SAASF,KAAI,SAASC,KAAI,SAASC,KAAI;AAAA,EAChD;AAGA,MAAI,CAAC,EAAE,WAAW,GAAG,EAAG,QAAO;AAC/B,MAAI,MAAM,EAAE,MAAM,CAAC;AACnB,MAAI,IAAI,WAAW,EAAG,OAAM,IAAI,CAAC,IAAE,IAAI,CAAC,IAAE,IAAI,CAAC,IAAE,IAAI,CAAC,IAAE,IAAI,CAAC,IAAE,IAAI,CAAC;AACpE,MAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI;AAC1C,SAAO,SAAS,IAAI,SAAS,IAAI,SAAS,IAAI;AAChD;AAWA,IAAM,kBAA0C;AAAA,EAC9C,gBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,qBAAuB;AAAA,EACvB,oBAAuB;AAAA,EACvB,oBAAuB;AAAA,EACvB,eAAuB;AAAA,EACvB,sBAAuB;AAAA,EACvB,qBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,sBAAuB;AAAA,EACvB,iBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,cAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,kBAAuB;AACzB;AAGA,IAAM,iBAAyC;AAAA,EAC7C,gBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,qBAAuB;AAAA,EACvB,oBAAuB;AAAA,EACvB,oBAAuB;AAAA,EACvB,eAAuB;AAAA,EACvB,sBAAuB;AAAA,EACvB,qBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,mBAAuB;AAAA,EACvB,sBAAuB;AAAA,EACvB,iBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,cAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,kBAAuB;AAAA,EACvB,gBAAuB;AAAA,EACvB,kBAAuB;AACzB;AAGA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EAAgB;AAAA,EAAmB;AAAA,EAAqB;AAAA,EAAoB;AAAA,EAC5E;AAAA,EAAe;AAAA,EACf;AAAA,EAAqB;AAAA,EAAuB;AAAA,EAAmB;AAAA,EAC/D;AAAA,EAAe;AAAA,EAAqB;AAAA,EACpC;AAAA,EAAiB;AAAA,EAAkB;AAAA,EACnC;AAAA,EAAgB;AAAA,EAAgB;AAAA,EAChC;AAAA,EAAkB;AAAA,EAAkB;AAAA,EACpC;AAAA,EAAgB;AAClB;AAMO,IAAM,6BAA6B;AAAA;AAAA,EAExC;AAAA,EAAoB;AAAA,EAA2B;AAAA,EAC/C;AAAA,EAAuB;AAAA,EAAwB;AAAA,EAC/C;AAAA,EAA2B;AAAA;AAAA,EAE3B;AAAA,EAAqB;AAAA,EAAyB;AAAA,EAC9C;AAAA,EAA+B;AAAA,EAAyB;AAAA;AAAA,EAExD;AAAA,EAAgB;AAAA,EAAsB;AAAA,EAA0B;AAAA;AAAA,EAEhE;AAAA,EAAkB;AAAA,EAA2B;AAAA,EAC7C;AAAA,EAAqB;AAAA,EAA2B;AAAA;AAAA,EAEhD;AAAA,EAA0B;AAAA,EAA4B;AAAA,EACtD;AAAA;AAAA,EAEA;AAAA,EAAmB;AAAA,EACnB;AAAA,EAA2B;AAAA,EAA2B;AAAA;AAAA,EAEtD;AAAA;AAAA,EAEA;AAAA,EAAuB;AAAA,EACvB;AAAA,EAAmB;AAAA,EAAmB;AAAA,EAAsB;AAAA;AAAA,EAE5D;AAAA,EAAqB;AAAA,EACrB;AAAA,EAAsB;AAAA;AAAA,EAEtB,GAAG;AACL;AAMO,SAAS,oBACd,OAAoB,SAAS,iBACvB;AACN,aAAW,QAAQ,4BAA4B;AAC7C,SAAK,MAAM,eAAe,IAAI;AAAA,EAChC;AACF;AAaO,SAAS,mBACd,OACA,OAAoB,SAAS,iBAC7B,QACM;AACN,QAAM,OAAO,UAAU;AAGvB,QAAM,OAAO,OAAO,iBAAiB;AACrC,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC9C,SAAK,MAAM,YAAY,MAAM,GAAG;AAAA,EAClC;AAGA,QAAM,cAAc,QAAQ,UACtB,iBAAiB,IAAI,EAAE,iBAAiB,gBAAgB,EAAE,KAAK,MAAM,OAAO,YAAY;AAC9F,QAAM,cAAc,QAAQ,SACvB,sBAAsB,WAAW;AACtC,QAAM,YAAY,QAAQ,cACpB,iBAAiB,IAAI,EAAE,iBAAiB,mBAAmB,EAAE,KAAK,KAAK;AAE7E,OAAK,MAAM,YAAY,eAAe,WAAW;AACjD,OAAK,MAAM,YAAY,qBAAqB,WAAW;AACvD,OAAK,MAAM,YAAY,yBAAyB,SAAS;AACzD,OAAK,MAAM,YAAY,kBAAkB,sBAAsB,WAAW,IAAI,OAAO,KAAK,EAAE,iBAAiB;AAC7G,OAAK,MAAM,YAAY,oBAAoB,OAAO,YAAY,WAAW;AAC3E;AAWO,SAAS,oBACd,QACA,OAAoB,SAAS,iBACvB;AACN,QAAM;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,IACtB;AAAA,IACA,cAAc;AAAA,IACd,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,EAClB,IAAI;AAKJ,QAAM,UAAU,gBAAgB,IAAI,YAAY,GAAG,IAAI;AACvD,QAAM,gBAAgB,gBAAgB,IAAI,YAAY,IAAI,IAAI;AAC9D,QAAM,aAAa,gBAAgB,IAAI,YAAY,KAAK,OAAO,IAAI;AACnE,QAAM,mBAAmB,gBAAgB,IAAI,gBAAgB,GAAG,IAAI;AACpE,QAAM,aAAa,gBAAgB,IAAI,YAAY,GAAG,IAAI;AAG1D,QAAM,cAAc,gBAAgB,IAAI,aAAa,GAAG,IAAI;AAG5D,QAAM,WAAW,gBAAgB,IAAI,gBAAgB,GAAG,IAAI;AAC5D,QAAM,eAAe,gBAAgB,IAAI,aAAa,GAAG,IAAI;AAC7D,QAAM,oBAAoB,gBAAgB,IAAI,aAAa,GAAG,IAAI;AAClE,QAAM,cAAc,IAAI,aAAa,GAAG;AACxC,QAAM,eAAe,IAAI,aAAa,GAAG;AAGzC,QAAM,gBAAgB,IAAI,WAAW,GAAG;AACxC,QAAM,eAAe,IAAI,WAAW,GAAG;AAGvC,QAAM,cAAc,IAAI,aAAa,KAAK,OAAO;AACjD,QAAM,YAAY,IAAI,gBAAgB,GAAG;AACzC,QAAM,iBAAiB,IAAI,gBAAgB,KAAK,OAAO;AACvD,QAAM,eAAe,IAAI,cAAc,KAAK,OAAO;AAGnD,QAAM,gBAAgB,IAAI,aAAa,GAAG;AAC1C,QAAM,kBAAkB,IAAI,aAAa,GAAG;AAC5C,QAAM,eAAe,IAAI,aAAa,IAAI;AAC1C,QAAM,kBACJ,aAAa,IAAI,aAAa,IAAI,CAAC,eAAe,IAAI,aAAa,IAAI,CAAC;AAG1E,QAAM,UAAU,IAAI,cAAc,IAAI;AACtC,QAAM,iBAAiB,gBAAgB,IAAI,WAAW,IAAI,IAAI;AAG9D,QAAM,kBAAkB,6CAA6C,cAAc,4CAA4C,cAAc,6CAA6C,cAAc,4CAA4C,cAAc,4CAA4C,cAAc;AAG5T,QAAM,qBAAqB;AAAA,IACzB,sCAAsC,cAAc;AAAA,IACpD,sCAAsC,cAAc;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kCAAkC,cAAc;AAAA,EAClD,EAAE,KAAK,IAAI;AAMX,QAAM,mBAAmB,KAAK,QAAQ;AACtC,QAAM,OAAQ,qBAAqB,UAAU,qBAAqB,UAC9D,qBAAqB,SACrB,YAAY,eAAe;AAG/B,OAAK,QAAQ,gBAAgB,gBAAgB,YAAY;AACzD,MAAI,CAAC,kBAAkB;AACrB,SAAK,QAAQ,UAAU,OAAO,SAAS;AAAA,EACzC;AAGA,QAAM,UAA8B;AAAA;AAAA,IAElC,CAAC,oBAAoB,OAAO;AAAA,IAC5B,CAAC,2BAA2B,aAAa;AAAA,IACzC,CAAC,8BAA8B,gBAAgB;AAAA,IAC/C,CAAC,uBAAuB,UAAU;AAAA,IAClC,CAAC,wBAAwB,UAAU;AAAA,IACnC,CAAC,wBAAwB,WAAW;AAAA,IACpC,CAAC,2BAA2B,cAAc;AAAA,IAC1C,CAAC,sBAAsB,eAAe;AAAA;AAAA,IAGtC,CAAC,qBAAqB,QAAQ;AAAA,IAC9B,CAAC,yBAAyB,YAAY;AAAA,IACtC,CAAC,wBAAwB,WAAW;AAAA,IACpC,CAAC,+BAA+B,iBAAiB;AAAA,IACjD,CAAC,yBAAyB,YAAY;AAAA,IACtC,CAAC,qBAAqB,SAAS;AAAA;AAAA,IAG/B,CAAC,gBAAgB,SAAS;AAAA,IAC1B,CAAC,sBAAsB,SAAS;AAAA,IAChC,CAAC,0BAA0B,aAAa;AAAA,IACxC,CAAC,yBAAyB,YAAY;AAAA;AAAA,IAGtC,CAAC,kBAAkB,WAAW;AAAA,IAC9B,CAAC,2BAA2B,mBAAmB;AAAA,IAC/C,CAAC,wBAAwB,WAAW;AAAA,IACpC,CAAC,qBAAqB,SAAS;AAAA,IAC/B,CAAC,2BAA2B,cAAc;AAAA,IAC1C,CAAC,yBAAyB,YAAY;AAAA;AAAA,IAGtC,CAAC,0BAA0B,aAAa;AAAA,IACxC,CAAC,4BAA4B,eAAe;AAAA,IAC5C,CAAC,yBAAyB,YAAY;AAAA,IACtC,CAAC,4BAA4B,eAAe;AAAA;AAAA,IAG5C,CAAC,mBAAmB,OAAO;AAAA,IAC3B,CAAC,yBAAyB,YAAY;AAAA,IACtC,CAAC,2BAA2B,wBAAwB;AAAA,IACpD,CAAC,2BAA2B,sBAAsB;AAAA,IAClD,CAAC,+BAA+B,wBAAwB;AAAA;AAAA,IAGxD,CAAC,kBAAkB,IAAI,aAAa,GAAG,CAAC;AAAA;AAAA,IAGxC,CAAC,uBAAuB,SAAS;AAAA,IACjC,CAAC,6BAA6B,wBAAwB;AAAA,IACtD,CAAC,mBAAmB,SAAS;AAAA,IAC7B,CAAC,mBAAmB,SAAS;AAAA,IAC7B,CAAC,sBAAsB,0BAA0B;AAAA,IACjD,CAAC,sBAAsB,SAAS;AAAA;AAAA,IAGhC,CAAC,qBAAqB,cAAc;AAAA;AAAA,IAGpC,CAAC,gBAAgB,mEAAmE;AAAA;AAAA,IAGpF,CAAC,sBAAsB,eAAe;AAAA,IACtC,CAAC,0BAA0B,kBAAkB;AAAA,EAC/C;AAEA,aAAW,CAAC,UAAU,KAAK,KAAK,SAAS;AACvC,SAAK,MAAM,YAAY,UAAU,KAAK;AAAA,EACxC;AAGA,qBAAmB,OAAO,SAAS,SAAS,MAAM;AAAA,IAChD,OAAO;AAAA,IACP,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAUO,SAAS,iBACd,OAAoB,SAAS,iBACP;AACtB,QAAM,SAAS,iBAAiB,IAAI;AACpC,QAAM,MAAM,CAAC,MAAc,aACzB,OAAO,iBAAiB,IAAI,EAAE,KAAK,KAAK;AAE1C,SAAO;AAAA,IACL,cAAc,IAAI,4BAA4B,SAAS;AAAA,IACvD,gBAAgB,IAAI,2BAA2B,SAAS;AAAA,IACxD,aAAa,IAAI,mBAAmB,SAAS;AAAA,IAC7C,WAAW,IAAI,mBAAmB,SAAS;AAAA,IAC3C,aAAa,IAAI,kBAAkB,uBAAuB;AAAA,IAC1D,iBAAiB,IAAI,mBAAmB,SAAS;AAAA,IACjD,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,qBAAqB;AAAA,EACvB;AACF;;;ADvVS,qBAAAC,WAAA,OAAAC,YAAA;AAVF,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AACF,GAAoD;AAClD,EAAAC,YAAU,MAAM;AACd,UAAM,OAAO,SAAS;AACtB,UAAM,SAAS,SAAS,iBAAiB,IAAI;AAC7C,wBAAoB,QAAQ,IAAI;AAAA,EAClC,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO,gBAAAD,KAAAD,WAAA,EAAG,UAAS;AACrB;;;AEjDA,SAAS,YAAAG,YAAU,aAAAC,mBAAiB;AAM7B,SAAS,iBAA0B;AACxC,QAAM,CAAC,QAAQ,SAAS,IAAID;AAAA,IAAS,MACnC,OAAO,aAAa,eAAe,SAAS,gBAAgB,QAAQ,YAAY;AAAA,EAClF;AAEA,EAAAC,YAAU,MAAM;AACd,UAAM,SAAS,MAAY;AACzB,gBAAU,SAAS,gBAAgB,QAAQ,YAAY,OAAO;AAAA,IAChE;AACA,WAAO;AACP,WAAO,iBAAiB,wBAAwB,MAAM;AACtD,WAAO,MAAM,OAAO,oBAAoB,wBAAwB,MAAM;AAAA,EACxE,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;;;ACMA,SAAS,iBAAAC,gBAAe,cAAAC,aAAY,YAAAC,YAAU,aAAAC,aAAW,UAAAC,UAAQ,eAAAC,qBAAmB;AA2IhF,gBAAAC,YAAA;AAnHG,IAAM,kBAAkBC,eAA2C,IAAI;AAEvE,SAAS,cAAoC;AAClD,QAAM,MAAMC,YAAW,eAAe;AACtC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,oDAAoD;AAC9E,SAAO;AACT;AAOO,SAAS,WAAyB;AACvC,QAAM,EAAE,OAAO,eAAe,IAAI,YAAY;AAC9C,EAAAC,YAAU,MAAM,eAAe,GAAG,CAAC,cAAc,CAAC;AAClD,SAAO;AACT;AAEO,SAAS,iBAAiB,EAAE,SAAS,GAAkC;AAC5E,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAAuB,CAAC,CAAC;AAGnD,QAAM,mBAAmBC,SAAO,CAAC;AACjC,QAAM,CAAC,aAAa,cAAc,IAAID,WAAS,KAAK;AAEpD,QAAM,iBAAiBE,cAAY,MAAM;AACvC,qBAAiB;AACjB,QAAI,iBAAiB,YAAY,EAAG,gBAAe,IAAI;AACvD,WAAO,MAAM;AACX,uBAAiB;AACjB,UAAI,iBAAiB,YAAY,EAAG,gBAAe,KAAK;AAAA,IAC1D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,EAAAH,YAAU,MAAM;AACd,QAAI,CAAC,YAAa;AAElB,QAAI,UAAU;AACd,QAAI,KAAuB;AAC3B,QAAI;AACJ,QAAI;AAEJ,mBAAe,UAAU;AACvB,YAAM,QAAQ,MAAM,aAAa;AACjC,UAAI,CAAC,QAAS;AACd,UAAI,CAAC,OAAO;AAEV,qBAAa,WAAW,SAAS,GAAK;AACtC;AAAA,MACF;AAEA,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,WAAK,IAAI;AAAA,QACP,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI,4BAA4B,mBAAmB,KAAK,CAAC;AAAA,MAC3F;AAEA,SAAG,YAAY,CAAC,MAAM;AACpB,YAAI,EAAE,SAAS,OAAQ;AACvB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,EAAE,IAAI;AAC7B,kBAAQ,IAAI,MAAM;AAAA,YAChB,KAAK;AACH,uBAAS,IAAI,OAAO;AACpB;AAAA,YACF,KAAK;AACH,uBAAS,UAAQ,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC;AACrC;AAAA,YACF,KAAK;AACH,uBAAS,UAAQ,KAAK,OAAO,OAAK,EAAE,mBAAmB,IAAI,cAAc,CAAC;AAC1E;AAAA,YACF,KAAK;AACH;AAAA,gBAAS,UACP,KAAK,IAAI,OAAM,EAAE,mBAAmB,IAAI,MAAM,iBAAiB,IAAI,QAAQ,CAAE;AAAA,cAC/E;AACA;AAAA,UACJ;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,SAAG,UAAU,MAAM;AACjB,YAAI,SAAS;AAEX,uBAAa,WAAW,SAAS,GAAK;AAAA,QACxC;AAAA,MACF;AAEA,qBAAe,YAAY,MAAM;AAC/B,YAAI,IAAI,eAAe,UAAU,KAAM,IAAG,KAAK,MAAM;AAAA,MACvD,GAAG,GAAM;AAAA,IACX;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,gBAAU;AACV,mBAAa,UAAU;AACvB,oBAAc,YAAY;AAC1B,UAAI,MAAM;AACV,eAAS,CAAC,CAAC;AAAA,IACb;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAGhB,QAAM,gBAAgBG,cAAY,OAAO,MAAc,SAAuB;AAC5E,UAAM,QAAQ,MAAM,aAAa;AACjC,UAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,QAAI,MAAO,SAAQ,IAAI,iBAAiB,UAAU,KAAK,EAAE;AACzD,QAAI,CAAC,QAAQ,IAAI,cAAc,KAAK,MAAM,KAAM,SAAQ,IAAI,gBAAgB,kBAAkB;AAC9F,WAAO,MAAM,YAAY,IAAI,IAAI,EAAE,GAAG,MAAM,QAAQ,CAAC;AAAA,EACvD,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAN,KAAC,gBAAgB,UAAhB,EAAyB,OAAO,EAAE,eAAe,gBAAgB,MAAM,GACrE,UACH;AAEJ;;;ACnJA,SAAS,YAAAO,YAAU,aAAAC,aAAW,UAAAC,gBAAc;AAI5C,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAwBtB,SAAS,cACd,SACqB;AACrB,QAAM,EAAE,MAAM,SAAS,cAAc,UAAU,IAAI;AACnD,QAAM,QAAQC,SAAyB,IAAI;AAC3C,QAAM,kBAAkBA,SAA8C,IAAI;AAC1E,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAAY,YAAY;AAClD,QAAM,sBAAsBD,SAAO,CAAC;AACpC,QAAM,oBAAoBA,SAA6C,IAAI;AAC3E,QAAM,aAAaA,SAAO,IAAI;AAG9B,QAAM,eAAeA,SAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,kBAAkBA,SAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,EAAAE,YAAU,MAAM;AACd,eAAW,UAAU;AACrB,WAAO,MAAM;AAAE,iBAAW,UAAU;AAAA,IAAM;AAAA,EAC5C,GAAG,CAAC,CAAC;AAEL,EAAAA,YAAU,MAAM;AACd,QAAI,CAAC,QAAS;AAEd,aAAS,gBAAgB,OAAO;AAChC,wBAAoB,UAAU;AAE9B,mBAAe,UAAU;AACvB,UAAI,CAAC,WAAW,WAAW,CAAC,QAAS;AAErC,YAAM,QAAQ,MAAM,aAAa;AACjC,UAAI,CAAC,SAAS,CAAC,WAAW,SAAS;AACjC,0BAAkB,UAAU,WAAW,SAAS,GAAK;AACrD;AAAA,MACF;AAEA,YAAM,SAAS,IAAI,gBAAgB;AACnC,aAAO,IAAI,SAAS,KAAK;AAEzB,YAAM,WAAW,OAAO,SAAS,aAAa,WAAW,SAAS;AAClE,YAAM,KAAK,IAAI;AAAA,QACb,GAAG,QAAQ,KAAK,OAAO,SAAS,IAAI,gBAAgB,IAAI,IAAI,OAAO,IAAI,MAAM;AAAA,MAC/E;AACA,YAAM,UAAU;AAEhB,SAAG,YAAY,CAAC,MAAM;AACpB,YAAI,EAAE,SAAS,OAAQ;AACvB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,EAAE,IAAI;AAC7B,cAAI,IAAI,SAAS,QAAQ;AACvB,gCAAoB,UAAU;AAAA,UAChC;AACA,mBAAS,UAAQ,aAAa,QAAQ,KAAK,IAAI,CAAC;AAAA,QAClD,SAAS,KAAK;AACZ,kBAAQ,MAAM,kBAAkB,IAAI,0BAA0B,GAAG;AAAA,QACnE;AAAA,MACF;AAEA,SAAG,UAAU,MAAM;AACjB,YAAI,CAAC,WAAW,QAAS;AACzB,cAAM,UAAU,oBAAoB;AACpC,cAAM,QAAQ,KAAK,IAAI,uBAAuB,KAAK,IAAI,GAAG,OAAO,GAAG,mBAAmB;AACvF,iBAAS,WAAS;AAAA,UAChB,GAAG;AAAA,UACH,QAAS,YAAY,IAAI,eAAe;AAAA,QAC1C,EAAE;AACF,0BAAkB,UAAU,WAAW,SAAS,KAAK;AAAA,MACvD;AAEA,UAAI,gBAAgB,QAAS,eAAc,gBAAgB,OAAO;AAClE,sBAAgB,UAAU,YAAY,MAAM;AAC1C,YAAI,GAAG,eAAe,UAAU,KAAM,IAAG,KAAK,MAAM;AAAA,MACtD,GAAG,GAAM;AAAA,IACX;AAEA,YAAQ;AAER,WAAO,MAAM;AACX,UAAI,kBAAkB,SAAS;AAC7B,qBAAa,kBAAkB,OAAO;AACtC,0BAAkB,UAAU;AAAA,MAC9B;AACA,UAAI,gBAAgB,SAAS;AAC3B,sBAAc,gBAAgB,OAAO;AACrC,wBAAgB,UAAU;AAAA,MAC5B;AACA,YAAM,SAAS,MAAM;AACrB,YAAM,UAAU;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,SAAS,IAAI,CAAC;AAElB,QAAM,OAAOF,SAAO,CAAC,QAAiC;AACpD,UAAM,SAAS,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,EACzC,CAAC,EAAE;AAEH,SAAO,EAAE,OAAO,KAAK;AACvB;;;AC1IA,IAAM,kBAAkB;AACxB,IAAMG,sBAAqB;AAc3B,SAAS,WAAW,UAA0B;AAC5C,MAAI,SAAS,WAAW,SAAS,KAAK,SAAS,WAAW,UAAU,GAAG;AACrE,WAAO;AAAA,EACT;AACA,QAAM,OAAO,SAAS,WAAW,GAAG,IAAI,WAAW,WAAW,GAAG,eAAe,IAAI,QAAQ,KAAK;AACjG,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,GAAG,OAAO,SAAS,MAAM,GAAG,IAAI;AAAA,EACzC;AACA,SAAO;AACT;AAEA,eAAe,QACb,QACA,UACA,MACA,SACiC;AACjC,QAAM,MAAM,WAAW,QAAQ;AAC/B,QAAM,YAAY,SAAS,aAAaA;AAExC,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,GAAG,SAAS;AAAA,EACd;AAGA,MAAI;AACF,UAAM,QAAQ,MAAM,aAAa;AACjC,QAAI,MAAO,SAAQ,eAAe,IAAI,UAAU,KAAK;AAAA,EACvD,QAAQ;AAAA,EAER;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAE9D,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,MAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,MAC5C,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,QAAI;AACJ,QAAI;AACF,gBAAW,MAAM,IAAI,KAAK;AAAA,IAC5B,QAAQ;AACN,aAAO,EAAE,SAAS,OAAO,OAAO,mBAAmB,IAAI,MAAM,IAAI;AAAA,IACnE;AAEA,QAAI,CAAC,IAAI,MAAM,QAAQ,YAAY,OAAO;AACxC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAQ,QAAQ,SAAqB,QAAQ,WAAsB,mBAAmB,IAAI,MAAM;AAAA,QAChG,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAwC,IAAI,CAAC;AAAA,MACtF;AAAA,IACF;AAGA,QAAI,UAAU,SAAS;AACrB,aAAO,EAAE,SAAS,MAAM,MAAM,QAAQ,KAAU;AAAA,IAClD;AACA,UAAM,EAAE,SAAS,UAAU,GAAG,KAAK,IAAI;AACvC,WAAO,EAAE,SAAS,MAAM,MAAM,KAAU;AAAA,EAC1C,SAAS,KAAc;AACrB,QAAI,eAAe,gBAAgB,IAAI,SAAS,cAAc;AAC5D,aAAO,EAAE,SAAS,OAAO,OAAO,2BAA2B,SAAS,KAAK;AAAA,IAC3E;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,IAC9C;AAAA,EACF,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEO,IAAM,cAAc;AAAA,EACzB,KAAkB,UAAkB,MAAgB,SAA0B;AAC5E,WAAO,QAAW,QAAQ,UAAU,MAAM,OAAO;AAAA,EACnD;AAAA,EACA,IAAiB,UAAkB,QAAuE,SAA0B;AAClI,QAAI,MAAM;AACV,QAAI,QAAQ;AACV,YAAM,eAAe,IAAI,gBAAgB;AACzC,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,YAAI,KAAK,KAAM,cAAa,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,MAC9C;AACA,YAAM,KAAK,aAAa,SAAS;AACjC,UAAI,GAAI,OAAM,GAAG,QAAQ,IAAI,EAAE;AAAA,IACjC;AACA,WAAO,QAAW,OAAO,KAAK,QAAW,OAAO;AAAA,EAClD;AAAA,EACA,IAAiB,UAAkB,MAAgB,SAA0B;AAC3E,WAAO,QAAW,OAAO,UAAU,MAAM,OAAO;AAAA,EAClD;AAAA,EACA,OAAoB,UAAkB,MAAgB,SAA0B;AAC9E,WAAO,QAAW,UAAU,UAAU,MAAM,OAAO;AAAA,EACrD;AACF;;;ACpGO,SAAS,aAAa,MAAoC;AAC/D,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,WAAW,GAAG,EAAG,QAAO;AACjC,MAAI,CAAC,KAAK,WAAW,OAAO,EAAG,QAAO;AAGtC,QAAM,MAAM,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,EAAE,EAAE,QAAQ,OAAO,EAAE;AAC7D,MAAI,QAAQ,SAAU,QAAO;AAC7B,MAAI;AACF,UAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA2BO,SAAS,oBAAoB,OAA6C;AAC/E,MAAI,OAAO,MAAM,SAAS,SAAU,QAAO;AAE3C,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,cAAc;AACjB,YAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC9D,UAAI,CAAC,MAAO,QAAO;AACnB,aAAO,EAAE,MAAM,eAAe,MAAM;AAAA,IACtC;AAAA,IAEA,KAAK,wBAAwB;AAC3B,UAAI,OAAO,MAAM,eAAe,YAAY,OAAO,MAAM,aAAa,SAAU,QAAO;AACvF,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,MACf;AAAA,IACF;AAAA,IAEA,KAAK,yBAAyB;AAC5B,UAAI,OAAO,MAAM,eAAe,SAAU,QAAO;AAQjD,YAAM,SAAS,YAAY,QAAQ,MAAM,SAAS;AAClD,aAAO,EAAE,MAAM,sBAAsB,YAAY,MAAM,YAAY,OAAO;AAAA,IAC5E;AAAA,IAEA,KAAK,oBAAoB;AACvB,UAAI,OAAO,MAAM,eAAe,YAAY,OAAO,MAAM,aAAa,SAAU,QAAO;AACvF,YAAM,YAAY,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1E,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,qBAAqB;AACxB,UAAI,OAAO,MAAM,eAAe,SAAU,QAAO;AACjD,YAAM,YAAY,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1E,aAAO,EAAE,MAAM,oBAAoB,YAAY,MAAM,YAAY,UAAU;AAAA,IAC7E;AAAA,IAEA,KAAK,SAAS;AACZ,YAAM,YAAY,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1E,aAAO,EAAE,MAAM,gBAAgB,UAAU;AAAA,IAC3C;AAAA,IAEA,KAAK;AACH,aAAO,EAAE,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA,IAKzB;AACE,aAAO;AAAA,EACX;AACF;;;ACrIA,SAAS,eAAAC,eAAa,aAAAC,aAAW,YAAAC,kBAAgB;;;AC2C1C,IAAM,oBAAyC,oBAAI,IAAI;AAAA,EAC5D;AAAA,EACA;AACF,CAAC;AAYM,SAAS,WAAW,MAAc,QAAyB;AAChE,MAAI,SAAS,OAAQ,QAAO;AAC5B,SAAO,kBAAkB,IAAI,MAAM;AACrC;;;ADKA,eAAe,WAAc,MAAc,MAAgC;AACzE,QAAM,QAAQ,MAAM,aAAa;AACjC,QAAM,MAAM,MAAM,MAAM,MAAM;AAAA,IAC5B,GAAG;AAAA,IACH,aAAa;AAAA,IACb,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAI,QAAQ,EAAE,eAAe,UAAU,KAAK,GAAG,IAAI,CAAC;AAAA,MACpD,GAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AACD,QAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAO,KAAK,SAAoB,mBAAmB,IAAI,MAAM,GAAG;AAAA,EAC5E;AACA,SAAO;AACT;AAEO,SAAS,kBAAyC;AACvD,QAAM,CAAC,OAAO,QAAQ,IAAIC,WAA4B;AAAA,IACpD,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,aAAa;AAAA,IACb,OAAO,CAAC;AAAA,EACV,CAAC;AACD,QAAM,CAAC,WAAW,UAAU,IAAIA,WAAS,IAAI;AAC7C,QAAM,CAAC,OAAO,QAAQ,IAAIA,WAAwB,IAAI;AAEtD,QAAM,UAAUC,cAAY,YAAY;AACtC,eAAW,IAAI;AACf,QAAI;AACF,YAAM,IAAI,MAAM,WAA8B,8BAA8B;AAC5E,eAAS;AAAA,QACP,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,QACV,UAAU,EAAE,YAAY;AAAA,QACxB,kBAAkB,EAAE;AAAA,QACpB,mBAAmB,EAAE;AAAA,QACrB,aAAa,EAAE;AAAA,QACf,OAAO,EAAE,SAAS,CAAC;AAAA,MACrB,CAAC;AACD,eAAS,IAAI;AAAA,IACf,SAAS,GAAG;AACV,eAAS,aAAa,QAAQ,EAAE,UAAU,6BAA6B;AAAA,IACzE,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,EAAAC,YAAU,MAAM;AACd,YAAQ;AAAA,EACV,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,WAAW,WAAW,MAAM,MAAM,MAAM,MAAM;AACpD,QAAM,UAAUD;AAAA,IACd,CAAC,SAAiB,MAAM,SAAS,QAAQ,WAAW,MAAM,MAAM,MAAM,MAAM;AAAA,IAC5E,CAAC,MAAM,MAAM,MAAM,MAAM;AAAA,EAC3B;AACA,QAAM,YAAYA;AAAA,IAChB,CAAC,SAAiB;AAChB,UAAI,CAAC,WAAW,MAAM,MAAM,MAAM,MAAM,EAAG,QAAO;AAClD,YAAM,aAAa,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,GAAG;AAC7D,YAAM,cAAc,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,IAAI,GAAG;AACpE,UAAI,cAAc,QAAQ,eAAe,KAAM,QAAO;AACtD,aAAO,eAAe;AAAA,IACxB;AAAA,IACA,CAAC,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM;AAAA,EACxC;AAEA,QAAM,YAAYA;AAAA,IAChB,OAAO,UAAkB,SAAmD;AAC1E,YAAM,SAAS,MAAM,WAA4B,sCAAsC;AAAA,QACrF,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB;AAAA,UACA,UAAU,MAAM,YAAY;AAAA,UAC5B,WAAW,MAAM,aAAa,OAAO,SAAS;AAAA,UAC9C,WAAW,MAAM,aAAa,OAAO,SAAS;AAAA,UAC9C,cAAc,OAAO,WAAW;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AACD,UAAI,OAAO,UAAW,OAAM,QAAQ;AAOpC,UAAI,OAAO,WAAW,eAAe,OAAO,KAAK;AAC/C,eAAO,SAAS,OAAO,OAAO;AAAA,MAChC;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,aAAaA;AAAA,IACjB,OAAO,cAAuB;AAC5B,aAAO,WAA4B,oCAAoC;AAAA,QACrE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,EAAE,WAAW,aAAa,OAAO,SAAS,KAAK,CAAC;AAAA,MACvE,CAAC;AAAA,IACH;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,QAAQ,MAAM;AAAA,IACd;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,kBAAkB,MAAM;AAAA,IACxB,mBAAmB,MAAM;AAAA,IACzB,aAAa,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AEjJc,gBAAAE,OACA,QAAAC,aADA;AArCP,SAAS,aAAa,OAK1B;AACD,QAAM,WAAW,MAAM,YAAY;AACnC,SACE,gBAAAD,MAAC,SAAI,WAAU,6BACZ,gBAAM,MAAM,IAAI,CAAC,SAAS;AACzB,UAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAC7D,UAAM,WAAW,MAAM,gBAAgB,KAAK;AAM5C,UAAM,aAAa,KAAK,OAAO,WAAW;AAC1C,UAAM,iBAAiB,KAAK,OACzB,IAAI,CAAC,MAAM,EAAE,QAAQ,EACrB,OAAO,CAAC,MAAM,MAAM,QAAQ;AAC/B,UAAM,sBAAsB,CAAC,SAAS,CAAC;AACvC,UAAM,eAAe,eAAe,WAAW,IAAI,eAAe,CAAC,IAAI;AACvE,UAAM,mBAAmB,eACrB,iBAAiB,UACf,iBACA,gBACF;AACJ,UAAM,aAAa,QACf,KAAK,MAAM,aAAa,KAAK,QAAQ,CAAC,CAAC,KACvC,aACE,SACA;AACN,UAAM,WAAW,YAAY;AAC7B,WACE,gBAAAC,MAAC,aAAwB,WAAU,uCACjC;AAAA,sBAAAA,MAAC,SAAI,WAAU,aACb;AAAA,wBAAAD,MAAC,QAAG,WAAU,yBAAyB,eAAK,MAAK;AAAA,QACjD,gBAAAC,MAAC,OAAE,WAAU,0BACV;AAAA;AAAA,UACD,gBAAAD,MAAC,UAAK,WAAU,6CACb,kBAAQ,IAAI,QAAQ,KAAK,IAC5B;AAAA,WACF;AAAA,QACC,KAAK,YACJ,gBAAAC,MAAC,OAAE,WAAU,iCAAiC;AAAA,eAAK;AAAA,UAAU;AAAA,WAAe,IAC1E;AAAA,SACN;AAAA,MACA,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL;AAAA,UACA,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ;AAAA,UACtD,WAAU;AAAA,UAET,qBACG,iBACA,sBACE,mBACA;AAAA;AAAA,MACR;AAAA,SAxBY,KAAK,IAyBnB;AAAA,EAEJ,CAAC,GACH;AAEJ;;;ACzDA,SAAS,eAAAE,eAAa,aAAAC,aAAW,WAAAC,WAAS,YAAAC,kBAAgB;AAuF1D,eAAeC,YAAc,MAAc,MAAgC;AACzE,QAAM,QAAQ,MAAM,aAAa;AACjC,QAAM,MAAM,MAAM,MAAM,MAAM;AAAA,IAC5B,GAAG;AAAA,IACH,aAAa;AAAA,IACb,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,GAAI,QAAQ,EAAE,eAAe,UAAU,KAAK,GAAG,IAAI,CAAC;AAAA,MACpD,GAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AACD,QAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC/C,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAO,KAAK,SAAoB,mBAAmB,IAAI,MAAM,GAAG;AAAA,EAC5E;AACA,SAAO;AACT;AAEO,SAAS,YAAY,MAA2C;AACrE,QAAM,CAAC,WAAW,YAAY,IAAIC,WAAqB,CAAC,CAAC;AACzD,QAAM,CAAC,WAAW,UAAU,IAAIA,WAAS,IAAI;AAC7C,QAAM,CAAC,OAAO,QAAQ,IAAIA,WAAwB,IAAI;AAMtD,QAAM,UAAUC,cAAY,YAAY;AACtC,eAAW,IAAI;AACf,QAAI;AACF,YAAM,IAAI,MAAMF;AAAA,QACd;AAAA,MACF;AACA,mBAAa,EAAE,aAAa,CAAC,CAAC;AAC9B,eAAS,IAAI;AAAA,IACf,SAAS,GAAG;AACV,eAAS,aAAa,QAAQ,EAAE,UAAU,0BAA0B;AAAA,IACtE,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,EAAAG,YAAU,MAAM;AACd,YAAQ;AAAA,EACV,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,aAAaD;AAAA,IACjB,OAAO,eAA0D;AAI/D,eAAS,IAAI;AAOb,YAAM,SAAS;AAAA,QACb,WAAW,WAAW,aAAa,OAAO,SAAS;AAAA,QACnD,WAAW,WAAW,aAAa,OAAO,SAAS;AAAA,QACnD,cAAc,OAAO,WAAW;AAAA,MAClC;AACA,YAAM,OACJ,WAAW,cAAc,SACrB,EAAE,GAAG,QAAQ,WAAW,WAAW,UAAU,IAC7C;AAAA,QACE,GAAG;AAAA,QACH,QAAQ,WAAW;AAAA,QACnB,MAAM,WAAW;AAAA,QACjB,GAAI,WAAW,cAAc,EAAE,aAAa,WAAW,YAAY,IAAI,CAAC;AAAA,MAC1E;AAEN,UAAI;AACF,cAAM,SAAS,MAAMF;AAAA,UACnB;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,MAAM,KAAK,UAAU,IAAI;AAAA,UAC3B;AAAA,QACF;AACA,YAAI,OAAO,WAAW,eAAe,OAAO,KAAK;AAC/C,iBAAO,SAAS,OAAO,OAAO;AAAA,QAChC;AACA,eAAO;AAAA,MACT,SAAS,GAAG;AACV,cAAM,MAAM,aAAa,QAAQ,EAAE,UAAU;AAC7C,iBAAS,GAAG;AACZ,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,cAAcE;AAAA,IAClB,CAAC,cAAsB,UAAU,KAAK,CAAC,MAAM,EAAE,cAAc,SAAS;AAAA,IACtE,CAAC,SAAS;AAAA,EACZ;AAKA,QAAM,QAAQE;AAAA,IACZ,MAAM,CAAC,CAAC,MAAM,aAAa,UAAU,KAAK,CAAC,MAAM,EAAE,cAAc,KAAK,SAAS;AAAA,IAC/E,CAAC,MAAM,WAAW,SAAS;AAAA,EAC7B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AChOA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAA8B;AAClD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ACLA,YAAYC,YAAW;AAQrB,gBAAAC,aAAA;AAJF,IAAM,OAAa,kBAGjB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,KAAK,cAAc;AAEnB,IAAM,aAAmB,kBAGvB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,wCAAwC,SAAS;AAAA,IAC9D,GAAG;AAAA;AACN,CACD;AACD,WAAW,cAAc;AAEzB,IAAM,YAAkB,kBAGtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,6CAA6C,SAAS;AAAA,IACnE,GAAG;AAAA;AACN,CACD;AACD,UAAU,cAAc;AAExB,IAAM,kBAAwB,kBAG5B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,IACvD,GAAG;AAAA;AACN,CACD;AACD,gBAAgB,cAAc;AAE9B,IAAM,cAAoB,kBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA,MAAC,SAAI,KAAU,WAAW,GAAG,2BAA2B,SAAS,GAAI,GAAG,OAAO,CAChF;AACD,YAAY,cAAc;AAE1B,IAAM,aAAmB,kBAGvB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,6CAA6C,SAAS;AAAA,IACnE,GAAG;AAAA;AACN,CACD;AACD,WAAW,cAAc;;;ACzEzB,YAAYC,YAAW;AACvB,YAAY,wBAAwB;AAYhC,gBAAAC,aAAA;AARJ,IAAM,YAAkB;AAAA,EAItB,CACE,EAAE,WAAW,cAAc,cAAc,aAAa,MAAM,GAAG,MAAM,GACrE,QAEA,gBAAAA;AAAA,IAAoB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,gBAAgB,eAAe,mBAAmB;AAAA,QAClD;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AACA,UAAU,cAAiC,wBAAK;;;AC1BhD,YAAYC,YAAW;AASnB,gBAAAC,aAAA;AALJ,IAAM,QAAc,kBAGlB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA,MAAC,SAAI,WAAU,iCACb,0BAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,IACvD,GAAG;AAAA;AACN,GACF,CACD;AACD,MAAM,cAAc;AAEpB,IAAM,cAAoB,kBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA,MAAC,WAAM,KAAU,WAAW,GAAG,mBAAmB,SAAS,GAAI,GAAG,OAAO,CAC1E;AACD,YAAY,cAAc;AAE1B,IAAM,YAAkB,kBAGtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,8BAA8B,SAAS;AAAA,IACpD,GAAG;AAAA;AACN,CACD;AACD,UAAU,cAAc;AAExB,IAAM,cAAoB,kBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAAc;AAE1B,IAAM,WAAiB,kBAGrB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,SAAS,cAAc;AAEvB,IAAM,YAAkB,kBAGtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,UAAU,cAAc;AAExB,IAAM,YAAkB,kBAGtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,UAAU,cAAc;AAExB,IAAM,eAAqB,kBAGzB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,sCAAsC,SAAS;AAAA,IAC5D,GAAG;AAAA;AACN,CACD;AACD,aAAa,cAAc;;;AC5G3B,YAAYC,aAAW;AACvB,YAAY,mBAAmB;AAU7B,gBAAAC,aAAA;AANF,IAAM,OAAqB;AAE3B,IAAM,WAAiB,mBAGrB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAe;AAAA,EAAd;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,SAAS,cAA4B,mBAAK;AAE1C,IAAM,cAAoB,mBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAe;AAAA,EAAd;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAA4B,sBAAQ;AAEhD,IAAM,cAAoB,mBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAe;AAAA,EAAd;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAA4B,sBAAQ;;;AClDhD,YAAYC,aAAW;AACvB,SAAS,YAAY;AACrB,SAAS,WAA8B;AA6CjC,SAOI,OAAAC,OAPJ,QAAAC,aAAA;AAzCN,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,WACE;AAAA,QACF,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AASA,IAAM,SAAe;AAAA,EACnB,CAAC,EAAE,WAAW,SAAS,MAAM,UAAU,OAAO,UAAU,OAAO,UAAU,UAAU,GAAG,MAAM,GAAG,QAAQ;AACrG,UAAM,OAAO,UAAU,OAAO;AAC9B,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,eAAe,EAAE,SAAS,MAAM,UAAU,CAAC,CAAC;AAAA,QAC1D;AAAA,QACA,UAAU,YAAY;AAAA,QACrB,GAAG;AAAA,QAEH;AAAA,qBACC,gBAAAD,MAAC,UAAK,WAAU,kFAAiF;AAAA,UAElG;AAAA;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,OAAO,cAAc;;;AC7DrB,YAAYE,aAAW;AAOjB,gBAAAC,aAAA;AAHN,IAAM,QAAc;AAAA,EAClB,CAAC,EAAE,WAAW,MAAM,GAAG,MAAM,GAAG,QAAQ;AACtC,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AACA,MAAM,cAAc;;;ACnBpB,YAAYC,aAAW;AASnB,gBAAAC,aAAA;AALJ,IAAM,WAAiB,mBAGrB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ;AAClC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AACD,SAAS,cAAc;;;ACnBvB,YAAYC,aAAW;AACvB,YAAY,qBAAqB;AACjC,SAAS,OAAO,aAAa,iBAAiB;AAc5C,SAUI,OAAAC,OAVJ,QAAAC,aAAA;AAVF,IAAM,SAAyB;AAE/B,IAAM,cAA8B;AAEpC,IAAM,cAA8B;AAEpC,IAAM,gBAAsB,mBAG1B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QACpC,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEH;AAAA;AAAA,MACD,gBAAAD,MAAiB,sBAAhB,EAAqB,SAAO,MAC3B,0BAAAA,MAAC,eAAY,WAAU,sBAAqB,GAC9C;AAAA;AAAA;AACF,CACD;AACD,cAAc,cAA8B,wBAAQ;AAEpD,IAAM,uBAA6B,mBAGjC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ,0BAAAA,MAAC,aAAU,WAAU,WAAU;AAAA;AACjC,CACD;AACD,qBAAqB,cAA8B,+BAAe;AAElE,IAAM,yBAA+B,mBAGnC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ,0BAAAA,MAAC,eAAY,WAAU,WAAU;AAAA;AACnC,CACD;AACD,uBAAuB,cACL,iCAAiB;AAEnC,IAAM,gBAAsB,mBAG1B,CAAC,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,MAAM,GAAG,QACzD,gBAAAA,MAAiB,wBAAhB,EACC,0BAAAC;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,aAAa,YACX;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,sBAAAD,MAAC,wBAAqB;AAAA,MACtB,gBAAAA;AAAA,QAAiB;AAAA,QAAhB;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,aAAa,YACX;AAAA,UACJ;AAAA,UAEC;AAAA;AAAA,MACH;AAAA,MACA,gBAAAA,MAAC,0BAAuB;AAAA;AAAA;AAC1B,GACF,CACD;AACD,cAAc,cAA8B,wBAAQ;AAEpD,IAAM,cAAoB,mBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,qCAAqC,SAAS;AAAA,IAC3D,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAA8B,sBAAM;AAEhD,IAAM,aAAmB,mBAGvB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QACpC,gBAAAC;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,sBAAAD,MAAC,UAAK,WAAU,iEACd,0BAAAA,MAAiB,+BAAhB,EACC,0BAAAA,MAAC,SAAM,WAAU,WAAU,GAC7B,GACF;AAAA,MACA,gBAAAA,MAAiB,0BAAhB,EAA0B,UAAS;AAAA;AAAA;AACtC,CACD;AACD,WAAW,cAA8B,qBAAK;AAE9C,IAAM,kBAAwB,mBAG5B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,4BAA4B,SAAS;AAAA,IAClD,GAAG;AAAA;AACN,CACD;AACD,gBAAgB,cAA8B,0BAAU;;;AC/IxD,YAAYE,aAAW;AACvB,YAAY,uBAAuB;AACnC,SAAS,SAAAC,cAAa;AAmBhB,gBAAAC,aAAA;AAfN,IAAM,WAAiB,mBAGrB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAmB;AAAA,EAAlB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ,0BAAAA;AAAA,MAAmB;AAAA,MAAlB;AAAA,QACC,WAAW,GAAG,wCAAwC;AAAA,QAEtD,0BAAAA,MAACC,QAAA,EAAM,WAAU,WAAU;AAAA;AAAA,IAC7B;AAAA;AACF,CACD;AACD,SAAS,cAAgC,uBAAK;;;ACzB9C,YAAYC,aAAW;AACvB,YAAY,sBAAsB;AAgB9B,gBAAAC,aAAA;AAZJ,IAAM,SAAe,mBAGnB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAkB;AAAA,EAAjB;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IACJ;AAAA,IAEA,0BAAAA;AAAA,MAAkB;AAAA,MAAjB;AAAA,QACC,WAAW;AAAA,UACT;AAAA,QACF;AAAA;AAAA,IACF;AAAA;AACF,CACD;AACD,OAAO,cAA+B,sBAAK;;;ACxB3C,YAAYC,aAAW;AACvB,YAAY,oBAAoB;AAChC,SAAS,OAAAC,YAA8B;AAarC,gBAAAC,aAAA;AATF,IAAM,gBAAgBC;AAAA,EACpB;AACF;AAEA,IAAMC,SAAc,mBAIlB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAF;AAAA,EAAgB;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAW,GAAG,cAAc,GAAG,SAAS;AAAA,IACvC,GAAG;AAAA;AACN,CACD;AACDE,OAAM,cAA6B,oBAAK;;;ACpBxC,SAAS,OAAAC,YAA8B;AA0CnC,gBAAAC,aAAA;AAtCJ,IAAM,gBAAgBC;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,WACE;AAAA,QACF,aACE;AAAA,QACF,SAAS;AAAA,QACT,SACE;AAAA,QACF,SACE;AAAA,QACF,MACE;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAMA,SAAS,MAAM,EAAE,WAAW,SAAS,MAAM,GAAG,MAAM,GAAe;AACjE,SACE,gBAAAD,MAAC,SAAI,WAAW,GAAG,cAAc,EAAE,SAAS,KAAK,CAAC,GAAG,SAAS,GAAI,GAAG,OAAO;AAEhF;;;AC7CA,YAAYE,aAAW;AACvB,YAAY,qBAAqB;AAQ/B,gBAAAC,aAAA;AAJF,IAAM,SAAe,mBAGnB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,OAAO,cAA8B,qBAAK;AAE1C,IAAM,cAAoB,mBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,+BAA+B,SAAS;AAAA,IACrD,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAA8B,sBAAM;AAEhD,IAAM,iBAAuB,mBAG3B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,eAAe,cAA8B,yBAAS;;;AC7CtD,YAAYC,aAAW;AACvB,YAAY,uBAAuB;AAgB/B,gBAAAC,aAAA;AAZJ,IAAM,WAAiB,mBAGrB,CAAC,EAAE,WAAW,OAAO,GAAG,MAAM,GAAG,QACjC,gBAAAA;AAAA,EAAmB;AAAA,EAAlB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ,0BAAAA;AAAA,MAAmB;AAAA,MAAlB;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,WAAW,eAAe,OAAO,SAAS,EAAE,KAAK;AAAA;AAAA,IAC5D;AAAA;AACF,CACD;AACD,SAAS,cAAgC,uBAAK;;;ACV1C,gBAAAC,OAgDE,QAAAC,aAhDF;AALJ,SAAS,SAAS;AAAA,EAChB;AAAA,EACA,GAAG;AACL,GAAyC;AACvC,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,0CAA0C,SAAS;AAAA,MAChE,GAAG;AAAA;AAAA,EACN;AAEJ;AAYA,SAAS,aAAa;AAAA,EACpB,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,YAAY;AACd,GAAmC;AACjC,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC,gBAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,MACrC,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,WAAU;AAAA,MACV,OAAO,EAAE,OAAO,MAAM,QAAQ,IAAI,gBAAgB,OAAO;AAAA;AAAA,IAFpD;AAAA,EAGP,CACD,GACH;AAEJ;AAWA,SAAS,aAAa,EAAE,WAAW,OAAO,YAAY,GAAG,GAAmC;AAC1F,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,mDAAmD,SAAS,GAC5E;AAAA,gBAAY,gBAAAD,MAAC,YAAS,WAAU,4BAA2B;AAAA,IAC5D,gBAAAC,MAAC,SAAI,WAAU,iBACb;AAAA,sBAAAD,MAAC,YAAS,WAAU,aAAY;AAAA,MAChC,gBAAAA,MAAC,gBAAa,OAAO,GAAG;AAAA,MACxB,gBAAAA,MAAC,YAAS,WAAU,aAAY;AAAA,OAClC;AAAA,KACF;AAEJ;AAWA,SAAS,aAAa,EAAE,QAAQ,GAAG,YAAY,GAAG,GAAmC;AACnF,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC,gBAAM,KAAK,EAAE,QAAQ,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,MACrC,gBAAAC,MAAC,SAAY,WAAU,+DACrB;AAAA,oBAAAD,MAAC,YAAS,WAAU,0BAAyB;AAAA,IAC7C,gBAAAC,MAAC,SAAI,WAAU,oBACb;AAAA,sBAAAD,MAAC,YAAS,WAAU,aAAY;AAAA,MAChC,gBAAAA,MAAC,YAAS,WAAU,aAAY;AAAA,OAClC;AAAA,IACA,gBAAAA,MAAC,YAAS,WAAU,YAAW;AAAA,OANvB,CAOV,CACD,GACH;AAEJ;AAYA,SAAS,cAAc;AAAA,EACrB,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AACd,GAAoC;AAClC,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,mDAAmD,SAAS,GAE7E;AAAA,oBAAAD,MAAC,SAAI,WAAU,qDACZ,gBAAM,KAAK,EAAE,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,GAAG,MACvC,gBAAAA,MAAC,YAAiB,WAAU,gBAAb,CAA0B,CAC1C,GACH;AAAA,IAEC,MAAM,KAAK,EAAE,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,aACpC,gBAAAA,MAAC,SAAmB,WAAU,uDAC3B,gBAAM,KAAK,EAAE,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAACE,IAAG,aACvC,gBAAAF;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,aAAa,IAAI,QAAQ,OAAU;AAAA;AAAA,MAF9C;AAAA,IAGP,CACD,KAPO,QAQV,CACD;AAAA,KACH;AAEJ;AAWA,SAAS,eAAe,EAAE,OAAO,MAAM,YAAY,GAAG,GAAqC;AACzF,QAAM,QAAQ;AAAA,IACZ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SAAO,gBAAAA,MAAC,YAAS,WAAW,GAAG,MAAM,IAAI,GAAG,gBAAgB,SAAS,GAAG;AAC1E;AAWA,SAAS,eAAe,EAAE,OAAO,MAAM,YAAY,GAAG,GAAqC;AACzF,QAAM,QAAQ;AAAA,IACZ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,MAAM,IAAI,GAAG,oEAAoE,SAAS;AAAA;AAAA,EAC1G;AAEJ;AAYA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAAqC;AACnC,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,mDAAmD,SAAS,GAC7E;AAAA,oBAAAD,MAAC,kBAAe,MAAK,MAAK;AAAA,IACzB,WAAW,gBAAAA,MAAC,OAAE,WAAU,8BAA8B,mBAAQ;AAAA,IAC9D;AAAA,KACH;AAEJ;;;ACtMA,SAAS,gBAAgB,cAAc;AAqBnC,gBAAAG,OA2EA,QAAAC,aA3EA;AATG,SAAS,SAAS,EAAE,UAAU,UAAU,GAAG,YAAY,IAAI,GAAG,KAAK,GAA+B;AACvG,QAAM,WAAW;AAAA,IACf,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,SACE,gBAAAD,MAAC,SAAI,WAAW,GAAG,uBAAuB,SAAS,OAAO,GAAG,SAAS,GAAI,GAAG,MAC1E,UACH;AAEJ;AAYO,SAAS,SAAS,EAAE,UAAU,SAAS,YAAY,IAAI,YAAY,MAAM,GAAG,KAAK,GAA+B;AACrH,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,aAAa;AAAA,QACb,WAAW;AAAA,QACX;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAaA,SAAS,cAAc,EAAE,KAAK,MAAM,IAAI,SAAS,MAAM,YAAY,GAAG,GAAoC;AACxG,QAAM,UAAU;AAAA,IACd,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,QAAQ,MAAM,GAAG,4BAA4B,SAAS,GACvE,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,gBAAe;AAAA,MACf,WAAU;AAAA;AAAA,EACZ,GACF;AAEJ;AAYA,SAAS,eAAe,EAAE,UAAU,SAAS,YAAY,GAAG,GAAqC;AAC/F,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,mDAAmD,SAAS,GAC7E;AAAA,oBAAAD,MAAC,SAAI,WAAU,kBAAkB,UAAS;AAAA,IACzC,WACC,gBAAAA,MAAC,SAAI,WAAU,uEACZ,mBACH;AAAA,KAEJ;AAEJ;AAWA,SAAS,cAAc,EAAE,UAAU,YAAY,GAAG,GAAoC;AACpF,SACE,gBAAAA,MAAC,QAAG,WAAW,GAAG,0CAA0C,SAAS,GAClE,UACH;AAEJ;AAWA,SAAS,gBAAgB,EAAE,UAAU,YAAY,GAAG,GAAsC;AACxF,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC,UACH;AAEJ;AAYA,SAAS,oBAAoB,EAAE,UAAU,QAAQ,GAAG,YAAY,GAAG,GAA0C;AAC3G,QAAM,YAAY;AAAA,IAChB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAEA,SACE,gBAAAA,MAAC,OAAE,WAAW,GAAG,iDAAiD,UAAU,KAAK,GAAG,SAAS,GAC1F,UACH;AAEJ;AAWA,SAAS,eAAe,EAAE,UAAU,YAAY,GAAG,GAAqC;AACtF,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,gDAAgD,SAAS,GACzE,UACH;AAEJ;AAYA,SAAS,cAAc,EAAE,UAAU,UAAU,WAAW,YAAY,GAAG,GAAoC;AACzG,QAAM,WAAW;AAAA,IACf,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,SACE,gBAAAA,MAAC,UAAK,WAAW,GAAG,8DAA8D,SAAS,OAAO,GAAG,SAAS,GAC3G,UACH;AAEJ;AAWA,SAAS,gBAAgB,EAAE,UAAU,OAAO,GAAsC;AAChF,QAAM,cAAc,CAAC,GAAqB,YAA+B;AACvE,MAAE,gBAAgB;AAClB,cAAU;AAAA,EACZ;AAEA,SACE,gBAAAC,MAAC,SAAI,WAAU,2BACZ;AAAA,cACC,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,CAAC,MAAM,YAAY,GAAG,MAAM;AAAA,QACrC,WAAU;AAAA,QAEV,0BAAAA,MAAC,kBAAe,WAAU,WAAU;AAAA;AAAA,IACtC;AAAA,IAED,YACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,CAAC,MAAM,YAAY,GAAG,QAAQ;AAAA,QACvC,WAAU;AAAA,QAEV,0BAAAA,MAAC,UAAO,WAAU,WAAU;AAAA;AAAA,IAC9B;AAAA,KAEJ;AAEJ;AAMA,SAAS,QAAQ;AACjB,SAAS,SAAS;AAClB,SAAS,QAAQ;AACjB,SAAS,UAAU;AACnB,SAAS,cAAc;AACvB,SAAS,SAAS;AAClB,SAAS,QAAQ;AACjB,SAAS,UAAU;;;ACjQnB,YAAYE,aAAW;AACvB,SAAS,OAAAC,YAA8B;AA8BrC,gBAAAC,aAAA;AA1BF,IAAM,gBAAgBC;AAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,aACE;AAAA,QACF,SACE;AAAA,QACF,SACE;AAAA,QACF,MACE;AAAA,MACJ;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAEA,IAAM,QAAc,mBAGlB,CAAC,EAAE,WAAW,SAAS,GAAG,MAAM,GAAG,QACnC,gBAAAD;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,MAAK;AAAA,IACL,WAAW,GAAG,cAAc,EAAE,QAAQ,CAAC,GAAG,SAAS;AAAA,IAClD,GAAG;AAAA;AACN,CACD;AACD,MAAM,cAAc;AAEpB,IAAM,aAAmB,mBAGvB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,gDAAgD,SAAS;AAAA,IACtE,GAAG;AAAA;AACN,CACD;AACD,WAAW,cAAc;AAEzB,IAAM,mBAAyB,mBAG7B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC;AAAA,IACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,IACvD,GAAG;AAAA;AACN,CACD;AACD,iBAAiB,cAAc;;;AC7C/B;AAAA,EACE,iBAAAE;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,eAAAC;AAAA,EACA,aAAAC;AAAA,OAEK;AAiCH,SACE,OAAAC,OADF,QAAAC,cAAA;AAFJ,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AAC9D,SACE,gBAAAA,OAAC,SAAI,WAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAa,GAAG,eAAc,SAAQ,gBAAe,SACpI;AAAA,oBAAAD,MAAC,UAAK,GAAE,sCAAqC;AAAA,IAC7C,gBAAAA,MAAC,cAAS,QAAO,yBAAwB;AAAA,KAC3C;AAEJ;AAEA,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AAC9D,SACE,gBAAAC,OAAC,SAAI,WAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAa,GAAG,eAAc,SAAQ,gBAAe,SACpI;AAAA,oBAAAD,MAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,IAC/B,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,IACrC,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,SAAQ,IAAG,MAAK;AAAA,KAC3C;AAEJ;AAEA,SAAS,kBAAkB,EAAE,UAAU,GAA2B;AAChE,SACE,gBAAAC,OAAC,SAAI,WAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAa,GAAG,eAAc,SAAQ,gBAAe,SACpI;AAAA,oBAAAD,MAAC,UAAK,GAAE,4FAA2F;AAAA,IACnG,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,IACrC,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,SAAQ,IAAG,MAAK;AAAA,KAC3C;AAEJ;AAEA,SAAS,SAAS,EAAE,UAAU,GAA2B;AACvD,SACE,gBAAAC,OAAC,SAAI,WAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAa,GAAG,eAAc,SAAQ,gBAAe,SACpI;AAAA,oBAAAD,MAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,MAAK;AAAA,IAC/B,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK;AAAA,IACtC,gBAAAA,MAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,SAAQ,IAAG,KAAI;AAAA,KACzC;AAEJ;AAEA,SAAS,UAAU,EAAE,UAAU,GAA2B;AACxD,SACE,gBAAAC,OAAC,SAAI,WAAsB,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAa,GAAG,eAAc,SAAQ,gBAAe,SACpI;AAAA,oBAAAD,MAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK;AAAA,IACpC,gBAAAA,MAAC,UAAK,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK;AAAA,KACtC;AAEJ;AAMA,IAAM,eAAeL,eAAwC,IAAI;AAE1D,SAAS,WAA8B;AAC5C,QAAM,MAAMC,YAAW,YAAY;AACnC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4CAA4C;AACtE,SAAO;AACT;AAkBO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,WAAW;AAAA,EACX,YAAY;AACd,GAA2C;AACzC,QAAM,CAAC,QAAQ,SAAS,IAAIC,WAAkB,CAAC,CAAC;AAEhD,QAAM,UAAUC,cAAY,CAAC,OAAe;AAC1C,cAAU,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EACrD,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA,cAAY,MAAM;AACnC,cAAU,CAAC,CAAC;AAAA,EACd,GAAG,CAAC,CAAC;AAEL,QAAM,WAAWA;AAAA,IACf,CAAC,YAA+B;AAC9B,YAAM,KAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AAC7C,YAAM,WAAW,QAAQ,YAAY;AAErC,gBAAU,CAAC,SAAS;AAClB,cAAM,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,CAAC;AACzC,eAAO,KAAK,MAAM,CAAC,SAAS;AAAA,MAC9B,CAAC;AAED,UAAI,WAAW,GAAG;AAChB,mBAAW,MAAM,QAAQ,EAAE,GAAG,QAAQ;AAAA,MACxC;AAAA,IACF;AAAA,IACA,CAAC,SAAS,SAAS;AAAA,EACrB;AAEA,QAAM,QAAQA;AAAA,IACZ,CAAC,YAA+B,SAAS,OAAO;AAAA,IAChD,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,UAAUA;AAAA,IACd,CAAC,OAAe,gBACd,SAAS,EAAE,MAAM,WAAW,OAAO,YAAY,CAAC;AAAA,IAClD,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,QAAQA;AAAA,IACZ,CAAC,OAAe,gBACd,SAAS,EAAE,MAAM,SAAS,OAAO,YAAY,CAAC;AAAA,IAChD,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,UAAUA;AAAA,IACd,CAAC,OAAe,gBACd,SAAS,EAAE,MAAM,WAAW,OAAO,YAAY,CAAC;AAAA,IAClD,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,OAAOA;AAAA,IACX,CAAC,OAAe,gBACd,SAAS,EAAE,MAAM,QAAQ,OAAO,YAAY,CAAC;AAAA,IAC/C,CAAC,QAAQ;AAAA,EACX;AAEA,QAAM,kBAA0C;AAAA,IAC9C,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,iBAAiB;AAAA,EACnB;AAEA,SACE,gBAAAG;AAAA,IAAC,aAAa;AAAA,IAAb;AAAA,MACC,OAAO,EAAE,QAAQ,OAAO,SAAS,OAAO,SAAS,MAAM,SAAS,WAAW;AAAA,MAE1E;AAAA;AAAA,QAGD,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,qCAAqC,gBAAgB,QAAQ,CAAC;AAAA,YAExE,iBAAO,IAAI,CAAC,MACX,gBAAAA,MAAC,aAAqB,OAAO,GAAG,WAAW,MAAM,QAAQ,EAAE,EAAE,KAA7C,EAAE,EAA8C,CACjE;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAYA,IAAM,eAAe;AAAA,EACnB,SAAS,EAAE,MAAM,iBAAiB,QAAQ,cAAc,MAAM,eAAe;AAAA,EAC7E,OAAS,EAAE,MAAM,iBAAiB,QAAQ,kBAAkB,MAAM,mBAAmB;AAAA,EACrF,SAAS,EAAE,MAAM,mBAAmB,QAAQ,cAAc,MAAM,eAAe;AAAA,EAC/E,MAAS,EAAE,MAAM,UAAU,QAAQ,WAAW,MAAM,YAAY;AAClE;AAOA,SAAS,UAAU,EAAE,OAAO,UAAU,GAAuC;AAC3E,QAAM,EAAE,MAAAE,OAAM,QAAQ,KAAK,IAAI,aAAa,MAAM,IAAI;AACtD,QAAM,CAAC,SAAS,UAAU,IAAIL,WAAS,KAAK;AAG5C,EAAAE,YAAU,MAAM;AACd,QAAI,SAAS;AACX,YAAM,QAAQ,WAAW,WAAW,GAAG;AACvC,aAAO,MAAM,aAAa,KAAK;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,SAAS,SAAS,CAAC;AAEvB,SACE,gBAAAE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA;AAAA;AAAA;AAAA,UAIP,UACE,6DACA,yDACJ;AAAA;AAAA,MAEF,MAAK;AAAA,MAGL;AAAA,wBAAAD,MAAC,UAAK,WAAW,qCAAqC,MAAM,IAAI,eAAW,MAAC;AAAA,QAC5E,gBAAAA,MAACE,OAAA,EAAK,WAAW,2BAA2B,IAAI,IAAI;AAAA,QACpD,gBAAAD,OAAC,SAAI,WAAU,kBACb;AAAA,0BAAAD,MAAC,OAAE,WAAU,yCAAyC,gBAAM,OAAM;AAAA,UACjE,MAAM,eACL,gBAAAA,MAAC,OAAE,WAAU,qDACV,gBAAM,aACT;AAAA,WAEJ;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,WAAW,IAAI;AAAA,YAC9B,WAAU;AAAA,YACV,cAAW;AAAA,YAEX,0BAAAA,MAAC,aAAU,WAAU,eAAc;AAAA;AAAA,QACrC;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACzRA,SAAS,UAAU,QAAQ,OAAO,MAAM,YAAY,OAAO,mBAAmB;AAkCpE,gBAAAG,OAUE,QAAAC,cAVF;AAbH,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,GAAG;AACL,GAAiC;AAC/B,SACE,gBAAAA,OAAC,SAAI,WAAW,GAAG,oEAAoE,SAAS,GAAI,GAAG,MACpG;AAAA,YACC,gBAAAD,MAAC,SAAI,WAAU,gGACb,0BAAAA,MAAC,UAAK,WAAU,yBAAyB,gBAAK,GAChD;AAAA,IAEF,gBAAAA,MAAC,QAAG,WAAU,8CAA8C,iBAAM;AAAA,IACjE,eACC,gBAAAA,MAAC,OAAE,WAAU,+CAA+C,uBAAY;AAAA,KAExE,UAAU,oBACV,gBAAAC,OAAC,SAAI,WAAU,2BACZ;AAAA,gBACC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,OAAO;AAAA,UAChB,WAAU;AAAA,UAEV;AAAA,4BAAAD,MAAC,QAAK,WAAU,WAAU;AAAA,YACzB,OAAO;AAAA;AAAA;AAAA,MACV;AAAA,MAED,mBACC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,gBAAgB;AAAA,UACzB,WAAU;AAAA,UAET,0BAAgB;AAAA;AAAA,MACnB;AAAA,OAEJ;AAAA,KAEJ;AAEJ;AAcO,SAAS,WAAW,EAAE,QAAQ,UAAU,GAAwC;AACrF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,SAAM,WAAU,WAAU;AAAA,MACjC,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,QAAQ,SAAS,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,IAAI;AAAA,MACpE;AAAA;AAAA,EACF;AAEJ;AAOO,SAAS,YAAY,EAAE,OAAO,SAAS,UAAU,GAAkC;AACxF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,UAAO,WAAU,WAAU;AAAA,MAClC,OAAM;AAAA,MACN,aAAa,QAAQ,mBAAmB,KAAK,oCAAoC;AAAA,MACjF,iBAAiB,UAAU,EAAE,OAAO,gBAAgB,SAAS,QAAQ,IAAI;AAAA,MACzE;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,eAAe,EAAE,QAAQ,UAAU,GAAwC;AACzF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,YAAS,WAAU,WAAU;AAAA,MACpC,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,QAAQ,SAAS,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,IAAI;AAAA,MACpE;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,cAAc,EAAE,QAAQ,UAAU,GAAwC;AACxF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,cAAW,WAAU,WAAU;AAAA,MACtC,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,QAAQ,SAAS,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,IAAI;AAAA,MACpE;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,UAAU,EAAE,QAAQ,UAAU,GAAwC;AACpF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,SAAM,WAAU,WAAU;AAAA,MACjC,OAAM;AAAA,MACN,aAAY;AAAA,MACZ,QAAQ,SAAS,EAAE,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,IAAI;AAAA,MACpE;AAAA;AAAA,EACF;AAEJ;AAOO,SAAS,WAAW,EAAE,OAAO,SAAS,UAAU,GAAiC;AACtF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,gBAAAA,MAAC,eAAY,WAAU,4BAA2B;AAAA,MACxD,OAAM;AAAA,MACN,aAAa,SAAS;AAAA,MACtB,QAAQ,UAAU,EAAE,OAAO,aAAa,SAAS,QAAQ,IAAI;AAAA,MAC7D;AAAA;AAAA,EACF;AAEJ;;;AC/JA,YAAYE,aAAW;AACvB,YAAY,qBAAqB;AACjC,SAAS,SAAS;AAgBhB,gBAAAC,OA0BI,QAAAC,cA1BJ;AAZF,IAAM,SAAyB;AAE/B,IAAM,gBAAgC;AAEtC,IAAM,eAA+B;AAErC,IAAM,cAA8B;AAEpC,IAAM,gBAAsB,mBAG1B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAD;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,cAAc,cAA8B,wBAAQ;AAEpD,IAAM,gBAAsB,mBAG1B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QACpC,gBAAAC,OAAC,gBACC;AAAA,kBAAAD,MAAC,iBAAc;AAAA,EACf,gBAAAC;AAAA,IAAiB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACD,gBAAAA,OAAiB,uBAAhB,EAAsB,WAAU,qRAC/B;AAAA,0BAAAD,MAAC,KAAE,WAAU,WAAU;AAAA,UACvB,gBAAAA,MAAC,UAAK,WAAU,WAAU,mBAAK;AAAA,WACjC;AAAA;AAAA;AAAA,EACF;AAAA,GACF,CACD;AACD,cAAc,cAA8B,wBAAQ;AAEpD,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA,GAAG;AACL,MACE,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN;AAEF,aAAa,cAAc;AAE3B,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA,GAAG;AACL,MACE,gBAAAA;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN;AAEF,aAAa,cAAc;AAE3B,IAAM,cAAoB,mBAGxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,YAAY,cAA8B,sBAAM;AAEhD,IAAM,oBAA0B,mBAG9B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAiB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,IACvD,GAAG;AAAA;AACN,CACD;AACD,kBAAkB,cAA8B,4BAAY;;;AC1G5D,YAAYE,aAAW;AACvB,YAAY,2BAA2B;AACvC,SAAS,SAAAC,QAAO,cAAc,cAAc;AAsB1C,SAUE,OAAAC,OAVF,QAAAC,cAAA;AAlBF,IAAM,eAAqC;AAE3C,IAAM,sBAA4C;AAElD,IAAM,oBAA0C;AAEhD,IAAM,qBAA2C;AAEjD,IAAM,kBAAwC;AAE9C,IAAM,yBAA+C;AAErD,IAAM,yBAA+B,mBAKnC,CAAC,EAAE,WAAW,OAAO,UAAU,GAAG,MAAM,GAAG,QAC3C,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEH;AAAA;AAAA,MACD,gBAAAD,MAAC,gBAAa,WAAU,WAAU;AAAA;AAAA;AACpC,CACD;AACD,uBAAuB,cACC,iCAAW;AAEnC,IAAM,yBAA+B,mBAGnC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,uBAAuB,cACC,iCAAW;AAEnC,IAAM,sBAA4B,mBAGhC,CAAC,EAAE,WAAW,aAAa,GAAG,GAAG,MAAM,GAAG,QAC1C,gBAAAA,MAAuB,8BAAtB,EACC,0BAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,GACF,CACD;AACD,oBAAoB,cAAoC,8BAAQ;AAEhE,IAAM,mBAAyB,mBAK7B,CAAC,EAAE,WAAW,OAAO,GAAG,MAAM,GAAG,QACjC,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,iBAAiB,cAAoC,2BAAK;AAE1D,IAAM,2BAAiC,mBAGrC,CAAC,EAAE,WAAW,UAAU,SAAS,GAAG,MAAM,GAAG,QAC7C,gBAAAC;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,sBAAAD,MAAC,UAAK,WAAU,gEACd,0BAAAA,MAAuB,qCAAtB,EACC,0BAAAA,MAACE,QAAA,EAAM,WAAU,WAAU,GAC7B,GACF;AAAA,MACC;AAAA;AAAA;AACH,CACD;AACD,yBAAyB,cACD,mCAAa;AAErC,IAAM,wBAA8B,mBAGlC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QACpC,gBAAAD;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ;AAAA,sBAAAD,MAAC,UAAK,WAAU,gEACd,0BAAAA,MAAuB,qCAAtB,EACC,0BAAAA,MAAC,UAAO,WAAU,wBAAuB,GAC3C,GACF;AAAA,MACC;AAAA;AAAA;AACH,CACD;AACD,sBAAsB,cAAoC,gCAAU;AAEpE,IAAM,oBAA0B,mBAK9B,CAAC,EAAE,WAAW,OAAO,GAAG,MAAM,GAAG,QACjC,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,kBAAkB,cAAoC,4BAAM;AAE5D,IAAM,wBAA8B,mBAGlC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B,gBAAAA;AAAA,EAAuB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,4BAA4B,SAAS;AAAA,IAClD,GAAG;AAAA;AACN,CACD;AACD,sBAAsB,cAAoC,gCAAU;AAEpE,IAAM,uBAAuB,CAAC;AAAA,EAC5B;AAAA,EACA,GAAG;AACL,MAA6C;AAC3C,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,8CAA8C,SAAS;AAAA,MACpE,GAAG;AAAA;AAAA,EACN;AAEJ;AACA,qBAAqB,cAAc;;;ACpLnC,YAAYG,aAAW;AACvB,YAAY,sBAAsB;AAe9B,gBAAAC,aAAA;AAXJ,IAAM,kBAAmC;AAEzC,IAAM,UAA2B;AAEjC,IAAM,iBAAkC;AAExC,IAAM,iBAAuB,mBAG3B,CAAC,EAAE,WAAW,aAAa,GAAG,GAAG,MAAM,GAAG,QAC1C,gBAAAA,MAAkB,yBAAjB,EACC,0BAAAA;AAAA,EAAkB;AAAA,EAAjB;AAAA,IACC;AAAA,IACA;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA;AACN,GACF,CACD;AACD,eAAe,cAA+B,yBAAQ;;;ACmBhD,gBAAAC,OA0HA,QAAAC,cA1HA;AAhBC,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAA4B;AAC1B,QAAM,QAAQ;AAAA,IACZ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE,gBAAAD,MAAC,UAAO,MAAY,cAAc,CAAC,MAAM;AAAE,QAAI,CAAC,EAAG,SAAQ;AAAA,EAAE,GAC3D,0BAAAA,MAAC,iBAAc,oBAAkB,QAAW,WAAW,GAAG,MAAM,IAAI,GAAG,8BAA8B,SAAS,GAC3G,UACH,GACF;AAEJ;AAYA,SAAS,YAAY,EAAE,UAAU,YAAY,GAAG,GAAkC;AAChF,SACE,gBAAAA,MAAC,gBAAQ,WACN,UACH;AAEJ;AAWA,SAAS,WAAW,EAAE,UAAU,YAAY,GAAG,GAAiC;AAC9E,SACE,gBAAAA,MAAC,eAAO,WACL,UACH;AAEJ;AAWA,SAAS,iBAAiB,EAAE,UAAU,YAAY,GAAG,GAAuC;AAC1F,SACE,gBAAAA,MAAC,qBAAa,WACX,UACH;AAEJ;AAWA,SAAS,UAAU,EAAE,UAAU,YAAY,GAAG,GAAgC;AAC5E,SACE,gBAAAA,MAAC,SAAI,WAAW,GAAG,+BAA+B,SAAS,GACxD,UACH;AAEJ;AAWA,SAAS,YAAY,EAAE,UAAU,YAAY,GAAG,GAAkC;AAChF,SACE,gBAAAA,MAAC,gBAAQ,WACN,UACH;AAEJ;AAkBO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AACZ,GAAmC;AACjC,SACE,gBAAAC,OAAC,SAAM,MAAY,SAAkB,MAAK,MACxC;AAAA,oBAAAA,OAAC,MAAM,QAAN,EACC;AAAA,sBAAAD,MAAC,MAAM,OAAN,EAAa,iBAAM;AAAA,MACnB,eAAe,gBAAAA,MAAC,MAAM,aAAN,EAAmB,uBAAY;AAAA,OAClD;AAAA,IACA,gBAAAC,OAAC,MAAM,QAAN,EACC;AAAA,sBAAAD,MAAC,UAAO,SAAQ,SAAQ,SAAS,SAAS,UAAU,SACjD,sBACH;AAAA,MACA,gBAAAA,MAAC,UAAO,SAAkB,SAAS,WAAW,SAC3C,uBACH;AAAA,OACF;AAAA,KACF;AAEJ;AAMA,MAAM,SAAS;AACf,MAAM,QAAQ;AACd,MAAM,cAAc;AACpB,MAAM,OAAO;AACb,MAAM,SAAS;;;AChMf,YAAYE,aAAW;AACvB,SAAS,UAAAC,SAAQ,KAAAC,UAAS;AAWpB,SACE,OAAAC,OADF,QAAAC,cAAA;AAHN,IAAM,cAAoB;AAAA,EACxB,CAAC,EAAE,WAAW,SAAS,OAAO,GAAG,MAAM,GAAG,QAAQ;AAChD,WACE,gBAAAA,OAAC,SAAI,WAAU,YACb;AAAA,sBAAAD,MAACE,SAAA,EAAO,WAAU,0EAAyE;AAAA,MAC3F,gBAAAF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,MAAK;AAAA,UACL,WAAW,GAAG,aAAa,SAAS;AAAA,UACpC;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA,MACC,SAAS,WACR,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UAEV,0BAAAA,MAACG,IAAA,EAAE,WAAU,WAAU;AAAA;AAAA,MACzB;AAAA,OAEJ;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;","names":["Fragment","jsx","jsxs","useEffect","useRef","Fragment","jsx","useRef","useEffect","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","createContext","useContext","useEffect","useState","useCallback","useRef","useMemo","useRef","jsx","Fragment","jsx","createContext","useContext","useState","useRef","useCallback","useEffect","useMemo","useEffect","useState","useCallback","useRef","useMemo","Fragment","jsx","jsxs","recordMatchesWhere","useRef","useState","useCallback","useEffect","useMemo","useMemo","useMemo","useEffect","useCallback","useRef","useMemo","useContext","useContext","useMemo","useRef","useEffect","useCallback","useCallback","useContext","useMemo","useContext","useCallback","useMemo","useEffect","useMemo","useEffect","useMemo","useState","useEffect","useCallback","useRef","Y","useState","useRef","useEffect","msgDocKey","payload","useCallback","useMemo","useCallback","useMemo","useCallback","useEffect","useCallback","useState","useState","useEffect","useCallback","u","useState","useEffect","useCallback","useRef","useMemo","Y","useState","useRef","useMemo","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useCallback","useState","useMemo","useState","useMemo","useCallback","useCallback","useMemo","useMemo","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useMemo","useCallback","useMemo","useCallback","useMemo","useRef","useRef","useMemo","useCallback","useCallback","useMemo","useMemo","useCallback","useCallback","useCallback","useEffect","r","g","b","Fragment","jsx","useEffect","useState","useEffect","createContext","useContext","useState","useEffect","useRef","useCallback","jsx","createContext","useContext","useEffect","useState","useRef","useCallback","useState","useEffect","useRef","useRef","useState","useEffect","DEFAULT_TIMEOUT_MS","useCallback","useEffect","useState","useState","useCallback","useEffect","jsx","jsxs","useCallback","useEffect","useMemo","useState","authedJson","useState","useCallback","useEffect","useMemo","React","jsx","React","jsx","React","jsx","React","jsx","React","jsx","jsxs","React","jsx","React","jsx","React","jsx","jsxs","React","Check","jsx","Check","React","jsx","React","cva","jsx","cva","Label","cva","jsx","cva","React","jsx","React","jsx","jsx","jsxs","_","jsx","jsxs","React","cva","jsx","cva","createContext","useContext","useState","useCallback","useEffect","jsx","jsxs","Icon","jsx","jsxs","React","jsx","jsxs","React","Check","jsx","jsxs","Check","React","jsx","jsx","jsxs","React","Search","X","jsx","jsxs","Search","X"]}
1
+ {"version":3,"sources":["../src/shared/env/index.ts","../src/shared/roles.ts","../src/shared/protocol/yjs.ts","../src/shared/protocol/constants.ts","../src/shared/protocol/messages.ts","../src/client/auth/DeepSpaceAuthProvider.tsx","../src/client/auth/client.ts","../src/client/auth/token.ts","../src/client/auth/hooks.ts","../src/client/auth/AuthOverlay.tsx","../src/client/auth/helpers.tsx","../src/client/auth/GuestBanner.tsx","../src/client/storage/context.tsx","../src/client/storage/store.ts","../src/client/storage/ScopeRegistry.tsx","../src/client/storage/serverErrors.ts","../src/client/storage/RecordScope.tsx","../src/client/storage/ws-log.ts","../src/client/storage/hooks/useUser.ts","../src/client/storage/hooks/useQuery.ts","../src/client/storage/hooks/useMutations.ts","../src/client/storage/hooks/useUsers.ts","../src/client/storage/hooks/useYjs.ts","../src/client/storage/hooks/useUserLookup.ts","../src/client/storage/hooks/usePresence.ts","../src/client/storage/hooks/useYjsRoom.ts","../src/client/storage/hooks/useGameRoom.ts","../src/client/storage/hooks/useCanvas.ts","../src/client/storage/hooks/useCronMonitor.ts","../src/client/storage/hooks/useJobs.ts","../src/client/storage/hooks/usePresenceRoom.ts","../src/client/storage/connection-status.ts","../src/client/storage/useR2Files.ts","../src/client/storage/file-attachment-utils.ts","../src/client/storage/user-color.ts","../src/client/messaging/useMessages.ts","../src/client/messaging/useChannels.ts","../src/client/messaging/useReactions.ts","../src/client/messaging/useChannelMembers.ts","../src/client/messaging/useReadReceipts.ts","../src/client/messaging/useConversation.ts","../src/client/messaging/utils.ts","../src/client/messaging/conversation-utils.ts","../src/client/messaging/message-utils.ts","../src/client/directory/useConversations.ts","../src/client/directory/useCommunities.ts","../src/client/directory/usePosts.ts","../src/client/theme/DeepSpaceThemeProvider.tsx","../src/client/theme/applyTheme.ts","../src/client/theme/useIsDarkTheme.ts","../src/client/platform/PlatformProvider.tsx","../src/client/platform/usePlatformWS.ts","../src/client/integration/index.ts","../src/client/ai-stream.ts","../src/client/subscriptions/useSubscription.ts","../src/shared/subscription.ts","../src/client/subscriptions/PricingTable.tsx","../src/client/charges/useCheckout.ts","../src/ui/utils.ts","../src/ui/Card.tsx","../src/ui/Separator.tsx","../src/ui/Table.tsx","../src/ui/Tabs.tsx","../src/ui/Button.tsx","../src/ui/Input.tsx","../src/ui/Textarea.tsx","../src/ui/Select.tsx","../src/ui/Checkbox.tsx","../src/ui/Switch.tsx","../src/ui/Label.tsx","../src/ui/Badge.tsx","../src/ui/Avatar.tsx","../src/ui/Progress.tsx","../src/ui/Skeleton.tsx","../src/ui/CardGrid.tsx","../src/ui/Alert.tsx","../src/ui/Toast.tsx","../src/ui/EmptyState.tsx","../src/ui/Dialog.tsx","../src/ui/DropdownMenu.tsx","../src/ui/Tooltip.tsx","../src/ui/Modal.tsx","../src/ui/SearchInput.tsx"],"sourcesContent":["/**\n * Environment detection and URL configuration\n *\n * Determines environment and provides URLs for DeepSpace services.\n *\n * Environment detection priority:\n * 1. Build-time __DEEPSPACE_ENV__ define (set via esbuild/Vite)\n * 2. Runtime window.__DEEPSPACE_ENV__\n * 3. Server-side process.env.DEEPSPACE_ENV\n * 4. Hostname detection (fallback)\n */\n\nexport type Environment = 'dev' | 'prod'\n\ndeclare const __DEEPSPACE_ENV__: string | undefined\n\n// ============================================================================\n// Environment Configuration\n// ============================================================================\n\ninterface EnvironmentConfig {\n name: Environment\n /** Platform API worker URL */\n apiUrl: string\n /** Platform worker URL (RecordRoom, schema registry) */\n platformWorkerUrl: string\n /** Auth worker URL (Better Auth) */\n authUrl: string\n /** Auth sign-in page URL */\n authSignInUrl: string\n /** Auth sign-up page URL */\n authSignUpUrl: string\n /** Main DeepSpace app URL */\n mainAppUrl: string\n /** Builder dashboard URL */\n dashboardUrl: string\n}\n\nconst DEV_CONFIG: EnvironmentConfig = {\n name: 'dev',\n apiUrl: 'http://localhost:8795',\n platformWorkerUrl: 'http://localhost:8792',\n authUrl: 'http://localhost:8794',\n authSignInUrl: 'http://localhost:5173/sign-in',\n authSignUpUrl: 'http://localhost:5173/sign-up',\n mainAppUrl: 'http://localhost:5173',\n dashboardUrl: 'http://localhost:5174',\n}\n\nconst PROD_CONFIG: EnvironmentConfig = {\n name: 'prod',\n apiUrl: 'https://api-worker.deep.space',\n platformWorkerUrl: 'https://platform-worker.deep.space',\n authUrl: 'https://auth.deep.space',\n authSignInUrl: 'https://auth.deep.space/login/social',\n authSignUpUrl: 'https://auth.deep.space/login/social',\n mainAppUrl: 'https://deep.space',\n dashboardUrl: 'https://dashboard.deep.space',\n}\n\n// ============================================================================\n// Environment Detection\n// ============================================================================\n\nlet cachedEnvironment: Environment | null = null\n\nfunction parseEnv(value: string | undefined): Environment | null {\n if (!value) return null\n const v = value.toLowerCase()\n if (v === 'dev' || v === 'development') return 'dev'\n if (v === 'prod' || v === 'production') return 'prod'\n return null\n}\n\nexport function detectEnvironment(): Environment {\n if (cachedEnvironment) return cachedEnvironment\n\n // 1. Build-time define\n if (typeof __DEEPSPACE_ENV__ !== 'undefined') {\n const env = parseEnv(__DEEPSPACE_ENV__)\n if (env) {\n cachedEnvironment = env\n return env\n }\n }\n\n // 2. Runtime window variable\n if (typeof window !== 'undefined') {\n const windowEnv = (window as { __DEEPSPACE_ENV__?: string }).__DEEPSPACE_ENV__\n const env = parseEnv(windowEnv)\n if (env) {\n cachedEnvironment = env\n return env\n }\n }\n\n // 3. Server-side env var\n if (typeof window === 'undefined') {\n try {\n const env = parseEnv(process.env.DEEPSPACE_ENV)\n if (env) {\n cachedEnvironment = env\n return env\n }\n if (process.env.NODE_ENV !== 'production') {\n cachedEnvironment = 'dev'\n return 'dev'\n }\n } catch {\n // process may not exist in Workers\n }\n }\n\n // 4. Hostname detection\n if (typeof window !== 'undefined') {\n const hostname = window.location.hostname\n\n if (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname.startsWith('192.168.')\n ) {\n cachedEnvironment = 'dev'\n return 'dev'\n }\n\n // Production: app.space, *.app.space, deep.space, *.deep.space\n if (\n hostname === 'app.space' ||\n hostname.endsWith('.app.space') ||\n hostname === 'deep.space' ||\n hostname.endsWith('.deep.space')\n ) {\n cachedEnvironment = 'prod'\n return 'prod'\n }\n }\n\n // Default to prod for unknown domains\n cachedEnvironment = 'prod'\n return 'prod'\n}\n\nexport function getEnvironmentConfig(): EnvironmentConfig {\n const env = detectEnvironment()\n return env === 'dev' ? DEV_CONFIG : PROD_CONFIG\n}\n\n// ============================================================================\n// Convenience Getters\n// ============================================================================\n\nexport function getApiUrl(): string {\n return getEnvironmentConfig().apiUrl\n}\n\nexport function getPlatformWorkerUrl(): string {\n return getEnvironmentConfig().platformWorkerUrl\n}\n\nexport function getAuthUrl(): string {\n return getEnvironmentConfig().authUrl\n}\n\nexport function isLocalDev(): boolean {\n return detectEnvironment() === 'dev'\n}\n\nexport function isProduction(): boolean {\n return detectEnvironment() === 'prod'\n}\n\n/** Reset cached environment (useful for testing) */\nexport function resetEnvironmentCache(): void {\n cachedEnvironment = null\n}\n\n// ============================================================================\n// Convenience Object\n// ============================================================================\n\nexport const ENV = {\n get current() {\n return detectEnvironment()\n },\n get config() {\n return getEnvironmentConfig()\n },\n get apiUrl() {\n return getApiUrl()\n },\n get platformWorkerUrl() {\n return getPlatformWorkerUrl()\n },\n get authUrl() {\n return getAuthUrl()\n },\n get isLocal() {\n return isLocalDev()\n },\n get isProd() {\n return isProduction()\n },\n} as const\n","/**\n * Standard DeepSpace role constants.\n *\n * Every DeepSpace app uses the same three roles.\n * Apps can import these instead of defining them locally.\n */\n\nexport const ROLES = {\n VIEWER: 'viewer',\n MEMBER: 'member',\n ADMIN: 'admin',\n} as const\n\nexport type Role = (typeof ROLES)[keyof typeof ROLES]\n\nexport const ROLE_CONFIG: Record<Role, { title: string; badgeVariant: string; description: string }> = {\n viewer: { title: 'Viewer', badgeVariant: 'secondary', description: 'Read-only access' },\n member: { title: 'Member', badgeVariant: 'default', description: 'Can create and edit own content' },\n admin: { title: 'Admin', badgeVariant: 'warning', description: 'Full access to all features' },\n}\n","/**\n * Yjs Sync Protocol Implementation\n * \n * This implements the y-protocols sync and awareness protocols without\n * depending on y-websocket internal paths. Makes it easier to bundle\n * and template.\n * \n * Protocol spec: https://github.com/yjs/y-protocols\n */\n\nimport * as Y from 'yjs'\n\n// Message type constants\nexport const MSG_SYNC = 0\nexport const MSG_AWARENESS = 1\n\n// Sync message subtypes\nexport const MSG_SYNC_STEP1 = 0 // Send state vector\nexport const MSG_SYNC_STEP2 = 1 // Send diff based on received state vector\nexport const MSG_SYNC_UPDATE = 2 // Send incremental update\n\n// ============================================================================\n// Binary Encoding Utilities (lib0 compatible)\n// ============================================================================\n\nexport function createEncoder(): { data: number[] } {\n return { data: [] }\n}\n\nexport function toUint8Array(encoder: { data: number[] }): Uint8Array {\n return new Uint8Array(encoder.data)\n}\n\nexport function writeVarUint(encoder: { data: number[] }, num: number): void {\n while (num > 0x7f) {\n encoder.data.push((num & 0x7f) | 0x80)\n num = Math.floor(num / 128)\n }\n encoder.data.push(num & 0x7f)\n}\n\nexport function writeVarUint8Array(encoder: { data: number[] }, arr: Uint8Array): void {\n writeVarUint(encoder, arr.length)\n for (let i = 0; i < arr.length; i++) {\n encoder.data.push(arr[i])\n }\n}\n\nexport function createDecoder(data: Uint8Array): { data: Uint8Array; pos: number } {\n return { data, pos: 0 }\n}\n\nexport function readVarUint(decoder: { data: Uint8Array; pos: number }): number {\n let num = 0\n let mult = 1\n const len = decoder.data.length\n while (decoder.pos < len) {\n const byte = decoder.data[decoder.pos++]\n num += (byte & 0x7f) * mult\n mult *= 128\n if (byte < 0x80) {\n return num\n }\n }\n throw new Error('Unexpected end of buffer')\n}\n\nexport function readVarUint8Array(decoder: { data: Uint8Array; pos: number }): Uint8Array {\n const len = readVarUint(decoder)\n const arr = decoder.data.subarray(decoder.pos, decoder.pos + len)\n decoder.pos += len\n return arr\n}\n\nexport function hasContent(decoder: { data: Uint8Array; pos: number }): boolean {\n return decoder.pos < decoder.data.length\n}\n\n// ============================================================================\n// Sync Protocol\n// ============================================================================\n\n/**\n * Encode sync step 1: our state vector\n */\nexport function encodeSyncStep1(doc: Y.Doc): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_STEP1)\n writeVarUint8Array(encoder, Y.encodeStateVector(doc))\n return toUint8Array(encoder)\n}\n\n/**\n * Encode sync step 2: diff based on received state vector\n */\nexport function encodeSyncStep2(doc: Y.Doc, stateVector: Uint8Array): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_STEP2)\n writeVarUint8Array(encoder, Y.encodeStateAsUpdate(doc, stateVector))\n return toUint8Array(encoder)\n}\n\n/**\n * Encode an incremental update\n */\nexport function encodeUpdate(update: Uint8Array): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_SYNC)\n writeVarUint(encoder, MSG_SYNC_UPDATE)\n writeVarUint8Array(encoder, update)\n return toUint8Array(encoder)\n}\n\nexport interface SyncResult {\n type: 'step1' | 'step2' | 'update'\n response?: Uint8Array\n stateVector?: Uint8Array\n update?: Uint8Array\n}\n\n/**\n * Handle an incoming sync message\n * Returns response to send (if any) and whether this was an update\n */\nexport function handleSyncMessage(doc: Y.Doc, data: Uint8Array): SyncResult {\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n \n if (messageType !== MSG_SYNC) {\n throw new Error(`Expected sync message (${MSG_SYNC}), got ${messageType}`)\n }\n \n const syncType = readVarUint(decoder)\n \n switch (syncType) {\n case MSG_SYNC_STEP1: {\n // Received state vector, send our diff\n const stateVector = readVarUint8Array(decoder)\n const response = encodeSyncStep2(doc, stateVector)\n return { type: 'step1', response, stateVector }\n }\n \n case MSG_SYNC_STEP2: {\n // Received diff, apply it\n const update = readVarUint8Array(decoder)\n Y.applyUpdate(doc, update)\n return { type: 'step2', update }\n }\n \n case MSG_SYNC_UPDATE: {\n // Received incremental update, apply it\n const update = readVarUint8Array(decoder)\n Y.applyUpdate(doc, update)\n return { type: 'update', update }\n }\n \n default:\n throw new Error(`Unknown sync type: ${syncType}`)\n }\n}\n\n// ============================================================================\n// Awareness Protocol\n// ============================================================================\n\nexport interface AwarenessState {\n [key: string]: unknown\n}\n\nexport interface AwarenessStates {\n [clientId: number]: AwarenessState\n}\n\n/**\n * Simple awareness implementation for presence/cursors\n */\nexport class Awareness {\n doc: Y.Doc\n clientID: number\n states: Map<number, AwarenessState> = new Map()\n private meta: Map<number, { clock: number; lastUpdated: number }> = new Map()\n private updateListeners: Set<(changes: { added: number[]; updated: number[]; removed: number[] }) => void> = new Set()\n private changeListeners: Set<(changes: { added: number[]; updated: number[]; removed: number[] }) => void> = new Set()\n\n constructor(doc: Y.Doc) {\n this.doc = doc\n this.clientID = doc.clientID\n }\n \n getStates(): Map<number, AwarenessState> {\n return this.states\n }\n \n getLocalState(): AwarenessState | null {\n return this.states.get(this.clientID) || null\n }\n \n setLocalState(state: AwarenessState | null): void {\n const clientID = this.clientID\n const prevState = this.states.get(clientID)\n \n if (state === null) {\n this.states.delete(clientID)\n this.meta.delete(clientID)\n if (prevState) {\n this.emit({ added: [], updated: [], removed: [clientID] })\n }\n } else {\n const meta = this.meta.get(clientID) || { clock: 0, lastUpdated: Date.now() }\n meta.clock++\n meta.lastUpdated = Date.now()\n this.meta.set(clientID, meta)\n this.states.set(clientID, state)\n this.emit({\n added: prevState ? [] : [clientID],\n updated: prevState ? [clientID] : [],\n removed: [],\n })\n }\n }\n \n setLocalStateField(field: string, value: unknown): void {\n const state = this.getLocalState() || {}\n state[field] = value\n this.setLocalState(state)\n }\n \n on(event: 'update' | 'change', handler: (changes: { added: number[]; updated: number[]; removed: number[] }) => void): void {\n if (event === 'update') {\n this.updateListeners.add(handler)\n } else if (event === 'change') {\n this.changeListeners.add(handler)\n }\n }\n\n off(event: 'update' | 'change', handler: (changes: { added: number[]; updated: number[]; removed: number[] }) => void): void {\n if (event === 'update') {\n this.updateListeners.delete(handler)\n } else if (event === 'change') {\n this.changeListeners.delete(handler)\n }\n }\n\n private emit(changes: { added: number[]; updated: number[]; removed: number[] }): void {\n for (const handler of this.updateListeners) {\n handler(changes)\n }\n if (changes.added.length > 0 || changes.updated.length > 0 || changes.removed.length > 0) {\n for (const handler of this.changeListeners) {\n handler(changes)\n }\n }\n }\n \n /**\n * Encode awareness update for specific clients\n */\n encodeUpdate(clientIds?: number[]): Uint8Array {\n const ids = clientIds || Array.from(this.states.keys())\n const encoder = createEncoder()\n writeVarUint(encoder, ids.length)\n \n for (const clientId of ids) {\n const state = this.states.get(clientId)\n const meta = this.meta.get(clientId) || { clock: 0, lastUpdated: Date.now() }\n \n writeVarUint(encoder, clientId)\n writeVarUint(encoder, meta.clock)\n \n const stateStr = state ? JSON.stringify(state) : 'null'\n const stateBytes = new TextEncoder().encode(stateStr)\n writeVarUint8Array(encoder, stateBytes)\n }\n \n return toUint8Array(encoder)\n }\n \n /**\n * Apply awareness update from another client\n */\n applyUpdate(data: Uint8Array): { added: number[]; updated: number[]; removed: number[] } {\n const decoder = createDecoder(data)\n const len = readVarUint(decoder)\n \n const added: number[] = []\n const updated: number[] = []\n const removed: number[] = []\n \n for (let i = 0; i < len; i++) {\n const clientId = readVarUint(decoder)\n const clock = readVarUint(decoder)\n const stateBytes = readVarUint8Array(decoder)\n const stateStr = new TextDecoder().decode(stateBytes)\n const state = stateStr === 'null' ? null : JSON.parse(stateStr) as AwarenessState\n \n const prevMeta = this.meta.get(clientId)\n const prevState = this.states.get(clientId)\n \n // Only apply if this is a newer update\n if (!prevMeta || prevMeta.clock < clock) {\n this.meta.set(clientId, { clock, lastUpdated: Date.now() })\n \n if (state === null) {\n this.states.delete(clientId)\n if (prevState) {\n removed.push(clientId)\n }\n } else {\n this.states.set(clientId, state)\n if (prevState) {\n updated.push(clientId)\n } else {\n added.push(clientId)\n }\n }\n }\n }\n \n if (added.length > 0 || updated.length > 0 || removed.length > 0) {\n this.emit({ added, updated, removed })\n }\n \n return { added, updated, removed }\n }\n \n /**\n * Remove awareness states for disconnected clients\n */\n removeStates(clientIds: number[]): void {\n const removed: number[] = []\n for (const clientId of clientIds) {\n if (this.states.has(clientId)) {\n this.states.delete(clientId)\n this.meta.delete(clientId)\n removed.push(clientId)\n }\n }\n if (removed.length > 0) {\n this.emit({ added: [], updated: [], removed })\n }\n }\n}\n\n/**\n * Encode a full awareness message\n */\nexport function encodeAwarenessMessage(awareness: Awareness, clientIds?: number[]): Uint8Array {\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_AWARENESS)\n writeVarUint8Array(encoder, awareness.encodeUpdate(clientIds))\n return toUint8Array(encoder)\n}\n\n/**\n * Decode and apply awareness message\n */\nexport function handleAwarenessMessage(\n awareness: Awareness, \n data: Uint8Array\n): { added: number[]; updated: number[]; removed: number[] } {\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n \n if (messageType !== MSG_AWARENESS) {\n throw new Error(`Expected awareness message (${MSG_AWARENESS}), got ${messageType}`)\n }\n \n const update = readVarUint8Array(decoder)\n return awareness.applyUpdate(update)\n}\n\n/**\n * Get message type from raw data\n */\nexport function getMessageType(data: Uint8Array): number {\n const decoder = createDecoder(data)\n return readVarUint(decoder)\n}\n\n","/**\n * Wire protocol constants.\n *\n * The JSON WebSocket protocol uses dotted string identifiers (e.g.\n * `\"game.input\"`) as the `type` discriminator. All message types are\n * grouped under a single `MSG` object so imports stay tidy:\n *\n * import { MSG, dispatch, clientBuild } from 'deepspace'\n *\n * dispatch<ServerMessage>(raw, {\n * [MSG.GAME_STATE]: (p) => { ... },\n * [MSG.GAME_TICK]: (p) => { ... },\n * })\n *\n * Each key's value is the on-wire string — grep-friendly, self-\n * documenting, and infinite per namespace. Adding a new message is one\n * line here plus one arm in the discriminated union in `./messages.ts`.\n *\n * Yjs binary protocol constants (`MSG_YJS_SYNC`, `MSG_YJS_AWARENESS`) are\n * intentionally kept numeric and separate from `MSG` — they ride a\n * binary WebSocket frame format and aren't part of the JSON dispatcher.\n */\n\nexport const MSG = {\n // ---- Records / CRUD --------------------------------------------------\n SUBSCRIBE: 'core.subscribe',\n UNSUBSCRIBE: 'core.unsubscribe',\n QUERY_RESULT: 'core.query_result',\n RECORD_CHANGE: 'core.record_change',\n PUT: 'core.put',\n DELETE: 'core.delete',\n ERROR: 'core.error',\n\n // ---- Users -----------------------------------------------------------\n USER_INFO: 'user.info',\n USER_LIST: 'user.list',\n SET_ROLE: 'user.set_role',\n USER_UPDATE: 'user.update',\n\n // ---- Auth signal -----------------------------------------------------\n // Server → client one-shot on connect from rooms that enforce role-based\n // writes (Canvas, Game, Cron). Tells the client whether this connection\n // can write so its hook can disable local write APIs and the UI can\n // render controls accordingly. Without this, a viewer's click would\n // round-trip to the server and silently come back as ERROR.\n AUTH: 'auth',\n\n // ---- Yjs JSON control frames (binary sync lives in ./yjs.ts) ---------\n YJS_JOIN: 'yjs.join',\n YJS_LEAVE: 'yjs.leave',\n\n // ---- Records room misc -----------------------------------------------\n ACK: 'records.ack',\n LIST_SCHEMAS: 'records.list_schemas',\n RESUBSCRIBE: 'records.resubscribe',\n\n // ---- GameRoom --------------------------------------------------------\n GAME_STATE: 'game.state',\n GAME_INPUT: 'game.input',\n GAME_PLAYER_JOIN: 'game.player_join',\n GAME_PLAYER_LEAVE: 'game.player_leave',\n GAME_PLAYER_READY: 'game.player_ready',\n GAME_START: 'game.start',\n GAME_END: 'game.end',\n GAME_TICK: 'game.tick',\n\n // ---- CanvasRoom ------------------------------------------------------\n CANVAS_SHAPES: 'canvas.shapes',\n CANVAS_ADD: 'canvas.add',\n CANVAS_MOVE: 'canvas.move',\n CANVAS_RESIZE: 'canvas.resize',\n CANVAS_DELETE: 'canvas.delete',\n CANVAS_UPDATE: 'canvas.update',\n CANVAS_VIEWPORT: 'canvas.viewport',\n CANVAS_UNDO: 'canvas.undo',\n CANVAS_REDO: 'canvas.redo',\n\n // ---- CronRoom --------------------------------------------------------\n CRON_TASKS: 'cron.tasks',\n CRON_HISTORY: 'cron.history',\n CRON_TRIGGER: 'cron.trigger',\n CRON_PAUSE: 'cron.pause',\n CRON_RESUME: 'cron.resume',\n CRON_STATUS: 'cron.status',\n\n // ---- JobRoom ---------------------------------------------------------\n // Background-job queue with durable, alarm-driven execution. See\n // server/rooms/job-room.ts. Clients enqueue and subscribe to updates;\n // the room broadcasts JOB_UPDATE for every status transition.\n JOB_ENQUEUE: 'job.enqueue',\n JOB_CANCEL: 'job.cancel',\n JOB_RETRY: 'job.retry',\n JOB_UPDATE: 'job.update',\n\n // ---- PresenceRoom ----------------------------------------------------\n PRESENCE_SYNC: 'presence.sync',\n PRESENCE_JOIN: 'presence.join',\n PRESENCE_LEAVE: 'presence.leave',\n PRESENCE_UPDATE: 'presence.update',\n\n // ---- Gateway multiplexing --------------------------------------------\n GW_SCOPE_CONNECT: 'gateway.scope_connect',\n GW_SCOPE_DISCONNECT: 'gateway.scope_disconnect',\n GW_SCOPE_ERROR: 'gateway.scope_error',\n GW_TOKEN_REFRESH: 'gateway.token_refresh',\n GW_USER_UPDATE: 'gateway.user_update',\n} as const\n\n/**\n * Type of any message type constant — the union of every string literal\n * stored in `MSG`. Useful when declaring functions that accept \"any known\n * message type\" without enumerating all 54 strings by hand.\n */\nexport type MsgType = (typeof MSG)[keyof typeof MSG]\n\n// ---------------------------------------------------------------------------\n// Yjs binary protocol (NOT part of MSG — see header comment)\n// ---------------------------------------------------------------------------\n\n/** Outer envelope id for binary-framed yjs sync messages. Varuint-encoded. */\nexport const MSG_YJS_SYNC = 22\n/** Outer envelope id for binary-framed yjs awareness messages. Varuint-encoded. */\nexport const MSG_YJS_AWARENESS = 23\n\n// ---------------------------------------------------------------------------\n// Role names — not wire messages, just the string values the auth layer uses\n// as role identifiers.\n// ---------------------------------------------------------------------------\n\n/** Role assigned to unauthenticated WebSocket connections */\nexport const ROLE_ANONYMOUS = 'viewer'\n/** Default role for newly registered authenticated users */\nexport const ROLE_DEFAULT = 'member'\n/** Admin role */\nexport const ROLE_ADMIN = 'admin'\n","/**\n * Typed wire-protocol layer — discriminated unions, typed builders, and a\n * type-safe dispatcher for every `MSG.*` the SDK understands.\n *\n * Why this exists\n * ---------------\n *\n * The string `MSG.*` constants in `./constants.ts` are the authoritative\n * wire protocol, but using them directly is error-prone: a typo picks the\n * wrong message with the wrong payload shape and fails silently at\n * runtime. This module pairs every constant with its payload type, so\n * that:\n *\n * 1. Building a message with `clientBuild.gameInput(...)` is payload-\n * checked at the call site — the compiler refuses to ship a wrong\n * shape.\n *\n * 2. Parsing an inbound message via `dispatch(raw, handlers)` narrows the\n * payload type inside each handler automatically, replacing the\n * unsafe `switch (msg.type) { case MSG.X: (payload as any).foo }`\n * pattern.\n *\n * 3. Tightening `BaseRoom.sendTo` / `BaseRoom.broadcast` /\n * `HandlerContext.send` / `SubscriptionContext.send` to accept\n * `ServerMessage` turns the type layer into enforcement: any room\n * that ships a payload inconsistent with its declared arm fails to\n * compile. Without that, the discriminated union is documentation,\n * not contract.\n *\n * 4. Adding a new `MSG.*` is localized: one entry in the discriminated\n * union, one builder function, one handler key in every dispatcher\n * that cares. No grep-and-fix across the codebase.\n *\n * 5. Apps can extend the SDK protocol without forking: `dispatch<M>` is\n * generic over any `M extends ProtocolMessage`, and builders are\n * plain objects so apps compose via spread (`{ ...clientBuild,\n * myMessage: ... }`).\n *\n * Direction split\n * ---------------\n *\n * Some message types carry different payloads depending on who's sending.\n * `MSG.GAME_START`, for example, is `{}` when the client requests a start\n * but `{ state, tick }` when the server broadcasts the start event.\n * `MSG.CANVAS_ADD` is a flat shape dict on the way in and a `{ shape }`\n * wrapper on the way out. Modelling these with one union would force\n * handlers to juggle a union payload — clunky and error-prone. Instead we\n * split by direction:\n *\n * - `ClientMessage` — what the client sends to the server\n * - `ServerMessage` — what the server sends to the client\n * - `ProtocolMessage = ClientMessage | ServerMessage` (for code that\n * really doesn't care — avoid when possible)\n *\n * Each side gets its own builder (`clientBuild` / `serverBuild`) and each\n * side's dispatcher is parameterised with the union it expects.\n *\n * Payload strictness\n * ------------------\n *\n * Where payload shapes are stable + narrow (ids, flags), we type them\n * precisely. Where they're opaque or escape the protocol layer (record\n * data blobs, Yjs binary frames, game-engine state), we use `unknown` and\n * defer narrowing to the caller. This is intentional: over-typing opaque\n * payloads would require the protocol layer to import application types\n * and defeat the \"thin wire contract\" goal.\n */\n\nimport { MSG } from './constants'\n\n// =============================================================================\n// Envelope + helpers\n// =============================================================================\n\n/**\n * The outer shape of every wire message. `T` is the string discriminator\n * (e.g. `\"game.input\"`) — keeping it as a generic literal type lets the\n * discriminated-union narrowing in `dispatch()` pick the right payload.\n *\n * Callers extending the protocol should pass a string-literal type for\n * `T`, not the widened `string`. `BaseMessage<string, P>` collapses the\n * discriminated union and handler-map key inference falls back to a\n * single untyped `string` key, losing all narrowing.\n */\nexport interface BaseMessage<T extends string, P> {\n type: T\n payload: P\n}\n\n/** Matches when a payload is intentionally empty — `{}` on the wire. */\ntype EmptyPayload = Record<string, never>\n\n/**\n * Frozen empty payload reused by every \"no args\" builder. Frozen so a\n * runaway consumer mutating `.payload` can't corrupt the shared instance\n * that every other call site sees.\n */\nconst EMPTY: EmptyPayload = Object.freeze({}) as EmptyPayload\n\n// =============================================================================\n// Client → Server messages\n// =============================================================================\n\n/**\n * Every message the client can legitimately send. Extend in app code with\n * a string-literal union arm:\n *\n * type MyClientMessage = ClientMessage | BaseMessage<'myapp.foo', { x: number }>\n */\nexport type ClientMessage =\n // ---- Records / CRUD ---------------------------------------------------\n | BaseMessage<typeof MSG.SUBSCRIBE, { subscriptionId: string; query: unknown }>\n | BaseMessage<typeof MSG.UNSUBSCRIBE, { subscriptionId: string }>\n | BaseMessage<\n typeof MSG.PUT,\n { collection: string; recordId: string; data: Record<string, unknown>; requestId?: string }\n >\n | BaseMessage<\n typeof MSG.DELETE,\n { collection: string; recordId: string; requestId?: string }\n >\n // ---- Users ------------------------------------------------------------\n | BaseMessage<typeof MSG.USER_LIST, EmptyPayload>\n | BaseMessage<typeof MSG.SET_ROLE, { userId: string; role: string }>\n | BaseMessage<typeof MSG.USER_UPDATE, EmptyPayload>\n | BaseMessage<typeof MSG.LIST_SCHEMAS, EmptyPayload>\n // ---- Yjs --------------------------------------------------------------\n | BaseMessage<typeof MSG.YJS_JOIN, { collection: string; recordId: string; fieldName: string }>\n | BaseMessage<typeof MSG.YJS_LEAVE, { collection: string; recordId: string; fieldName: string }>\n // Binary yjs sync/awareness frames use numeric `MSG_YJS_SYNC` /\n // `MSG_YJS_AWARENESS` envelope ids from `./constants.ts` and ride the\n // binary WebSocket channel. They bypass this typed layer entirely.\n // ---- Game -------------------------------------------------------------\n | BaseMessage<typeof MSG.GAME_INPUT, { action: string; data: Record<string, unknown> }>\n | BaseMessage<typeof MSG.GAME_PLAYER_READY, EmptyPayload>\n | BaseMessage<typeof MSG.GAME_START, EmptyPayload>\n | BaseMessage<typeof MSG.GAME_END, EmptyPayload>\n // ---- Canvas -----------------------------------------------------------\n // `CANVAS_ADD` sends a flat shape dict as the payload (not `{ shape }`);\n // the server wraps it in `{ shape }` on its rebroadcast. Keep the types\n // aligned with the real wire or `clientBuild` lies. See\n // server/rooms/canvas-room.ts for the server side of this asymmetry.\n // `unknown` here (rather than `Record<string, unknown>`) so closed\n // concrete shape types pass assignability without index signatures.\n | BaseMessage<typeof MSG.CANVAS_ADD, unknown>\n | BaseMessage<typeof MSG.CANVAS_MOVE, { shapeId: string; x: number; y: number }>\n | BaseMessage<\n typeof MSG.CANVAS_RESIZE,\n { shapeId: string; width: number; height: number; x?: number; y?: number }\n >\n | BaseMessage<typeof MSG.CANVAS_DELETE, { shapeId: string }>\n | BaseMessage<\n typeof MSG.CANVAS_UPDATE,\n { shapeId: string; props: Record<string, unknown> }\n >\n // Flat payload in the client→server direction, matching `CANVAS_ADD`.\n | BaseMessage<typeof MSG.CANVAS_VIEWPORT, unknown>\n | BaseMessage<typeof MSG.CANVAS_UNDO, EmptyPayload>\n | BaseMessage<typeof MSG.CANVAS_REDO, EmptyPayload>\n // ---- Cron -------------------------------------------------------------\n | BaseMessage<typeof MSG.CRON_TRIGGER, { taskName: string }>\n | BaseMessage<typeof MSG.CRON_PAUSE, { taskName: string }>\n | BaseMessage<typeof MSG.CRON_RESUME, { taskName: string }>\n // ---- Jobs -------------------------------------------------------------\n // `JOB_ENQUEUE` uses requestId/JOB_UPDATE-ack so the caller learns the\n // newly-assigned jobId.\n | BaseMessage<\n typeof MSG.JOB_ENQUEUE,\n {\n requestId: string\n type: string\n payload?: unknown\n maxAttempts?: number\n }\n >\n | BaseMessage<typeof MSG.JOB_CANCEL, { jobId: string }>\n | BaseMessage<typeof MSG.JOB_RETRY, { jobId: string }>\n // ---- Presence ---------------------------------------------------------\n // Flat state object — the server merges incoming fields into the peer's\n // stored state; there's no `{ state }` wrapper in the client direction.\n | BaseMessage<typeof MSG.PRESENCE_UPDATE, Record<string, unknown>>\n // ---- Gateway ----------------------------------------------------------\n | BaseMessage<typeof MSG.GW_SCOPE_CONNECT, { scopeType: string; scopeId: string }>\n | BaseMessage<typeof MSG.GW_SCOPE_DISCONNECT, { scopeType: string; scopeId: string }>\n | BaseMessage<typeof MSG.GW_TOKEN_REFRESH, { token: string }>\n\n// =============================================================================\n// Server → Client messages\n// =============================================================================\n\n/**\n * Every message the server can send. Room and handler `send` / `broadcast`\n * signatures are tightened to this union so outbound payloads are\n * compile-checked against the wire contract. As with `ClientMessage`,\n * extend via a string-literal union arm in app code when adding new\n * server-side broadcasts.\n */\nexport type ServerMessage =\n // ---- Records / CRUD ---------------------------------------------------\n | BaseMessage<\n typeof MSG.QUERY_RESULT,\n { subscriptionId: string; records: unknown[] }\n >\n | BaseMessage<\n typeof MSG.RECORD_CHANGE,\n {\n collection: string\n record: unknown\n // Real wire values are `create`/`update`/`delete`, not the\n // underlying storage op name. See `server/handlers/subscriptions.ts`.\n changeType: 'create' | 'update' | 'delete'\n }\n >\n // `subscriptionId` is optional because generic transport errors (bad\n // envelope, missing connection) have no subscription context. Specific\n // query failures include the id so the client can correlate.\n | BaseMessage<typeof MSG.ERROR, { error: string; subscriptionId?: string }>\n // ACK is a mutation ack — it carries the correlation `requestId` from\n // the inbound PUT/DELETE plus a success flag. Server/handlers/records.ts\n // is the authoritative send site.\n | BaseMessage<\n typeof MSG.ACK,\n | { requestId: string; success: true; recordId?: string }\n | { requestId: string; success: false; error: string }\n >\n | BaseMessage<typeof MSG.RESUBSCRIBE, EmptyPayload>\n | BaseMessage<typeof MSG.LIST_SCHEMAS, { schemas: unknown }>\n // ---- Auth -------------------------------------------------------------\n // Emitted once per connection by rooms that enforce role-based writes\n // (Canvas, Game, Cron). Client hooks store `canWrite` in state and\n // disable write APIs when false. See useCanvas / useGameRoom /\n // useCronMonitor for the consumer side.\n | BaseMessage<typeof MSG.AUTH, { canWrite: boolean }>\n // ---- Users ------------------------------------------------------------\n // `USER_INFO` carries an app-specific user object (column-shape varies\n // per deployment), so the wire type is opaque. Narrow at the consumer.\n | BaseMessage<typeof MSG.USER_INFO, unknown>\n | BaseMessage<typeof MSG.USER_LIST, { users: unknown[] }>\n // ---- Yjs (JSON frames; binary sync/awareness bypass this layer) -------\n | BaseMessage<\n typeof MSG.YJS_JOIN,\n { collection: string; recordId: string; fieldName: string; canWrite: boolean }\n >\n // ---- Game -------------------------------------------------------------\n | BaseMessage<\n typeof MSG.GAME_STATE,\n { state: unknown; tick: number; players: unknown[]; running: boolean }\n >\n | BaseMessage<typeof MSG.GAME_TICK, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_START, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_END, { state: unknown; tick: number }>\n | BaseMessage<typeof MSG.GAME_PLAYER_JOIN, { player: unknown }>\n | BaseMessage<typeof MSG.GAME_PLAYER_LEAVE, { userId: string }>\n | BaseMessage<typeof MSG.GAME_PLAYER_READY, { userId: string }>\n // ---- Canvas -----------------------------------------------------------\n // `CANVAS_SHAPES` carries both the shape list and the viewports snapshot\n // so new connections can restore a multi-user view in one message. See\n // server/rooms/canvas-room.ts:onConnect.\n | BaseMessage<\n typeof MSG.CANVAS_SHAPES,\n { shapes: unknown[]; viewports: unknown[] }\n >\n | BaseMessage<typeof MSG.CANVAS_ADD, { shape: unknown }>\n | BaseMessage<typeof MSG.CANVAS_MOVE, { shapeId: string; x: number; y: number }>\n | BaseMessage<\n typeof MSG.CANVAS_RESIZE,\n { shapeId: string; width: number; height: number; x?: number; y?: number }\n >\n | BaseMessage<typeof MSG.CANVAS_DELETE, { shapeId: string }>\n | BaseMessage<\n typeof MSG.CANVAS_UPDATE,\n { shapeId: string; props: Record<string, unknown> }\n >\n | BaseMessage<\n typeof MSG.CANVAS_VIEWPORT,\n { viewport: unknown } | { userId: string; removed: true }\n >\n // ---- Cron -------------------------------------------------------------\n // `CRON_STATUS` server broadcasts carry both tasks and recent history;\n // see server/rooms/cron-room.ts.\n | BaseMessage<typeof MSG.CRON_TASKS, { tasks: unknown }>\n | BaseMessage<typeof MSG.CRON_HISTORY, { history: unknown }>\n | BaseMessage<typeof MSG.CRON_STATUS, { tasks: unknown; recentHistory: unknown }>\n // ---- Jobs -------------------------------------------------------------\n // `JOB_UPDATE` is the single push channel — same payload shape carries\n // initial-snapshot, enqueue, progress, success, failure, cancel, and\n // retry events. `kind` discriminates client-side. See useJobs.\n | BaseMessage<\n typeof MSG.JOB_UPDATE,\n {\n kind: 'snapshot' | 'enqueued' | 'progress' | 'succeeded' | 'failed' | 'canceled' | 'retried'\n job?: unknown\n jobs?: unknown[]\n /** Echoes the enqueue requestId when the update is the enqueue ack. */\n requestId?: string\n }\n >\n // ---- Presence ---------------------------------------------------------\n | BaseMessage<typeof MSG.PRESENCE_SYNC, { peers: unknown[] }>\n | BaseMessage<typeof MSG.PRESENCE_JOIN, { peer: unknown }>\n | BaseMessage<typeof MSG.PRESENCE_LEAVE, { userId: string }>\n | BaseMessage<\n typeof MSG.PRESENCE_UPDATE,\n { userId: string; state: Record<string, unknown> }\n >\n // ---- Gateway ----------------------------------------------------------\n | BaseMessage<\n typeof MSG.GW_SCOPE_ERROR,\n { scopeType: string; scopeId: string; error: string }\n >\n | BaseMessage<typeof MSG.GW_USER_UPDATE, unknown>\n\n/**\n * Any wire message, regardless of direction. Use this only when the code\n * path genuinely doesn't care — otherwise pick `ClientMessage` or\n * `ServerMessage` so the handler's payload type is narrower.\n */\nexport type ProtocolMessage = ClientMessage | ServerMessage\n\n// =============================================================================\n// Typed builders\n// =============================================================================\n//\n// Each builder returns a `{ type, payload }` object typed as a specific arm\n// of `ClientMessage` / `ServerMessage`. Call sites that hand the result to\n// `JSON.stringify` ship exactly what the wire protocol expects.\n//\n// `as const` on every return preserves the literal string `type` value\n// (e.g. `\"game.input\"`), which is what the discriminated-union narrowing\n// in `dispatch` keys on. Without it TS widens to `string` and the handler\n// map collapses to a single untyped key.\n// =============================================================================\n\n/** Factories for every client → server message. */\nexport const clientBuild = {\n // Records / CRUD\n subscribe: (subscriptionId: string, query: unknown) =>\n ({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }) as const,\n unsubscribe: (subscriptionId: string) =>\n ({ type: MSG.UNSUBSCRIBE, payload: { subscriptionId } }) as const,\n put: (\n collection: string,\n recordId: string,\n data: Record<string, unknown>,\n requestId?: string,\n ) =>\n ({\n type: MSG.PUT,\n payload: { collection, recordId, data, requestId },\n }) as const,\n remove: (collection: string, recordId: string, requestId?: string) =>\n ({ type: MSG.DELETE, payload: { collection, recordId, requestId } }) as const,\n // Users\n userList: () => ({ type: MSG.USER_LIST, payload: EMPTY }) as const,\n setRole: (userId: string, role: string) =>\n ({ type: MSG.SET_ROLE, payload: { userId, role } }) as const,\n userUpdate: () => ({ type: MSG.USER_UPDATE, payload: EMPTY }) as const,\n listSchemas: () => ({ type: MSG.LIST_SCHEMAS, payload: EMPTY }) as const,\n // Yjs\n yjsJoin: (collection: string, recordId: string, fieldName: string) =>\n ({ type: MSG.YJS_JOIN, payload: { collection, recordId, fieldName } }) as const,\n yjsLeave: (collection: string, recordId: string, fieldName: string) =>\n ({ type: MSG.YJS_LEAVE, payload: { collection, recordId, fieldName } }) as const,\n // Game\n gameInput: (action: string, data: Record<string, unknown> = {}) =>\n ({ type: MSG.GAME_INPUT, payload: { action, data } }) as const,\n gamePlayerReady: () => ({ type: MSG.GAME_PLAYER_READY, payload: EMPTY }) as const,\n gameStart: () => ({ type: MSG.GAME_START, payload: EMPTY }) as const,\n gameEnd: () => ({ type: MSG.GAME_END, payload: EMPTY }) as const,\n // Canvas — `CANVAS_ADD` / `CANVAS_VIEWPORT` payloads are flat (the shape\n // or viewport object is the whole payload).\n canvasAdd: (shape: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_ADD, payload: shape }) as const,\n canvasMove: (shapeId: string, x: number, y: number) =>\n ({ type: MSG.CANVAS_MOVE, payload: { shapeId, x, y } }) as const,\n canvasResize: (\n shapeId: string,\n width: number,\n height: number,\n x?: number,\n y?: number,\n ) =>\n ({ type: MSG.CANVAS_RESIZE, payload: { shapeId, width, height, x, y } }) as const,\n canvasDelete: (shapeId: string) =>\n ({ type: MSG.CANVAS_DELETE, payload: { shapeId } }) as const,\n canvasUpdate: (shapeId: string, props: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_UPDATE, payload: { shapeId, props } }) as const,\n canvasViewport: (viewport: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_VIEWPORT, payload: viewport }) as const,\n canvasUndo: () => ({ type: MSG.CANVAS_UNDO, payload: EMPTY }) as const,\n canvasRedo: () => ({ type: MSG.CANVAS_REDO, payload: EMPTY }) as const,\n // Cron\n cronTrigger: (taskName: string) =>\n ({ type: MSG.CRON_TRIGGER, payload: { taskName } }) as const,\n cronPause: (taskName: string) =>\n ({ type: MSG.CRON_PAUSE, payload: { taskName } }) as const,\n cronResume: (taskName: string) =>\n ({ type: MSG.CRON_RESUME, payload: { taskName } }) as const,\n // Jobs\n jobEnqueue: (\n requestId: string,\n type: string,\n payload?: unknown,\n maxAttempts?: number,\n ) =>\n ({\n type: MSG.JOB_ENQUEUE,\n payload: { requestId, type, payload, maxAttempts },\n }) as const,\n jobCancel: (jobId: string) =>\n ({ type: MSG.JOB_CANCEL, payload: { jobId } }) as const,\n jobRetry: (jobId: string) =>\n ({ type: MSG.JOB_RETRY, payload: { jobId } }) as const,\n // Presence\n presenceUpdate: (state: Record<string, unknown>) =>\n ({ type: MSG.PRESENCE_UPDATE, payload: state }) as const,\n // Gateway\n gwScopeConnect: (scopeType: string, scopeId: string) =>\n ({ type: MSG.GW_SCOPE_CONNECT, payload: { scopeType, scopeId } }) as const,\n gwScopeDisconnect: (scopeType: string, scopeId: string) =>\n ({ type: MSG.GW_SCOPE_DISCONNECT, payload: { scopeType, scopeId } }) as const,\n gwTokenRefresh: (token: string) =>\n ({ type: MSG.GW_TOKEN_REFRESH, payload: { token } }) as const,\n}\n\n/** Factories for every server → client message. Used by room DOs and\n * handler modules so server broadcasts are payload-checked too. Opaque\n * slots (`record`, `shape`, `peer`, etc.) take `unknown` so concrete\n * domain types — `RecordResult`, `CanvasShape`, `MediaPeer` — can be\n * passed without casts. */\nexport const serverBuild = {\n // Records / CRUD\n queryResult: (subscriptionId: string, records: unknown[]) =>\n ({ type: MSG.QUERY_RESULT, payload: { subscriptionId, records } }) as const,\n recordChange: (\n collection: string,\n record: unknown,\n changeType: 'create' | 'update' | 'delete',\n ) =>\n ({ type: MSG.RECORD_CHANGE, payload: { collection, record, changeType } }) as const,\n error: (error: string, subscriptionId?: string) =>\n ({ type: MSG.ERROR, payload: { error, subscriptionId } }) as const,\n ackSuccess: (requestId: string, recordId?: string) =>\n ({\n type: MSG.ACK,\n payload: { requestId, success: true as const, recordId },\n }) as const,\n ackFailure: (requestId: string, error: string) =>\n ({\n type: MSG.ACK,\n payload: { requestId, success: false as const, error },\n }) as const,\n resubscribe: () => ({ type: MSG.RESUBSCRIBE, payload: EMPTY }) as const,\n schemas: (schemas: unknown) =>\n ({ type: MSG.LIST_SCHEMAS, payload: { schemas } }) as const,\n // Users\n userInfo: (user: unknown) =>\n ({ type: MSG.USER_INFO, payload: user }) as const,\n userList: (users: unknown[]) =>\n ({ type: MSG.USER_LIST, payload: { users } }) as const,\n // Yjs\n yjsJoin: (collection: string, recordId: string, fieldName: string, canWrite: boolean) =>\n ({\n type: MSG.YJS_JOIN,\n payload: { collection, recordId, fieldName, canWrite },\n }) as const,\n // Game\n gameState: (state: unknown, tick: number, players: unknown[], running: boolean) =>\n ({ type: MSG.GAME_STATE, payload: { state, tick, players, running } }) as const,\n gameTick: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_TICK, payload: { state, tick } }) as const,\n gameStart: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_START, payload: { state, tick } }) as const,\n gameEnd: (state: unknown, tick: number) =>\n ({ type: MSG.GAME_END, payload: { state, tick } }) as const,\n gamePlayerJoin: (player: unknown) =>\n ({ type: MSG.GAME_PLAYER_JOIN, payload: { player } }) as const,\n gamePlayerLeave: (userId: string) =>\n ({ type: MSG.GAME_PLAYER_LEAVE, payload: { userId } }) as const,\n gamePlayerReady: (userId: string) =>\n ({ type: MSG.GAME_PLAYER_READY, payload: { userId } }) as const,\n // Canvas\n canvasShapes: (shapes: unknown[], viewports: unknown[]) =>\n ({ type: MSG.CANVAS_SHAPES, payload: { shapes, viewports } }) as const,\n canvasAdd: (shape: unknown) =>\n ({ type: MSG.CANVAS_ADD, payload: { shape } }) as const,\n canvasMove: (shapeId: string, x: number, y: number) =>\n ({ type: MSG.CANVAS_MOVE, payload: { shapeId, x, y } }) as const,\n canvasResize: (\n shapeId: string,\n width: number,\n height: number,\n x?: number,\n y?: number,\n ) =>\n ({ type: MSG.CANVAS_RESIZE, payload: { shapeId, width, height, x, y } }) as const,\n canvasDelete: (shapeId: string) =>\n ({ type: MSG.CANVAS_DELETE, payload: { shapeId } }) as const,\n canvasUpdate: (shapeId: string, props: Record<string, unknown>) =>\n ({ type: MSG.CANVAS_UPDATE, payload: { shapeId, props } }) as const,\n canvasViewport: (viewport: unknown) =>\n ({ type: MSG.CANVAS_VIEWPORT, payload: { viewport } }) as const,\n canvasViewportRemoved: (userId: string) =>\n ({\n type: MSG.CANVAS_VIEWPORT,\n payload: { userId, removed: true as const },\n }) as const,\n // Cron\n cronTasks: (tasks: unknown) =>\n ({ type: MSG.CRON_TASKS, payload: { tasks } }) as const,\n cronHistory: (history: unknown) =>\n ({ type: MSG.CRON_HISTORY, payload: { history } }) as const,\n cronStatus: (tasks: unknown, recentHistory: unknown) =>\n ({ type: MSG.CRON_STATUS, payload: { tasks, recentHistory } }) as const,\n // Jobs\n jobSnapshot: (jobs: unknown[]) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'snapshot' as const, jobs } }) as const,\n jobEnqueued: (job: unknown, requestId?: string) =>\n ({\n type: MSG.JOB_UPDATE,\n payload: { kind: 'enqueued' as const, job, requestId },\n }) as const,\n jobProgress: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'progress' as const, job } }) as const,\n jobSucceeded: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'succeeded' as const, job } }) as const,\n jobFailed: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'failed' as const, job } }) as const,\n jobCanceled: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'canceled' as const, job } }) as const,\n jobRetried: (job: unknown) =>\n ({ type: MSG.JOB_UPDATE, payload: { kind: 'retried' as const, job } }) as const,\n // Presence\n presenceSync: (peers: unknown[]) =>\n ({ type: MSG.PRESENCE_SYNC, payload: { peers } }) as const,\n presenceJoin: (peer: unknown) =>\n ({ type: MSG.PRESENCE_JOIN, payload: { peer } }) as const,\n presenceLeave: (userId: string) =>\n ({ type: MSG.PRESENCE_LEAVE, payload: { userId } }) as const,\n presenceUpdate: (userId: string, state: Record<string, unknown>) =>\n ({ type: MSG.PRESENCE_UPDATE, payload: { userId, state } }) as const,\n // Gateway\n gwScopeError: (scopeType: string, scopeId: string, error: string) =>\n ({\n type: MSG.GW_SCOPE_ERROR,\n payload: { scopeType, scopeId, error },\n }) as const,\n gwUserUpdate: (user: unknown) =>\n ({ type: MSG.GW_USER_UPDATE, payload: user }) as const,\n}\n\n// =============================================================================\n// Typed dispatch\n// =============================================================================\n//\n// `dispatch` parses a raw WebSocket frame (or takes an already-parsed\n// object) and routes it to the right handler. Handlers are indexed by the\n// message's string `type`, and TS narrows the `payload` argument to the\n// correct arm of the message union automatically thanks to the\n// discriminated-union lookup.\n//\n// The generic `M` defaults to `ProtocolMessage` so ad-hoc uses get the\n// full SDK vocabulary for free, but apps can pass a narrower (or extended)\n// union:\n//\n// dispatch<ServerMessage>(raw, {\n// [MSG.GAME_STATE]: (p) => { /* p is narrowed */ },\n// [MSG.GAME_TICK]: (p) => { /* p is narrowed */ },\n// })\n//\n// // With an app-defined message (use a STRING LITERAL for the type\n// // parameter — `string` widens the union and kills narrowing):\n// type MyMsg =\n// | ServerMessage\n// | BaseMessage<'myapp.boss_spawn', { hp: number }>\n// dispatch<MyMsg>(raw, {\n// 'myapp.boss_spawn': (p) => { console.log(p.hp) },\n// })\n//\n// =============================================================================\n\n/**\n * Handler map keyed by a message's string `type`. Every key maps to the\n * payload type of the matching arm in `M`, so handlers get automatic\n * payload narrowing with no runtime checks.\n *\n * Narrowing requires each `M` arm to use a string-literal `T`; widening\n * `M` to `BaseMessage<string, unknown>` collapses all keys to a single\n * untyped `string` and the map becomes a plain `Record<string, (p: unknown)\n * => void>`.\n */\nexport type MessageHandlers<M extends BaseMessage<string, unknown> = ProtocolMessage> = {\n [K in M as K['type']]?: (payload: K['payload']) => void\n}\n\n/**\n * Parse and route an incoming wire message. Accepts either the raw JSON\n * string (directly from `ws.onmessage`'s `event.data`) or an already-\n * parsed object. Returns `true` if a handler ran, `false` otherwise\n * (unrecognised type, parse failure, or malformed envelope).\n *\n * Defaults `M` to `ProtocolMessage` so callers who don't care about\n * direction can just do `dispatch(raw, handlers)`; narrow with\n * `dispatch<ClientMessage>` / `dispatch<ServerMessage>` to restrict which\n * arms the handler map is allowed to cover.\n */\nexport function dispatch<M extends BaseMessage<string, unknown> = ProtocolMessage>(\n raw: unknown,\n handlers: MessageHandlers<M>,\n): boolean {\n let msg: { type?: unknown; payload?: unknown }\n if (typeof raw === 'string') {\n try {\n msg = JSON.parse(raw) as { type?: unknown; payload?: unknown }\n } catch {\n return false\n }\n } else if (raw && typeof raw === 'object') {\n msg = raw as { type?: unknown; payload?: unknown }\n } else {\n return false\n }\n if (typeof msg.type !== 'string') return false\n const handler = (handlers as Record<string, ((payload: unknown) => void) | undefined>)[\n msg.type\n ]\n if (!handler) return false\n handler(msg.payload)\n return true\n}\n\n/**\n * Serialise a typed-built message for `ws.send`. A tiny wrapper around\n * `JSON.stringify` kept around so call sites read as\n * `ws.send(encode(clientBuild.gameInput(...)))` rather than paying\n * attention to stringify arguments.\n */\nexport function encode<M extends BaseMessage<string, unknown>>(message: M): string {\n return JSON.stringify(message)\n}\n","/**\n * DeepSpace Auth Provider.\n *\n * Wraps the app with the Better Auth session hook so children can read\n * the current user via `useAuth` / `useAuthUser`. Sessions ride a\n * same-origin cookie so there's no satellite-domain configuration.\n */\n\nimport React, { useEffect, useRef } from 'react'\nimport { useSession } from './client'\n\ninterface DeepSpaceAuthProviderProps {\n children: React.ReactNode\n}\n\n/** Logs auth state transitions once. */\nfunction AuthLogger() {\n const session = useSession()\n const isSignedIn = !!session.data?.user\n const prevSignedIn = useRef<boolean | null>(null)\n\n useEffect(() => {\n if (session.isPending) return\n if (prevSignedIn.current !== isSignedIn) {\n if (isSignedIn) {\n console.log(`[ds:auth] signed in as ${session.data?.user?.name ?? session.data?.user?.id}`)\n } else if (prevSignedIn.current !== null) {\n console.log('[ds:auth] signed out')\n }\n prevSignedIn.current = isSignedIn\n }\n }, [isSignedIn, session.isPending, session.data?.user?.name, session.data?.user?.id])\n\n return null\n}\n\n/**\n * Auth provider for DeepSpace apps.\n *\n * Better Auth uses cookie-based sessions, so there's no provider\n * state to manage. This component exists for API compatibility\n * and as a place to add auth-related context in the future.\n */\nexport function DeepSpaceAuthProvider({ children }: DeepSpaceAuthProviderProps) {\n return (\n <>\n <AuthLogger />\n {children}\n </>\n )\n}\n","/**\n * Better Auth Client for DeepSpace\n *\n * Creates a typed Better Auth client that communicates via the app's\n * own /api/auth/* proxy (same-origin cookies, no CORS issues).\n * The app's worker proxies these requests to the auth-worker.\n */\n\nimport { createAuthClient } from 'better-auth/react'\nimport { organizationClient, twoFactorClient } from 'better-auth/client/plugins'\nimport { clearAuthToken } from './token'\n\n/**\n * Auth base URL — always same-origin.\n * The app's worker.ts proxies /api/auth/* to the auth-worker.\n */\nfunction getBaseURL(): string {\n if (typeof window !== 'undefined') {\n return window.location.origin\n }\n return ''\n}\n\nexport const authClient = createAuthClient({\n baseURL: getBaseURL(),\n plugins: [organizationClient(), twoFactorClient()],\n})\n\nexport const {\n useSession,\n signIn,\n useActiveOrganization,\n useListOrganizations,\n} = authClient\n\nexport async function signOut(\n ...args: Parameters<typeof authClient.signOut>\n): Promise<Awaited<ReturnType<typeof authClient.signOut>>> {\n try {\n return await authClient.signOut(...args)\n } finally {\n clearAuthToken()\n }\n}\n","/**\n * Short-lived JWT provider for WebSocket and API authentication.\n *\n * Fetches an ES256 token from the same-origin `/api/auth/token` endpoint\n * (routed through to the auth-worker), caches it in module scope, and\n * refreshes ~30s before expiry by reading `exp` out of the payload.\n */\n\n// Token is fetched via same-origin /api/auth/token — the app's worker (or Vite proxy)\n// routes this to the auth-worker. No cross-origin requests needed.\n\nlet cachedToken: string | null = null\nlet tokenExpiry = 0\n\nfunction extractExpiry(token: string): number {\n try {\n const parts = token.split('.')\n if (parts.length < 2) return 0\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n return (payload.exp ?? 0) * 1000\n } catch {\n return 0\n }\n}\n\n/**\n * Get a short-lived JWT for WebSocket and API calls.\n *\n * The token is obtained from the auth-worker's /api/auth/token endpoint,\n * authenticated via the Better Auth session cookie. Tokens are cached\n * and refreshed 30s before expiry.\n */\nexport async function getAuthToken(): Promise<string | null> {\n if (typeof window === 'undefined') return null\n\n // Return cached token if still valid (30s buffer)\n if (cachedToken && Date.now() < tokenExpiry - 30_000) {\n return cachedToken\n }\n\n try {\n const res = await fetch('/api/auth/token', {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n })\n\n if (!res.ok) {\n cachedToken = null\n tokenExpiry = 0\n return null\n }\n\n const data = (await res.json()) as { token?: string | null }\n if (!data.token) {\n cachedToken = null\n tokenExpiry = 0\n return null\n }\n\n cachedToken = data.token\n tokenExpiry = extractExpiry(data.token)\n return data.token\n } catch {\n return null\n }\n}\n\n/** Clear cached token (call on sign-out). */\nexport function clearAuthToken(): void {\n cachedToken = null\n tokenExpiry = 0\n}\n","/**\n * Auth hooks for the DeepSpace SDK.\n *\n * Thin wrappers over Better Auth's `useSession` that expose the loaded /\n * signed-in / userId / user-profile shape the storage layer reads.\n */\n\nimport { useSession } from './client'\n\n/**\n * Sticky-true flag: becomes true once the session query first resolves\n * (success or error) and stays true for the lifetime of the page.\n *\n * Better Auth's underlying query atom briefly flips `isPending` back to\n * true on every background refetch when `data` is `null` — i.e. for\n * anonymous users on every tab-visibility change. Reporting that as\n * `isLoaded: false` would cause consumers (e.g. `RecordProvider`) to\n * unmount and remount their children on each refocus.\n *\n * `isLoaded` here means \"the first session check has completed,\" which\n * is the contract consumers actually want.\n */\nlet sessionHasResolved = false\n\nfunction stickyIsLoaded(isPending: boolean): boolean {\n if (!isPending) sessionHasResolved = true\n return sessionHasResolved\n}\n\n/**\n * Returns auth state compatible with what storage/context.tsx expects.\n */\nexport function useAuth() {\n const session = useSession()\n\n const isSignedIn = !!session.data?.user\n const userId = session.data?.user?.id ?? null\n\n return {\n isLoaded: stickyIsLoaded(session.isPending),\n isSignedIn,\n userId,\n sessionId: session.data?.session?.id ?? null,\n }\n}\n\n/**\n * Returns user data compatible with what storage/context.tsx expects.\n */\nexport function useAuthUser() {\n const session = useSession()\n const user = session.data?.user ?? null\n\n return {\n isLoaded: stickyIsLoaded(session.isPending),\n isSignedIn: !!user,\n user: user\n ? {\n id: user.id,\n fullName: user.name ?? null,\n firstName: user.name?.split(' ')[0] ?? null,\n lastName: user.name?.split(' ').slice(1).join(' ') || null,\n emailAddresses: user.email\n ? [{ emailAddress: user.email }]\n : [],\n imageUrl: user.image ?? null,\n primaryEmailAddress: user.email\n ? { emailAddress: user.email }\n : null,\n }\n : null,\n }\n}\n","/**\n * Full-page frosted-glass auth overlay for deployed DeepSpace apps.\n *\n * Primary: OAuth (GitHub, Google).\n * Secondary: Email/password sign-in (for test accounts created via CLI/API).\n * Styled with shadcn semantic tokens so it themes along with the host app.\n */\n\nimport React, { useState } from 'react'\nimport { useAuth } from './hooks'\nimport { signIn } from './client'\n\ninterface AuthOverlayProps {\n /** Called when the user clicks the close button. If omitted, overlay is not closeable. */\n onClose?: () => void\n /** Which OAuth providers to show. Defaults to both. */\n providers?: Array<'github' | 'google'>\n}\n\nexport function AuthOverlay({\n onClose,\n providers = ['github', 'google'],\n}: AuthOverlayProps = {}): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const [showEmailForm, setShowEmailForm] = useState(false)\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [error, setError] = useState('')\n const [loading, setLoading] = useState(false)\n\n if (!isLoaded || isSignedIn) return null\n\n const handleSocial = (provider: 'github' | 'google') => {\n setLoading(true)\n window.location.href = `/api/auth/social-redirect?provider=${provider}`\n }\n\n const handleEmailSignIn = async (e: React.FormEvent) => {\n e.preventDefault()\n setError('')\n setLoading(true)\n\n try {\n const result = await signIn.email({ email, password })\n if (result.error) {\n setError(result.error.message ?? 'Sign in failed')\n setLoading(false)\n }\n } catch (err: any) {\n setError(err.message ?? 'Something went wrong')\n setLoading(false)\n }\n }\n\n return (\n <>\n <style>{`\n @keyframes ds-auth-overlay-in {\n from { opacity: 0 }\n to { opacity: 1 }\n }\n @keyframes ds-auth-card-in {\n from { opacity: 0; transform: translateY(16px) scale(0.97) }\n to { opacity: 1; transform: translateY(0) scale(1) }\n }\n `}</style>\n\n <div\n data-testid=\"auth-overlay\"\n onClick={onClose ? (e) => { if (e.target === e.currentTarget) onClose() } : undefined}\n className=\"fixed inset-0 z-[99999] flex items-center justify-center bg-black/55 backdrop-blur-2xl\"\n style={{\n opacity: 0,\n animation: 'ds-auth-overlay-in 0.4s ease forwards',\n }}\n >\n <div\n className=\"relative mx-6 w-full max-w-[380px] rounded-2xl border border-border bg-card p-8 text-center shadow-card-hover sm:p-9\"\n style={{\n opacity: 0,\n animation: 'ds-auth-card-in 0.45s cubic-bezier(0.25, 1, 0.5, 1) 0.08s forwards',\n }}\n >\n {onClose && (\n <button\n data-testid=\"auth-overlay-close\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"absolute right-3 top-3 inline-flex h-7 w-7 items-center justify-center rounded-full bg-secondary text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n ✕\n </button>\n )}\n\n <h2 className=\"mb-2 text-[22px] font-bold leading-snug text-foreground\">\n Sign in to DeepSpace\n </h2>\n\n <p className=\"mb-6 text-sm leading-snug text-muted-foreground\">\n Sync your data across devices\n </p>\n\n {/* OAuth buttons */}\n <div className=\"flex flex-col gap-2\">\n {providers.includes('github') && (\n <OAuthButton onClick={() => handleSocial('github')} disabled={loading} icon={<GitHubIcon />}>\n Continue with GitHub\n </OAuthButton>\n )}\n {providers.includes('google') && (\n <OAuthButton onClick={() => handleSocial('google')} disabled={loading} icon={<GoogleIcon />}>\n Continue with Google\n </OAuthButton>\n )}\n </div>\n\n <Divider />\n\n {!showEmailForm ? (\n <button\n type=\"button\"\n data-testid=\"auth-email-toggle\"\n onClick={() => setShowEmailForm(true)}\n className=\"flex w-full items-center justify-center gap-2.5 rounded-lg border border-border bg-transparent px-4 py-2.5 text-sm font-semibold text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n Sign in with email\n </button>\n ) : (\n <form onSubmit={handleEmailSignIn} className=\"text-left\">\n <input\n type=\"email\"\n placeholder=\"Email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n required\n autoComplete=\"email\"\n className=\"mb-3 block w-full rounded-lg border border-border bg-secondary px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none\"\n />\n <input\n type=\"password\"\n placeholder=\"Password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n required\n minLength={8}\n autoComplete=\"current-password\"\n className={`block w-full rounded-lg border border-border bg-secondary px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-none ${error ? 'mb-3' : 'mb-5'}`}\n />\n\n {error && (\n <div className=\"mb-4 text-center text-sm text-destructive\">{error}</div>\n )}\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"block w-full rounded-lg bg-primary px-5 py-3 text-[15px] font-semibold text-primary-foreground transition-opacity hover:opacity-90 disabled:cursor-wait disabled:opacity-70\"\n >\n {loading ? 'Please wait…' : 'Sign in'}\n </button>\n </form>\n )}\n\n <div className=\"mt-5 flex items-center justify-center gap-1.5 text-[11px] text-muted-foreground\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\" opacity=\"0.5\" aria-hidden>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n </svg>\n Powered by DeepSpace\n </div>\n </div>\n </div>\n </>\n )\n}\n\n// ────────────────────────────────────────────────────────────────────\n// Local components\n// ────────────────────────────────────────────────────────────────────\n\nfunction OAuthButton({\n onClick,\n disabled,\n icon,\n children,\n}: {\n onClick: () => void\n disabled: boolean\n icon: React.ReactNode\n children: React.ReactNode\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className=\"flex w-full items-center justify-center gap-2.5 rounded-lg border border-border bg-secondary px-4 py-2.5 text-sm font-semibold text-foreground transition-colors hover:bg-accent disabled:cursor-wait disabled:opacity-60\"\n >\n {icon}\n {children}\n </button>\n )\n}\n\nfunction Divider() {\n return (\n <div className=\"my-5 flex items-center gap-3 text-xs text-muted-foreground\">\n <div className=\"h-px flex-1 bg-border\" />\n or\n <div className=\"h-px flex-1 bg-border\" />\n </div>\n )\n}\n\nfunction GitHubIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden>\n <path d=\"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0016 8c0-4.42-3.58-8-8-8z\" />\n </svg>\n )\n}\n\n// Google logo uses Google's brand colors — these are required by Google's\n// brand guidelines and intentionally not theme-reactive.\nfunction GoogleIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden>\n <path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" />\n <path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </svg>\n )\n}\n","/** Conditional renderers, the route gate, and a display-name hook. */\n\nimport { useEffect, useRef, type ReactNode } from 'react'\nimport { useAuth, useAuthUser } from './hooks'\nimport { AuthOverlay } from './AuthOverlay'\n\n/**\n * Renders children only when the user is signed in.\n */\nexport function SignedIn({ children }: { children: ReactNode }): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n if (!isLoaded || !isSignedIn) return null\n return <>{children}</>\n}\n\n/**\n * Renders children only when the user is signed out.\n */\nexport function SignedOut({ children }: { children: ReactNode }): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n if (!isLoaded || isSignedIn) return null\n return <>{children}</>\n}\n\nexport interface AuthGateProps {\n /** Content to show when signed in */\n children: ReactNode\n /**\n * UI for first-visit signed-out users. If omitted, the SDK's sign-in\n * overlay is shown non-closeably. Not used on mid-session sign-out —\n * see `redirectOnSignOut`.\n */\n fallback?: ReactNode\n /** Where to send the user when they sign out from inside the gate. Defaults to '/'. */\n redirectOnSignOut?: string\n}\n\n/**\n * Gates a subtree behind sign-in. Children mount only when signed in (no flash).\n * If the user signs out from inside the gate, redirects out instead of trapping\n * them on the overlay.\n */\nexport function AuthGate({\n children,\n fallback,\n redirectOnSignOut = '/',\n}: AuthGateProps): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const wasSignedIn = useRef(false)\n if (isSignedIn) wasSignedIn.current = true\n\n if (!isLoaded) return null\n if (isSignedIn) return <>{children}</>\n if (wasSignedIn.current) return <RedirectAway to={redirectOnSignOut} />\n if (fallback) return <>{fallback}</>\n return <AuthOverlay />\n}\n\n// Full page load (not a router navigation) so the SDK stays router-agnostic\n// and the signed-out teardown is clean.\nfunction RedirectAway({ to }: { to: string }): null {\n useEffect(() => {\n if (typeof window !== 'undefined') window.location.replace(to)\n }, [to])\n return null\n}\n\n/**\n * Returns the current user's display name.\n *\n * Resolution order: fullName -> firstName -> email prefix -> 'User'.\n * Returns null when no user is signed in.\n */\nexport function useDisplayName(): string | null {\n const { user } = useAuthUser()\n if (!user) return null\n return (\n user.fullName ||\n user.firstName ||\n user.primaryEmailAddress?.emailAddress?.split('@')[0] ||\n 'User'\n )\n}\n","/**\n * Floating dismissible guest banner for DeepSpace apps.\n *\n * Shows a non-intrusive prompt for signed-out users to sign in or sign up.\n * Dismiss state is persisted in sessionStorage so it stays hidden for the\n * duration of the browsing session.\n *\n * Styled with shadcn semantic tokens (bg-card, text-foreground, etc.) so it\n * themes along with the host app.\n */\n\nimport React, { useEffect, useState } from 'react'\nimport { useAuth } from './hooks'\n\nconst DEFAULT_STORAGE_KEY = 'deepspace-guest-banner-dismissed'\nconst DEFAULT_MESSAGE = \"You're browsing as a guest. Sign in to unlock all features.\"\n\nexport interface GuestBannerProps {\n message?: string\n storageKey?: string\n /** Called when the user clicks \"Sign in\". */\n onSignIn?: () => void\n}\n\nexport function GuestBanner({\n message = DEFAULT_MESSAGE,\n storageKey = DEFAULT_STORAGE_KEY,\n onSignIn,\n}: GuestBannerProps): React.ReactElement | null {\n const { isLoaded, isSignedIn } = useAuth()\n const [mounted, setMounted] = useState(false)\n\n const [dismissed, setDismissed] = useState(() => {\n if (typeof window === 'undefined') return false\n try {\n return sessionStorage.getItem(storageKey) === '1'\n } catch {\n return false\n }\n })\n\n useEffect(() => {\n if (isLoaded && !isSignedIn && !dismissed) {\n requestAnimationFrame(() => setMounted(true))\n }\n }, [dismissed, isLoaded, isSignedIn])\n\n if (!isLoaded || isSignedIn || dismissed) return null\n\n const handleDismiss = (): void => {\n try {\n sessionStorage.setItem(storageKey, '1')\n } catch {\n // best effort\n }\n setDismissed(true)\n }\n\n return (\n <>\n <style>{`\n @keyframes ds-guest-banner-in {\n from { opacity: 0; transform: translateY(-12px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}</style>\n <div\n role=\"banner\"\n data-testid=\"guest-banner\"\n className=\"fixed top-3 inset-x-3 z-[99998] mx-auto flex max-w-[700px] items-center gap-3.5 rounded-2xl border border-border bg-card/95 px-4 py-3 text-sm leading-snug text-foreground shadow-card-hover backdrop-blur-xl sm:gap-4\"\n style={{\n opacity: mounted ? 1 : 0,\n animation: mounted\n ? 'ds-guest-banner-in 0.35s cubic-bezier(0.25, 1, 0.5, 1) forwards'\n : 'none',\n pointerEvents: mounted ? 'auto' : 'none',\n }}\n >\n <span\n aria-hidden\n className=\"hidden h-2 w-2 shrink-0 rounded-full bg-primary shadow-[0_0_8px_var(--color-primary)] sm:inline-block\"\n />\n\n <span className=\"min-w-0 flex-1 font-medium text-muted-foreground\">\n {message}\n </span>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n <button\n type=\"button\"\n data-testid=\"guest-banner-signin\"\n onClick={onSignIn}\n className=\"inline-flex items-center justify-center whitespace-nowrap rounded-lg bg-primary px-4 py-1.5 text-xs font-semibold text-primary-foreground transition-opacity hover:opacity-90 sm:text-sm\"\n >\n Sign in\n </button>\n\n <button\n type=\"button\"\n data-testid=\"guest-banner-dismiss\"\n onClick={handleDismiss}\n aria-label=\"Dismiss banner\"\n className=\"flex shrink-0 items-center justify-center rounded-md p-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n </div>\n </>\n )\n}\n","/**\n * RecordProvider Context\n *\n * Provides WebSocket connection and state management for RecordRoom.\n *\n * Multi-scope mode: RecordProvider can be used without roomId\n * to provide only auth context + ScopeRegistry. RecordScope components\n * handle individual WebSocket connections.\n */\n\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react'\nimport type { CollectionSchema } from '../../shared/types'\nimport { useAuth, getAuthToken } from '../auth'\nimport { RecordStore } from './store'\nimport { ScopeRegistryProvider } from './ScopeRegistry'\nimport { parseServerError } from './serverErrors'\nimport type {\n UserProfile,\n RoomUser,\n RoomConnectionState,\n FetchUserProfile,\n RecordData,\n} from './types'\nimport { MSG } from '@/shared/protocol/constants'\n\n// ============================================================================\n// RecordContext (per-scope connection state)\n// ============================================================================\n\nexport interface RecordContextValue {\n store: RecordStore\n roomId: string\n /** Collection names registered by this scope's schemas (used for scope resolution priority). */\n registeredCollections?: Set<string>\n userProfile: UserProfile | null\n userProfileLoading: boolean\n refetchUserProfile: () => Promise<void>\n roomRole: string | null\n allUsers: RoomUser[]\n /** True once the first MSG.USER_LIST response has been received. */\n usersLoaded: boolean\n status: RoomConnectionState\n ready: boolean\n /** Schemas discovered via MSG.LIST_SCHEMAS from the server. Available after ready. */\n discoveredSchemas?: CollectionSchema[]\n setUserRole: (userId: string, role: string) => void\n requestUserList: () => void\n registerSubscription: (subscriptionId: string, queryKey: string) => void\n unregisterSubscription: (subscriptionId: string) => void\n sendMessage: (message: { type: string; payload: unknown }) => void\n sendBinary: (data: Uint8Array) => void\n onBinaryMessage: (handler: (data: ArrayBuffer) => void) => () => void\n registerYjsJoinHandler: (docKey: string, handler: (canWrite: boolean) => void) => () => void\n sendConfirmed: (message: { type: string; payload: Record<string, unknown> }, timeoutMs?: number) => Promise<unknown>\n}\n\nexport const RecordContext = createContext<RecordContextValue | null>(null)\n\nexport function useRecordContext(): RecordContextValue {\n const ctx = useContext(RecordContext)\n if (!ctx) {\n throw new Error('useRecordContext must be used within a RecordProvider')\n }\n return ctx\n}\n\n// ============================================================================\n// RecordAuthContext (shared auth state for RecordScope)\n// ============================================================================\n\nexport interface RecordAuthContextValue {\n userProfile: UserProfile | null\n userProfileLoading: boolean\n refetchUserProfile: () => Promise<void>\n allowAnonymous: boolean\n /** Called by RecordScope when it receives an RBAC permission error */\n onPermissionError?: (title: string, detail: string) => void\n /** Called by RecordScope when it receives a validation/other error */\n onValidationError?: (title: string, detail: string) => void\n /** Get auth token for WebSocket connections. */\n getAuthToken?: () => Promise<string | null>\n}\n\nconst RecordAuthContext = createContext<RecordAuthContextValue | null>(null)\n\nexport function useRecordAuth(): RecordAuthContextValue | null {\n return useContext(RecordAuthContext)\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction recordMatchesWhere(record: RecordData, where?: Record<string, unknown>): boolean {\n if (!where) return true\n const r = record as RecordData & { data?: Record<string, unknown> }\n const data = r.data\n if (!data) return false\n // Schema columns take precedence over envelope fields — mirrors the\n // server-side where-builder in executeTableQuery so initial load and\n // live updates stay in sync when a schema defines a column named\n // 'createdBy' (e.g. the messaging `channels` collection).\n return Object.entries(where).every(([key, value]) => {\n if (key in data) return data[key] === value\n if (key === 'recordId') return r.recordId === value\n if (key === 'createdBy') return r.createdBy === value\n return false\n })\n}\n\n// ============================================================================\n// Core Provider (handles WebSocket connection — backward compat mode)\n// ============================================================================\n\ninterface RecordProviderCoreProps {\n roomId: string\n schemas: CollectionSchema[]\n wsUrl?: string\n children: ReactNode\n fetchUser: FetchUserProfile\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}\n\nfunction RecordProviderCore({\n roomId,\n schemas,\n wsUrl,\n children,\n fetchUser,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: RecordProviderCoreProps): React.ReactElement {\n\n const [userProfile, setUserProfile] = useState<UserProfile | null>(null)\n const [userProfileLoading, setUserProfileLoading] = useState(true)\n\n const [roomRole, setRoomRole] = useState<string | null>(null)\n const [allUsers, setAllUsers] = useState<RoomUser[]>([])\n const [usersLoaded, setUsersLoaded] = useState(false)\n const [status, setStatus] = useState<RoomConnectionState>('connecting')\n const [ready, setReady] = useState(false)\n\n // Callback refs for error handling — used by handleMessage (which has [] deps)\n // so it can invoke the latest callbacks without re-creating on every render.\n const onPermissionErrorRef = useRef<((title: string, detail: string) => void) | undefined>(undefined)\n const onValidationErrorRef = useRef<((title: string, detail: string) => void) | undefined>(undefined)\n\n const storeRef = useRef<RecordStore>(new RecordStore())\n const wsRef = useRef<WebSocket | null>(null)\n const subscriptionMapRef = useRef<Map<string, string>>(new Map())\n const binaryHandlersRef = useRef<Set<(data: ArrayBuffer) => void>>(new Set())\n const yjsJoinHandlersRef = useRef<Map<string, Set<(canWrite: boolean) => void>>>(new Map())\n const pendingRequestsRef = useRef<Map<string, {\n resolve: (data?: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n }>>(new Map())\n const reconnectAttemptRef = useRef(0)\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const connectedWithProfileRef = useRef(false)\n const userProfileRef = useRef<UserProfile | null>(null)\n\n userProfileRef.current = userProfile\n\n const refetchUserProfile = useCallback(async () => {\n try {\n const profile = await fetchUser()\n setUserProfile(profile)\n } catch (err) {\n console.error('[RecordProvider] Failed to refetch user profile:', err)\n }\n }, [fetchUser])\n\n // Fetch user profile on mount and refresh periodically.\n // fetchUser returns null when not signed in — that's fine.\n useEffect(() => {\n let mounted = true\n setUserProfileLoading(true)\n fetchUser()\n .then(profile => { if (mounted) setUserProfile(profile) })\n .finally(() => { if (mounted) setUserProfileLoading(false) })\n\n const interval = setInterval(() => {\n if (mounted) fetchUser().then(p => { if (mounted) setUserProfile(p) })\n }, 30000)\n\n return () => { mounted = false; clearInterval(interval) }\n }, [fetchUser])\n\n const handleMessage = useCallback((event: MessageEvent) => {\n if (event.data instanceof ArrayBuffer) {\n binaryHandlersRef.current.forEach(handler => handler(event.data as ArrayBuffer))\n return\n }\n\n try {\n const msg = JSON.parse(event.data as string) as { type: string; payload: unknown }\n const { type, payload } = msg\n\n switch (type) {\n case MSG.USER_INFO: {\n const serverUser = payload as { role: string }\n console.log('[WS] Ready:', { roomId, role: serverUser.role })\n setRoomRole(serverUser.role)\n setReady(true)\n reconnectAttemptRef.current = 0\n // Auto-request user list as part of connection handshake\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: MSG.USER_LIST, payload: {} }))\n }\n break\n }\n case MSG.USER_LIST:\n setAllUsers((payload as { users: RoomUser[] }).users)\n setUsersLoaded(true)\n break\n case MSG.QUERY_RESULT: {\n const { subscriptionId, records } = payload as { subscriptionId: string; records: RecordData[] }\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setQueryResult(queryKey, records)\n break\n }\n }\n break\n }\n case MSG.RECORD_CHANGE: {\n const { collection, record, changeType } = payload as {\n collection: string; record: RecordData; changeType: 'create' | 'update' | 'delete'\n }\n for (const [_subId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey) as { collection: string; where?: Record<string, unknown> }\n if (query.collection !== collection) continue\n const matches = recordMatchesWhere(record, query.where)\n const exists = storeRef.current.hasRecord(queryKey, record.recordId)\n if (changeType === 'delete') {\n if (exists) storeRef.current.applyChange(queryKey, record, 'delete')\n } else if (changeType === 'create') {\n if (matches) storeRef.current.applyChange(queryKey, record, 'create')\n } else {\n if (matches && exists) storeRef.current.applyChange(queryKey, record, 'update')\n else if (matches && !exists) storeRef.current.applyChange(queryKey, record, 'create')\n else if (!matches && exists) storeRef.current.applyChange(queryKey, record, 'delete')\n }\n } catch { /* Skip invalid query keys */ }\n }\n break\n }\n case MSG.ERROR: {\n const { subscriptionId, error } = payload as { subscriptionId?: string; error: string }\n if (subscriptionId) {\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) { storeRef.current.setError(queryKey, error); break }\n }\n } else {\n const parsed = parseServerError(error)\n console.error('[RecordProvider] Error:', error)\n // Errors are surfaced via callback refs — the consuming app\n // is responsible for displaying them (no built-in overlays/toasts).\n if (parsed.isPermissionError) {\n onPermissionErrorRef.current?.(parsed.title, parsed.detail)\n } else {\n onValidationErrorRef.current?.(parsed.title, parsed.detail)\n }\n }\n break\n }\n case MSG.YJS_JOIN: {\n const { collection, recordId, fieldName, canWrite } = payload as {\n collection: string; recordId: string; fieldName: string; canWrite: boolean\n }\n const docKey = `${collection}:${recordId}:${fieldName}`\n yjsJoinHandlersRef.current.get(docKey)?.forEach(handler => handler(canWrite))\n break\n }\n case MSG.ACK: {\n const { requestId, success, error, ...rest } = payload as {\n requestId: string; success: boolean; error?: string; [key: string]: unknown\n }\n const pending = pendingRequestsRef.current.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequestsRef.current.delete(requestId)\n if (success) pending.resolve(rest)\n else pending.reject(new Error(error || 'Mutation rejected'))\n }\n break\n }\n case MSG.RESUBSCRIBE: {\n // Team membership changed — re-subscribe all active queries\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) {\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip invalid */ }\n }\n }\n break\n }\n }\n } catch (e) {\n console.error('[RecordProvider] Failed to parse message:', e)\n }\n }, [])\n\n const connect = useCallback(async () => {\n const profile = userProfileRef.current\n if (!profile && !allowAnonymous) return\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n // We started anonymously; profile arriving means a token is now\n // available. Reconnect so the WS carries it and the DO sees the\n // authenticated identity (read from JWT claims).\n if (profile && !connectedWithProfileRef.current) {\n console.log(`[WS] Reconnecting with profile data`, { roomId })\n wsRef.current.onclose = null\n wsRef.current.close()\n wsRef.current = null\n } else {\n return\n }\n }\n if (wsRef.current?.readyState === WebSocket.CONNECTING) return\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n\n let baseUrl: string\n if (wsUrl) {\n baseUrl = wsUrl.replace(/^http/, 'ws')\n } else {\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n baseUrl = `${protocol}//${window.location.host}`\n }\n\n const params = new URLSearchParams()\n\n // Identity (userId, name, email, imageUrl, role) is derived server-side\n // from the verified JWT — any client-supplied identity params would be\n // stripped at the worker edge, so we don't send them.\n try {\n const tokenFn = getAuthTokenProp ?? getAuthToken\n const token = await tokenFn()\n if (token) params.set('token', token)\n } catch { /* Token fetch failed */ }\n\n connectedWithProfileRef.current = !!profile\n\n const wsPath = `/ws/${roomId}`\n const url = `${baseUrl}${wsPath}?${params.toString()}`\n console.log('[WS] Connecting:', { roomId, attempt: reconnectAttemptRef.current })\n const ws = new WebSocket(url)\n ws.binaryType = 'arraybuffer'\n\n ws.onopen = () => {\n console.log('[WS] Connected:', { roomId })\n setStatus('connected')\n }\n ws.onmessage = handleMessage\n ws.onclose = (event) => {\n console.log('[WS] Closed:', { roomId, code: event.code, reason: event.reason, wasClean: event.wasClean })\n setStatus('disconnected')\n setReady(false)\n wsRef.current = null\n for (const [_id, pending] of pendingRequestsRef.current) {\n clearTimeout(pending.timer)\n pending.reject(new Error('WebSocket disconnected'))\n }\n pendingRequestsRef.current.clear()\n const attempt = reconnectAttemptRef.current\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000)\n console.log('[WS] Scheduling reconnect:', { roomId, attempt, delayMs: delay })\n reconnectAttemptRef.current = attempt + 1\n reconnectTimeoutRef.current = setTimeout(connect, delay)\n }\n ws.onerror = (e) => { console.error('[WS] Error:', { roomId, error: e }) }\n wsRef.current = ws\n }, [roomId, wsUrl, handleMessage, allowAnonymous, getAuthTokenProp])\n\n useEffect(() => {\n if (userProfile?.id) connect()\n else if (allowAnonymous && !userProfileLoading) connect()\n }, [userProfile?.id, userProfileLoading, allowAnonymous, connect])\n\n useEffect(() => {\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible') {\n const ws = wsRef.current\n if (ws?.readyState !== WebSocket.OPEN && (userProfileRef.current || allowAnonymous)) {\n console.log('[WS] Reconnecting after visibility change')\n reconnectAttemptRef.current = 0\n connect()\n }\n }\n }\n document.addEventListener('visibilitychange', handleVisibilityChange)\n return () => document.removeEventListener('visibilitychange', handleVisibilityChange)\n }, [roomId, connect])\n\n useEffect(() => {\n return () => {\n console.log('[WS] Unmounting provider:', { roomId })\n if (reconnectTimeoutRef.current) clearTimeout(reconnectTimeoutRef.current)\n wsRef.current?.close()\n }\n }, [roomId])\n\n const sendMessage = useCallback((message: { type: string; payload: unknown }) => {\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message))\n else console.warn('[RecordProvider] Cannot send message, WebSocket not connected')\n }, [])\n\n const setUserRole = useCallback((userId: string, role: string) => {\n sendMessage({ type: MSG.SET_ROLE, payload: { userId, role } })\n }, [sendMessage])\n\n const requestUserList = useCallback(() => {\n sendMessage({ type: MSG.USER_LIST, payload: {} })\n }, [sendMessage])\n\n const registerSubscription = useCallback((subscriptionId: string, queryKey: string) => {\n subscriptionMapRef.current.set(subscriptionId, queryKey)\n }, [])\n\n const unregisterSubscription = useCallback((subscriptionId: string) => {\n subscriptionMapRef.current.delete(subscriptionId)\n }, [])\n\n const sendBinary = useCallback((data: Uint8Array) => {\n const ws = wsRef.current\n if (ws && ws.readyState === WebSocket.OPEN) ws.send(data)\n }, [])\n\n const onBinaryMessage = useCallback((handler: (data: ArrayBuffer) => void) => {\n binaryHandlersRef.current.add(handler)\n return () => { binaryHandlersRef.current.delete(handler) }\n }, [])\n\n const registerYjsJoinHandler = useCallback((docKey: string, handler: (canWrite: boolean) => void) => {\n if (!yjsJoinHandlersRef.current.has(docKey)) {\n yjsJoinHandlersRef.current.set(docKey, new Set())\n }\n yjsJoinHandlersRef.current.get(docKey)!.add(handler)\n return () => {\n const handlers = yjsJoinHandlersRef.current.get(docKey)\n if (handlers) {\n handlers.delete(handler)\n if (handlers.size === 0) yjsJoinHandlersRef.current.delete(docKey)\n }\n }\n }, [])\n\n const sendConfirmed = useCallback((\n message: { type: string; payload: Record<string, unknown> },\n timeoutMs = 10000\n ): Promise<unknown> => {\n const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error('WebSocket not connected'))\n }\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequestsRef.current.delete(requestId)\n reject(new Error('Mutation confirmation timed out'))\n }, timeoutMs)\n pendingRequestsRef.current.set(requestId, { resolve, reject, timer })\n ws.send(JSON.stringify({ ...message, payload: { ...message.payload, requestId } }))\n })\n }, [])\n\n const value: RecordContextValue = useMemo(() => ({\n store: storeRef.current, roomId, userProfile, userProfileLoading, refetchUserProfile,\n roomRole, allUsers, usersLoaded, status, ready,\n setUserRole, requestUserList,\n registerSubscription, unregisterSubscription, sendMessage, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, sendConfirmed,\n }), [roomId, userProfile, userProfileLoading, refetchUserProfile, roomRole, allUsers, usersLoaded, status, ready, setUserRole, requestUserList, registerSubscription, unregisterSubscription, sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, sendConfirmed])\n\n const onPermissionError = useCallback((title: string, detail: string) => {\n onPermissionErrorRef.current?.(title, detail)\n }, [])\n\n const onValidationError = useCallback((title: string, detail: string) => {\n onValidationErrorRef.current?.(title, detail)\n }, [])\n\n const authValue: RecordAuthContextValue = useMemo(() => ({\n userProfile,\n userProfileLoading,\n refetchUserProfile,\n allowAnonymous,\n getAuthToken: getAuthTokenProp,\n onPermissionError,\n onValidationError,\n }), [userProfile, userProfileLoading, refetchUserProfile, allowAnonymous, getAuthTokenProp, onPermissionError, onValidationError])\n\n return (\n <RecordAuthContext.Provider value={authValue}>\n <ScopeRegistryProvider>\n <RecordContext.Provider value={value}>\n {children}\n </RecordContext.Provider>\n </ScopeRegistryProvider>\n </RecordAuthContext.Provider>\n )\n}\n\n// ============================================================================\n// Auth-Only Provider (multi-scope mode — no roomId, no WS)\n// ============================================================================\n\ninterface RecordProviderAuthOnlyProps {\n children: ReactNode\n fetchUser: FetchUserProfile\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}\n\nfunction RecordProviderAuthOnly({\n children,\n fetchUser,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: RecordProviderAuthOnlyProps): React.ReactElement {\n const [userProfile, setUserProfile] = useState<UserProfile | null>(null)\n const [userProfileLoading, setUserProfileLoading] = useState(true)\n\n const refetchUserProfile = useCallback(async () => {\n try {\n const profile = await fetchUser()\n setUserProfile(profile)\n } catch (err) {\n console.error('[RecordProvider] Failed to refetch user profile:', err)\n }\n }, [fetchUser])\n\n // Fetch user profile on mount and refresh periodically.\n // fetchUser returns null when not signed in — that's fine, no retry needed.\n useEffect(() => {\n let mounted = true\n setUserProfileLoading(true)\n fetchUser()\n .then(profile => { if (mounted) setUserProfile(profile) })\n .finally(() => { if (mounted) setUserProfileLoading(false) })\n\n const interval = setInterval(() => {\n if (mounted) {\n fetchUser().then(p => { if (mounted) setUserProfile(p) })\n }\n }, 30000)\n\n return () => { mounted = false; clearInterval(interval) }\n }, [fetchUser])\n\n const authValue: RecordAuthContextValue = useMemo(() => ({\n userProfile,\n userProfileLoading,\n refetchUserProfile,\n allowAnonymous,\n getAuthToken: getAuthTokenProp,\n }), [userProfile, userProfileLoading, refetchUserProfile, allowAnonymous, getAuthTokenProp])\n\n return (\n <RecordAuthContext.Provider value={authValue}>\n <ScopeRegistryProvider>\n {children}\n </ScopeRegistryProvider>\n </RecordAuthContext.Provider>\n )\n}\n\n// ============================================================================\n// Main Entry Point\n// ============================================================================\n\n/**\n * RecordProvider - Main entry point for storage.\n *\n * Two modes:\n * 1. **Single-scope (backward compat):** Pass `roomId` + `schemas`. Opens one WS connection.\n * 2. **Multi-scope:** Omit `roomId`. Only provides auth + ScopeRegistry.\n * Use `<RecordScope>` components for individual WS connections.\n *\n * @example\n * ```tsx\n * // Single-scope (backward compat)\n * <RecordProvider roomId=\"my-app\" schemas={schemas}>\n * <App />\n * </RecordProvider>\n *\n * // Multi-scope\n * <RecordProvider>\n * <RecordScope roomId=\"app:slack-clone\" schemas={appSchemas}>\n * <RecordScope roomId={`conv:${channelId}`} schemas={convSchemas}>\n * <ChannelView />\n * </RecordScope>\n * </RecordScope>\n * </RecordProvider>\n * ```\n */\nexport function RecordProvider({\n roomId,\n schemas = [],\n wsUrl,\n children,\n allowAnonymous = false,\n getAuthToken: getAuthTokenProp,\n}: {\n roomId?: string\n schemas?: CollectionSchema[]\n wsUrl?: string\n children: ReactNode\n allowAnonymous?: boolean\n getAuthToken?: () => Promise<string | null>\n}): React.ReactElement {\n const { isLoaded, isSignedIn } = useAuth()\n\n // Derive user profile from the JWT — no API call needed.\n // Returns null when not signed in (no error, no console spam).\n const fetchUser = useCallback(async (): Promise<UserProfile | null> => {\n if (!isSignedIn) return null\n const token = await getAuthToken()\n if (!token) return null\n try {\n const parts = token.split('.')\n const payload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')))\n return {\n id: payload.sub,\n name: payload.name ?? '',\n email: payload.email ?? '',\n imageUrl: payload.image ?? undefined,\n }\n } catch {\n return null\n }\n }, [isSignedIn])\n\n // Build getAuthToken function — use prop override or default to auth module\n const getAuthTokenFn = useCallback(async (): Promise<string | null> => {\n if (getAuthTokenProp) return getAuthTokenProp()\n if (!isSignedIn) return null\n return getAuthToken()\n }, [getAuthTokenProp, isSignedIn])\n\n // Not loaded yet — render nothing (no loading screens — that's the app's job)\n if (!isLoaded) {\n return <>{null}</>\n }\n\n // Not signed in and not allowing anonymous — render nothing\n if (!isSignedIn && !allowAnonymous) {\n return <>{null}</>\n }\n\n if (roomId) {\n return (\n <RecordProviderCore\n roomId={roomId}\n schemas={schemas}\n wsUrl={wsUrl}\n fetchUser={fetchUser}\n allowAnonymous={allowAnonymous}\n getAuthToken={getAuthTokenFn}\n >\n {children}\n </RecordProviderCore>\n )\n }\n\n return (\n <RecordProviderAuthOnly\n fetchUser={fetchUser}\n allowAnonymous={allowAnonymous}\n getAuthToken={getAuthTokenFn}\n >\n {children}\n </RecordProviderAuthOnly>\n )\n}\n","/**\n * RecordStore\n * \n * Manages query subscriptions with version-tracked caching.\n * Uses external store pattern for React integration.\n */\n\nimport type { RecordData } from './types'\n\ninterface QueryState {\n status: 'loading' | 'ready' | 'error'\n records: RecordData[] // Cached array - stable reference until data changes\n version: number // Incremented on every change\n error?: string\n}\n\n// Stable empty array - never changes reference\nconst EMPTY_RECORDS: RecordData[] = []\n\nexport class RecordStore {\n private queries = new Map<string, QueryState>()\n private listeners = new Map<string, Set<() => void>>()\n /** Reference count for each query - only send SUBSCRIBE on first, UNSUBSCRIBE on last */\n private refCounts = new Map<string, number>()\n /** Track the single subscriptionId per queryKey (for deduplication) */\n private activeSubscriptions = new Map<string, string>()\n\n subscribe(queryKey: string, listener: () => void): () => void {\n const set = this.listeners.get(queryKey) ?? new Set()\n set.add(listener)\n this.listeners.set(queryKey, set)\n return () => {\n set.delete(listener)\n if (set.size === 0) {\n this.listeners.delete(queryKey)\n }\n }\n }\n\n getSnapshot(queryKey: string): RecordData[] {\n // Return stable empty array if query doesn't exist\n const state = this.queries.get(queryKey)\n if (!state) return EMPTY_RECORDS\n return state.records\n }\n\n getStatus(queryKey: string): 'loading' | 'ready' | 'error' {\n return this.queries.get(queryKey)?.status ?? 'loading'\n }\n\n getError(queryKey: string): string | undefined {\n return this.queries.get(queryKey)?.error\n }\n\n /**\n * Initialize a query subscription.\n * Returns true if this is the FIRST subscriber (should send SUBSCRIBE).\n */\n initQuery(queryKey: string): boolean {\n const prevCount = this.refCounts.get(queryKey) ?? 0\n this.refCounts.set(queryKey, prevCount + 1)\n \n if (!this.queries.has(queryKey)) {\n this.queries.set(queryKey, { status: 'loading', records: [], version: 0 })\n }\n \n // Return true if this is the first subscriber\n return prevCount === 0\n }\n \n /**\n * Release a query subscription.\n * Returns true if this was the LAST subscriber (should send UNSUBSCRIBE).\n */\n releaseQuery(queryKey: string): boolean {\n const count = (this.refCounts.get(queryKey) ?? 1) - 1\n \n if (count <= 0) {\n this.refCounts.delete(queryKey)\n this.activeSubscriptions.delete(queryKey)\n return true // Last subscriber\n }\n \n this.refCounts.set(queryKey, count)\n return false // Still has subscribers\n }\n \n /** Store the subscriptionId for a queryKey (for routing server responses) */\n setSubscriptionId(queryKey: string, subscriptionId: string): void {\n this.activeSubscriptions.set(queryKey, subscriptionId)\n }\n \n /** Get the subscriptionId for a queryKey */\n getSubscriptionId(queryKey: string): string | undefined {\n return this.activeSubscriptions.get(queryKey)\n }\n\n // Handle QUERY_RESULT from server\n setQueryResult(queryKey: string, records: RecordData[]): void {\n const current = this.queries.get(queryKey)\n\n this.queries.set(queryKey, {\n status: 'ready',\n records, // New array reference\n version: (current?.version ?? 0) + 1,\n })\n this.notify(queryKey)\n }\n\n /** Check if a record exists in a query's results */\n hasRecord(queryKey: string, recordId: string): boolean {\n const state = this.queries.get(queryKey)\n if (!state) return false\n return state.records.some(r => r.recordId === recordId)\n }\n\n // Handle RECORD_CHANGE from server\n applyChange(\n queryKey: string,\n record: RecordData,\n changeType: 'create' | 'update' | 'delete'\n ): void {\n const state = this.queries.get(queryKey)\n if (!state) return\n\n let newRecords: RecordData[]\n\n if (changeType === 'delete') {\n newRecords = state.records.filter(r => r.recordId !== record.recordId)\n } else if (changeType === 'create') {\n // Check if record already exists (prevent duplicates from race conditions)\n const exists = state.records.some(r => r.recordId === record.recordId)\n if (exists) {\n // If it exists, treat as update instead\n newRecords = state.records.map(r => r.recordId === record.recordId ? record : r)\n } else {\n // Append (correct for asc order, which is the common case for real-time data)\n newRecords = [...state.records, record]\n }\n } else {\n // update\n newRecords = state.records.map(r => r.recordId === record.recordId ? record : r)\n }\n\n this.queries.set(queryKey, {\n ...state,\n records: newRecords,\n version: state.version + 1,\n })\n this.notify(queryKey)\n }\n\n /**\n * Reset a query to loading state (used on WebSocket reconnect).\n * Preserves stale records so the UI can show them while reconnecting.\n */\n resetToLoading(queryKey: string): void {\n const current = this.queries.get(queryKey)\n if (!current) return\n\n this.queries.set(queryKey, {\n ...current,\n status: 'loading',\n version: current.version + 1,\n })\n this.notify(queryKey)\n }\n\n setError(queryKey: string, error: string): void {\n const current = this.queries.get(queryKey)\n this.queries.set(queryKey, {\n status: 'error',\n records: current?.records ?? [],\n version: (current?.version ?? 0) + 1,\n error,\n })\n this.notify(queryKey)\n }\n\n // Cleanup when query is no longer needed\n removeQuery(queryKey: string): void {\n this.queries.delete(queryKey)\n this.listeners.delete(queryKey)\n }\n\n private notify(queryKey: string): void {\n const set = this.listeners.get(queryKey)\n if (set) {\n set.forEach(fn => fn())\n }\n }\n}\n","/**\n * ScopeRegistry\n *\n * React context that maps collection names to scope entries.\n * RecordScope registers its collections on mount, and hooks\n * (useQuery, useMutations) resolve the correct scope by collection name.\n *\n * Each registration is tagged with a scopeId so that unregister only\n * removes entries owned by the calling scope — preventing one scope\n * from breaking another when both register the same collections.\n */\n\nimport { createContext, useContext, useCallback, useRef, useMemo, type ReactNode } from 'react'\nimport type { RecordStore } from './store'\nimport type { RoomConnectionState } from './types'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ScopeEntry {\n store: RecordStore\n sendMessage: (msg: { type: string; payload: unknown }) => void\n sendConfirmed: (\n msg: { type: string; payload: Record<string, unknown> },\n timeoutMs?: number,\n ) => Promise<unknown>\n registerSubscription: (subscriptionId: string, queryKey: string) => void\n unregisterSubscription: (subscriptionId: string) => void\n sendBinary: (data: Uint8Array) => void\n onBinaryMessage: (handler: (data: ArrayBuffer) => void) => () => void\n registerYjsJoinHandler: (\n docKey: string,\n handler: (canWrite: boolean) => void,\n ) => () => void\n ready: boolean\n status: RoomConnectionState\n}\n\ninterface Registration {\n scopeId: string\n entry: ScopeEntry\n}\n\ninterface ScopeRegistryValue {\n register: (scopeId: string, collections: string[], entry: ScopeEntry) => void\n unregister: (scopeId: string, collections: string[]) => void\n resolve: (collection: string) => ScopeEntry | null\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst ScopeRegistryContext = createContext<ScopeRegistryValue | null>(null)\n\nexport function useScopeRegistry(): ScopeRegistryValue | null {\n return useContext(ScopeRegistryContext)\n}\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport function ScopeRegistryProvider({ children }: { children: ReactNode }) {\n const mapRef = useRef(new Map<string, Registration>())\n\n const register = useCallback((scopeId: string, collections: string[], entry: ScopeEntry) => {\n for (const name of collections) {\n mapRef.current.set(name, { scopeId, entry })\n }\n }, [])\n\n const unregister = useCallback((scopeId: string, collections: string[]) => {\n for (const name of collections) {\n const existing = mapRef.current.get(name)\n // Only unregister if this scope owns the registration\n if (existing?.scopeId === scopeId) {\n mapRef.current.delete(name)\n }\n }\n }, [])\n\n const resolve = useCallback((collection: string): ScopeEntry | null => {\n return mapRef.current.get(collection)?.entry ?? null\n }, [])\n\n const value = useMemo(() => ({ register, unregister, resolve }), [register, unregister, resolve])\n\n return (\n <ScopeRegistryContext.Provider value={value}>\n {children}\n </ScopeRegistryContext.Provider>\n )\n}\n","/**\n * Server Error Parser\n * \n * Parses server-side error strings into user-friendly messages.\n * Covers RBAC permission errors, validation errors, and generic errors.\n */\n\nexport interface ServerErrorInfo {\n title: string\n detail: string\n /** True for RBAC/permission errors (shown as toasts). False for validation/other (shown in error overlay). */\n isPermissionError: boolean\n}\n\n/**\n * Humanize a collection slug (e.g. \"rbac-notes\" → \"Notes\", \"team-posts\" → \"Team Posts\").\n */\nfunction humanizeCollection(slug: string): string {\n return slug\n .replace(/^rbac-/, '')\n .split(/[-_]/)\n .map(w => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ')\n}\n\n/**\n * Humanize a role name for display (e.g. \"viewer\" → \"Viewer\").\n */\nfunction humanizeRole(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1)\n}\n\n/**\n * Parse a server error string into a user-friendly message.\n * Handles RBAC errors, validation errors, and falls back to a generic error.\n */\nexport function parseServerError(error: string): ServerErrorInfo {\n // ── RBAC Errors ──────────────────────────────────────────────────────\n\n // UPDATE DENIED: role=viewer, collection=tasks\n const updateMatch = error.match(/^UPDATE DENIED: role=(\\w+), collection=(.+)/)\n if (updateMatch) {\n return {\n title: `${humanizeRole(updateMatch[1])}s can't edit ${humanizeCollection(updateMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const createMatch = error.match(/^CREATE DENIED: role=(\\w+), collection=(.+)/)\n if (createMatch) {\n return {\n title: `${humanizeRole(createMatch[1])}s can't create ${humanizeCollection(createMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const deleteMatch = error.match(/^DELETE DENIED: role=(\\w+), collection=(.+)/)\n if (deleteMatch) {\n return {\n title: `${humanizeRole(deleteMatch[1])}s can't delete ${humanizeCollection(deleteMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const readMatch = error.match(/^READ DENIED: role=(\\w+), collection=(.+)/)\n if (readMatch) {\n return {\n title: `${humanizeRole(readMatch[1])}s can't view ${humanizeCollection(readMatch[2])}`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const fieldMatch = error.match(/^FIELD ERROR: Cannot update field '(\\w+)'.*role '(\\w+)'/)\n if (fieldMatch) {\n return {\n title: `${humanizeRole(fieldMatch[2])}s can't edit \"${fieldMatch[1]}\"`,\n detail: '',\n isPermissionError: true,\n }\n }\n\n const fieldGenericMatch = error.match(/^FIELD ERROR: (.+)/)\n if (fieldGenericMatch) {\n return {\n title: 'Field not editable',\n detail: '',\n isPermissionError: true,\n }\n }\n\n const permMatch = error.match(/^Permission denied: (.+)/)\n if (permMatch) {\n return {\n title: permMatch[1].charAt(0).toUpperCase() + permMatch[1].slice(1),\n detail: '',\n isPermissionError: true,\n }\n }\n\n // ── Validation Errors ────────────────────────────────────────────────\n\n // Missing required field: fieldName\n const requiredMatch = error.match(/^Missing required field: (.+)/)\n if (requiredMatch) {\n return {\n title: 'Missing field',\n detail: `\"${requiredMatch[1]}\" is required`,\n isPermissionError: false,\n }\n }\n\n // Cannot change immutable field: fieldName\n const immutableMatch = error.match(/^Cannot change immutable field: (.+)/)\n if (immutableMatch) {\n return {\n title: 'Cannot modify',\n detail: `\"${immutableMatch[1]}\" cannot be changed after creation`,\n isPermissionError: false,\n }\n }\n\n // Field 'x' must be your user ID\n const userBoundMatch = error.match(/^Field '(.+)' must be your user ID/)\n if (userBoundMatch) {\n return {\n title: 'Invalid value',\n detail: `\"${userBoundMatch[1]}\" must be your own user ID`,\n isPermissionError: false,\n }\n }\n\n // ── Fallback ─────────────────────────────────────────────────────────\n\n return {\n title: 'Error',\n detail: error,\n isPermissionError: false,\n }\n}\n","/**\n * RecordScope\n *\n * Opens a direct WebSocket connection to a RecordRoom DO.\n * Manages subscriptions, reconnection, and state via RecordStore.\n * Registers collections in ScopeRegistry so hooks resolve to the right scope.\n *\n * @example\n * ```tsx\n * <RecordProvider>\n * <RecordScope\n * roomId=\"app:my-app\"\n * schemas={appSchemas}\n * appId=\"my-app\"\n * sharedScopes={[\n * { roomId: 'workspace:default', schemas: workspaceSchemas },\n * ]}\n * >\n * <App />\n * </RecordScope>\n * </RecordProvider>\n * ```\n */\n\nimport React, {\n useEffect,\n useState,\n useCallback,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react'\nimport type { CollectionSchema } from '../../shared/types'\nimport { RecordContext, type RecordContextValue } from './context'\nimport { useRecordAuth } from './context'\nimport { RecordStore } from './store'\nimport { useScopeRegistry, type ScopeEntry } from './ScopeRegistry'\nimport { getAuthToken } from '../auth'\nimport { wsLog } from './ws-log'\nimport { parseServerError } from './serverErrors'\nimport type { RoomUser, RoomConnectionState, RecordData } from './types'\nimport { MSG } from '@/shared/protocol/constants'\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction recordMatchesWhere(\n record: RecordData,\n where?: Record<string, unknown>,\n): boolean {\n if (!where) return true\n const r = record as RecordData & { data?: Record<string, unknown> }\n const data = r.data\n if (!data) return false\n // Schema columns take precedence over envelope fields — mirrors the\n // server-side where-builder in executeTableQuery so initial load and\n // live updates stay in sync when a schema defines a column named\n // 'createdBy' (e.g. the messaging `channels` collection).\n return Object.entries(where).every(([key, value]) => {\n if (key in data) return data[key] === value\n if (key === 'recordId') return r.recordId === value\n if (key === 'createdBy') return r.createdBy === value\n return false\n })\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface SharedScopeConfig {\n roomId: string\n schemas: CollectionSchema[]\n}\n\ninterface RecordScopeProps {\n roomId: string\n schemas: CollectionSchema[]\n children?: ReactNode\n /** App ID passed to the server for schema resolution. */\n appId: string\n /** Additional scopes to connect (headless — no children, just register collections). */\n sharedScopes?: SharedScopeConfig[]\n /** WebSocket base URL override. Derived from window.location if omitted. */\n wsUrl?: string\n /** Path prefix for WebSocket route. Default: '/ws'. */\n wsPathPrefix?: string\n /** Don't register collections in ScopeRegistry (prevents name collisions). */\n isolated?: boolean\n}\n\n// ============================================================================\n// Headless scope — opens a WS connection and registers collections only\n// ============================================================================\n\nfunction HeadlessScope({ roomId, schemas, appId, wsUrl, wsPathPrefix }: {\n roomId: string\n schemas: CollectionSchema[]\n appId: string\n wsUrl?: string\n wsPathPrefix?: string\n}) {\n return (\n <ScopeConnection\n roomId={roomId}\n schemas={schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n />\n )\n}\n\n// ============================================================================\n// Core WebSocket connection logic (shared by primary + headless scopes)\n// ============================================================================\n\nfunction ScopeConnection({\n roomId,\n schemas,\n appId,\n children,\n wsUrl,\n wsPathPrefix = '/ws',\n isolated = false,\n}: {\n roomId: string\n schemas: CollectionSchema[]\n appId: string\n children?: ReactNode\n wsUrl?: string\n wsPathPrefix?: string\n isolated?: boolean\n}) {\n const auth = useRecordAuth()\n const registry = useScopeRegistry()\n\n const scopeIdRef = useRef(`scope-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`)\n\n // Room state\n const [roomRole, setRoomRole] = useState<string | null>(null)\n const [allUsers, setAllUsers] = useState<RoomUser[]>([])\n const [usersLoaded, setUsersLoaded] = useState(false)\n const [status, setStatus] = useState<RoomConnectionState>('connecting')\n const [ready, setReady] = useState(false)\n const [discoveredSchemas, setDiscoveredSchemas] = useState<CollectionSchema[]>([])\n\n // Refs\n const storeRef = useRef<RecordStore>(new RecordStore())\n const wsRef = useRef<WebSocket | null>(null)\n const subscriptionMapRef = useRef<Map<string, string>>(new Map())\n const binaryHandlersRef = useRef<Set<(data: ArrayBuffer) => void>>(new Set())\n const yjsJoinHandlersRef = useRef<Map<string, Set<(canWrite: boolean) => void>>>(new Map())\n const pendingRequestsRef = useRef<Map<string, {\n resolve: (data?: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n }>>(new Map())\n const reconnectAttemptRef = useRef(0)\n const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n // Auth refs (stable across renders)\n const userProfileRef = useRef(auth?.userProfile ?? null)\n userProfileRef.current = auth?.userProfile ?? null\n const getAuthTokenRef = useRef(auth?.getAuthToken ?? null)\n getAuthTokenRef.current = auth?.getAuthToken ?? null\n const authCallbacksRef = useRef({\n onPermissionError: auth?.onPermissionError,\n onValidationError: auth?.onValidationError,\n })\n authCallbacksRef.current.onPermissionError = auth?.onPermissionError\n authCallbacksRef.current.onValidationError = auth?.onValidationError\n const allowAnonymous = auth?.allowAnonymous ?? false\n\n // ── Message handler ──────────────────────────────────────────────────\n\n const handleMessage = useCallback((event: MessageEvent) => {\n if (event.data instanceof ArrayBuffer) {\n binaryHandlersRef.current.forEach((h) => h(event.data as ArrayBuffer))\n return\n }\n\n let msg: { type: string; payload: unknown }\n try {\n msg = JSON.parse(event.data as string)\n } catch {\n console.error('[RecordScope] Failed to parse message')\n return\n }\n\n const { type, payload } = msg\n\n switch (type) {\n case MSG.USER_INFO: {\n const { role } = payload as { role: string }\n setRoomRole(role)\n setReady(true)\n reconnectAttemptRef.current = 0\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ type: MSG.USER_LIST, payload: {} }))\n }\n break\n }\n\n case MSG.USER_LIST:\n setAllUsers((payload as { users: RoomUser[] }).users)\n setUsersLoaded(true)\n break\n\n case MSG.QUERY_RESULT: {\n const { subscriptionId, records } = payload as { subscriptionId: string; records: RecordData[] }\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setQueryResult(queryKey, records)\n break\n }\n }\n break\n }\n\n case MSG.RECORD_CHANGE: {\n const { collection, record, changeType } = payload as {\n collection: string; record: RecordData; changeType: 'create' | 'update' | 'delete'\n }\n for (const [, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey) as { collection: string; where?: Record<string, unknown> }\n if (query.collection !== collection) continue\n const matches = recordMatchesWhere(record, query.where)\n const exists = storeRef.current.hasRecord(queryKey, record.recordId)\n if (changeType === 'delete') {\n if (exists) storeRef.current.applyChange(queryKey, record, 'delete')\n } else if (changeType === 'create') {\n if (matches) storeRef.current.applyChange(queryKey, record, 'create')\n } else {\n if (matches && exists) storeRef.current.applyChange(queryKey, record, 'update')\n else if (matches && !exists) storeRef.current.applyChange(queryKey, record, 'create')\n else if (!matches && exists) storeRef.current.applyChange(queryKey, record, 'delete')\n }\n } catch { /* skip invalid query keys */ }\n }\n break\n }\n\n case MSG.ERROR: {\n const { subscriptionId, error } = payload as { subscriptionId?: string; error: string }\n if (subscriptionId) {\n for (const [subId, queryKey] of subscriptionMapRef.current) {\n if (subId === subscriptionId) {\n storeRef.current.setError(queryKey, error)\n break\n }\n }\n } else {\n const parsed = parseServerError(error)\n if (parsed.isPermissionError) {\n authCallbacksRef.current.onPermissionError?.(parsed.title, parsed.detail)\n } else {\n authCallbacksRef.current.onValidationError?.(parsed.title, parsed.detail)\n }\n }\n break\n }\n\n case MSG.YJS_JOIN: {\n const { collection, recordId, fieldName, canWrite } = payload as {\n collection: string; recordId: string; fieldName: string; canWrite: boolean\n }\n const docKey = `${collection}:${recordId}:${fieldName}`\n yjsJoinHandlersRef.current.get(docKey)?.forEach((h) => h(canWrite))\n break\n }\n\n case MSG.ACK: {\n const { requestId, success, error, ...rest } = payload as {\n requestId: string; success: boolean; error?: string; [key: string]: unknown\n }\n const pending = pendingRequestsRef.current.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequestsRef.current.delete(requestId)\n success ? pending.resolve(rest) : pending.reject(new Error(error || 'Mutation rejected'))\n }\n break\n }\n\n case MSG.LIST_SCHEMAS: {\n const { schemas: list } = payload as { schemas: CollectionSchema[] }\n setDiscoveredSchemas(list ?? [])\n break\n }\n\n case MSG.RESUBSCRIBE: {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) {\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip */ }\n }\n }\n break\n }\n }\n }, [roomId])\n\n // ── WebSocket connect ────────────────────────────────────────────────\n\n const connect = useCallback(async () => {\n const profile = userProfileRef.current\n const hasTokenProvider = !!getAuthTokenRef.current\n if (!profile && !hasTokenProvider && !allowAnonymous) return\n\n if (wsRef.current?.readyState === WebSocket.OPEN || wsRef.current?.readyState === WebSocket.CONNECTING) return\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = wsUrl?.replace(/^http/, 'ws') ?? `${protocol}//${window.location.host}`\n const params = new URLSearchParams()\n\n // Identity is derived server-side from the verified JWT — any\n // client-supplied identity params would be stripped at the worker\n // edge, so we don't send them.\n try {\n const tokenFn = getAuthTokenRef.current ?? getAuthToken\n const token = await tokenFn()\n if (token) params.set('token', token)\n } catch { /* token fetch failed — connect anyway if anonymous */ }\n\n params.set('appId', appId)\n\n const url = `${baseUrl}${wsPathPrefix}/${roomId}?${params.toString()}`\n wsLog('connecting', roomId)\n const ws = new WebSocket(url)\n ws.binaryType = 'arraybuffer'\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', roomId)\n setStatus('connected')\n // Re-subscribe all active queries\n for (const [subscriptionId, queryKey] of subscriptionMapRef.current) {\n try {\n const query = JSON.parse(queryKey)\n ws.send(JSON.stringify({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } }))\n } catch { /* skip */ }\n }\n }\n\n ws.onmessage = handleMessage\n\n ws.onclose = () => {\n wsLog('disconnected', roomId)\n setStatus('disconnected')\n setReady(false)\n wsRef.current = null\n for (const [, queryKey] of subscriptionMapRef.current) storeRef.current.resetToLoading(queryKey)\n for (const [, pending] of pendingRequestsRef.current) {\n clearTimeout(pending.timer)\n pending.reject(new Error('WebSocket disconnected'))\n }\n pendingRequestsRef.current.clear()\n const attempt = reconnectAttemptRef.current\n const delay = Math.min(1000 * Math.pow(2, attempt), 30000)\n reconnectAttemptRef.current = attempt + 1\n reconnectTimeoutRef.current = setTimeout(connect, delay)\n }\n\n ws.onerror = () => {}\n }, [roomId, wsUrl, wsPathPrefix, handleMessage, allowAnonymous, appId])\n\n // ── Disconnect helper ─────────────────────────────────────────────────\n\n const disconnect = useCallback(() => {\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current)\n reconnectTimeoutRef.current = null\n }\n const ws = wsRef.current\n if (ws) {\n wsLog('closing', roomId)\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n wsRef.current = null\n }\n setStatus('connecting')\n setReady(false)\n reconnectAttemptRef.current = 0\n }, [roomId])\n\n // ── Auth identity change → disconnect and reconnect ──────────────────\n // Fires when: sign-in, sign-out, account switch, or initial load completes.\n // The identity is the user's profile ID (null = anonymous).\n\n const userProfileId = auth?.userProfile?.id ?? null\n const userProfileLoading = auth?.userProfileLoading ?? false\n\n useEffect(() => {\n // Still loading auth — wait\n if (userProfileLoading) return\n\n // Tear down existing connection (if any) so we reconnect with new identity\n disconnect()\n\n // Connect if we have auth OR anonymous is allowed\n if (userProfileId || allowAnonymous) {\n connect()\n }\n\n return disconnect\n }, [userProfileId, userProfileLoading, allowAnonymous, connect, disconnect])\n\n // Reconnect on tab focus\n useEffect(() => {\n const onVisible = () => {\n if (document.visibilityState === 'visible' && wsRef.current?.readyState !== WebSocket.OPEN) {\n reconnectAttemptRef.current = 0\n connect()\n }\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n }, [connect])\n\n // ── Send helpers ─────────────────────────────────────────────────────\n\n const sendMessage = useCallback((message: { type: string; payload: unknown }) => {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message))\n }, [])\n\n const sendBinary = useCallback((data: Uint8Array) => {\n const ws = wsRef.current\n if (ws?.readyState === WebSocket.OPEN) ws.send(data)\n }, [])\n\n const onBinaryMessage = useCallback((handler: (data: ArrayBuffer) => void) => {\n binaryHandlersRef.current.add(handler)\n return () => { binaryHandlersRef.current.delete(handler) }\n }, [])\n\n const registerYjsJoinHandler = useCallback((docKey: string, handler: (canWrite: boolean) => void) => {\n if (!yjsJoinHandlersRef.current.has(docKey)) yjsJoinHandlersRef.current.set(docKey, new Set())\n yjsJoinHandlersRef.current.get(docKey)!.add(handler)\n return () => {\n const handlers = yjsJoinHandlersRef.current.get(docKey)\n if (handlers) { handlers.delete(handler); if (handlers.size === 0) yjsJoinHandlersRef.current.delete(docKey) }\n }\n }, [])\n\n const sendConfirmed = useCallback((\n message: { type: string; payload: Record<string, unknown> },\n timeoutMs = 10000,\n ): Promise<unknown> => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return Promise.reject(new Error('WebSocket not connected'))\n const requestId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pendingRequestsRef.current.delete(requestId)\n reject(new Error('Mutation confirmation timed out'))\n }, timeoutMs)\n pendingRequestsRef.current.set(requestId, { resolve, reject, timer })\n ws.send(JSON.stringify({ ...message, payload: { ...message.payload, requestId } }))\n })\n }, [])\n\n const setUserRole = useCallback((userId: string, role: string) => {\n sendMessage({ type: MSG.SET_ROLE, payload: { userId, role } })\n }, [sendMessage])\n\n const requestUserList = useCallback(() => {\n sendMessage({ type: MSG.USER_LIST, payload: {} })\n }, [sendMessage])\n\n const registerSubscription = useCallback((subscriptionId: string, queryKey: string) => {\n subscriptionMapRef.current.set(subscriptionId, queryKey)\n }, [])\n\n const unregisterSubscription = useCallback((subscriptionId: string) => {\n subscriptionMapRef.current.delete(subscriptionId)\n }, [])\n\n // Auto-discover schemas\n useEffect(() => {\n if (ready) sendMessage({ type: MSG.LIST_SCHEMAS, payload: {} })\n }, [ready, sendMessage])\n\n // ── ScopeRegistry ────────────────────────────────────────────────────\n\n const scopeEntryRef = useRef<ScopeEntry | null>(null)\n if (!scopeEntryRef.current) {\n scopeEntryRef.current = {\n store: storeRef.current, sendMessage, sendConfirmed,\n registerSubscription, unregisterSubscription, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, ready, status,\n }\n }\n scopeEntryRef.current.ready = ready\n scopeEntryRef.current.status = status\n\n const registeredSchemasRef = useRef<CollectionSchema[] | null>(null)\n if (!isolated && registry && schemas !== registeredSchemasRef.current) {\n if (registeredSchemasRef.current) {\n registry.unregister(scopeIdRef.current, registeredSchemasRef.current.map((s) => s.name))\n }\n const names = schemas.map((s) => s.name)\n if (names.length > 0) registry.register(scopeIdRef.current, names, scopeEntryRef.current!)\n registeredSchemasRef.current = schemas\n }\n\n useEffect(() => {\n if (isolated || !registry) return\n return () => {\n const names = (registeredSchemasRef.current ?? []).map((s) => s.name)\n if (names.length > 0) registry.unregister(scopeIdRef.current, names)\n }\n }, [isolated, registry, roomId])\n\n // ── Context ──────────────────────────────────────────────────────────\n\n const registeredCollections = useMemo(() => new Set(schemas.map((s) => s.name)), [schemas])\n\n const value: RecordContextValue = useMemo(() => ({\n store: storeRef.current, roomId, registeredCollections,\n userProfile: auth?.userProfile ?? null,\n userProfileLoading: auth?.userProfileLoading ?? false,\n refetchUserProfile: auth?.refetchUserProfile ?? (async () => {}),\n roomRole, allUsers, usersLoaded, status, ready, discoveredSchemas,\n setUserRole, requestUserList, registerSubscription, unregisterSubscription,\n sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, sendConfirmed,\n }), [\n roomId, registeredCollections, auth?.userProfile, auth?.userProfileLoading,\n auth?.refetchUserProfile, roomRole, allUsers, usersLoaded, status, ready,\n discoveredSchemas, setUserRole, requestUserList, registerSubscription,\n unregisterSubscription, sendMessage, sendBinary, onBinaryMessage,\n registerYjsJoinHandler, sendConfirmed,\n ])\n\n if (!children) return null\n return <RecordContext.Provider value={value}>{children}</RecordContext.Provider>\n}\n\n// ============================================================================\n// RecordScope (public API)\n// ============================================================================\n\nexport function RecordScope({\n roomId,\n schemas,\n children,\n appId,\n sharedScopes,\n wsUrl,\n wsPathPrefix = '/ws',\n isolated = false,\n}: RecordScopeProps) {\n return (\n <>\n {sharedScopes?.map((shared) => (\n <HeadlessScope\n key={shared.roomId}\n roomId={shared.roomId}\n schemas={shared.schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n />\n ))}\n <ScopeConnection\n roomId={roomId}\n schemas={schemas}\n appId={appId}\n wsUrl={wsUrl}\n wsPathPrefix={wsPathPrefix}\n isolated={isolated}\n >\n {children}\n </ScopeConnection>\n </>\n )\n}\n","/**\n * Shared WebSocket connection logger with active connection count.\n */\n\nlet activeCount = 0\n\nexport function wsLog(event: 'connecting' | 'connected' | 'disconnected' | 'closing', label: string) {\n if (event === 'connected') activeCount++\n if (event === 'closing') activeCount--\n\n console.log(`[ds:ws] ${event} → ${label} (${activeCount} active)`)\n}\n","/**\n * useUser Hook\n * \n * Access current user with profile data and room role.\n */\n\nimport { useMemo } from 'react'\nimport { useRecordContext } from '../context'\nimport type { User } from '../types'\n\n/**\n * Hook to access current user.\n * \n * Returns merged user data:\n * - Profile from API (karma, credits, subscription, isAdmin)\n * - Role from room (derived from user-roles collection)\n * \n * The role is the user's role in THIS miniapp/room, which can be\n * different from their global isAdmin status.\n * \n * @example\n * ```tsx\n * const { user, refetch, isLoading } = useUser()\n * \n * // Check role\n * if (user?.role === 'admin') { ... }\n * if (user?.role === 'intern') { ... }\n * \n * // Access karma/credits\n * const karma = user?.karma?.total ?? 0\n * \n * // Refetch after expensive operations\n * await refetch() // Updates user.credits\n * ```\n */\nexport function useUser(): {\n user: User | null\n isLoading: boolean\n refetch: () => Promise<void>\n} {\n const { userProfile, userProfileLoading, refetchUserProfile, roomRole } = useRecordContext()\n \n // Merge profile + room role into unified User\n const user = useMemo((): User | null => {\n if (!userProfile) return null\n return {\n ...userProfile,\n role: roomRole ?? 'viewer', // Default to 'viewer' if no role set\n }\n }, [userProfile, roomRole])\n \n return { user, isLoading: userProfileLoading, refetch: refetchUserProfile }\n}\n","/**\n * useQuery Hook\n *\n * Subscribe to a query with real-time updates.\n * Resolves the correct scope via ScopeRegistry (multi-scope)\n * or falls back to useRecordContext() (single-scope backward compat).\n */\n\nimport { useEffect, useCallback, useRef, useMemo, useContext, useSyncExternalStore } from 'react'\nimport { RecordContext } from '../context'\nimport { useScopeRegistry } from '../ScopeRegistry'\nimport type { Query, RecordData } from '../types'\nimport { MSG } from '@/shared/protocol/constants'\n\n/**\n * Subscribe to a query with real-time updates.\n *\n * @example\n * ```tsx\n * const { records, status } = useQuery('tasks', {\n * where: { userId: me },\n * orderBy: 'createdAt',\n * orderDir: 'desc',\n * limit: 50\n * })\n * ```\n */\nexport function useQuery<T = unknown>(\n collection: string,\n options?: {\n where?: Record<string, unknown>\n orderBy?: string\n orderDir?: 'asc' | 'desc'\n limit?: number\n },\n): {\n records: RecordData<T>[]\n status: 'loading' | 'ready' | 'error'\n error?: string\n} {\n // Try scope resolution first (multi-scope), then fall back to RecordContext\n const registry = useScopeRegistry()\n const recordCtx = useContext(RecordContext)\n\n const scopeEntry = registry?.resolve(collection) ?? null\n\n // Prefer RecordContext when this scope handles the collection (avoids stale ScopeRegistry during navigation)\n const preferLocal = recordCtx?.registeredCollections?.has(collection) ?? false\n const store = preferLocal ? recordCtx!.store : (scopeEntry?.store ?? recordCtx?.store)\n const sendMessage = preferLocal ? recordCtx!.sendMessage : (scopeEntry?.sendMessage ?? recordCtx?.sendMessage)\n const registerSub = preferLocal ? recordCtx!.registerSubscription : (scopeEntry?.registerSubscription ?? recordCtx?.registerSubscription)\n const unregisterSub = preferLocal ? recordCtx!.unregisterSubscription : (scopeEntry?.unregisterSubscription ?? recordCtx?.unregisterSubscription)\n\n if (!store || !sendMessage || !registerSub || !unregisterSub) {\n throw new Error(\n `useQuery('${collection}'): No scope found. Wrap in a RecordProvider (with roomId) or a RecordScope that registers this collection.`,\n )\n }\n\n const optionsKey = JSON.stringify(options ?? null)\n\n const query: Query = useMemo(\n () => ({\n collection,\n where: options?.where,\n orderBy: options?.orderBy,\n orderDir: options?.orderDir,\n limit: options?.limit,\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }),\n [collection, optionsKey],\n )\n\n const queryKey = useMemo(() => JSON.stringify(query), [query])\n\n const subscriptionIdRef = useRef<string>(\n `sub-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n )\n\n useEffect(() => {\n const subscriptionId = subscriptionIdRef.current\n\n const isFirst = store.initQuery(queryKey)\n\n if (isFirst) {\n store.setSubscriptionId(queryKey, subscriptionId)\n registerSub(subscriptionId, queryKey)\n sendMessage({ type: MSG.SUBSCRIBE, payload: { subscriptionId, query } })\n }\n\n return () => {\n const activeSubId = store.getSubscriptionId(queryKey) ?? subscriptionId\n const isLast = store.releaseQuery(queryKey)\n\n if (isLast) {\n sendMessage({ type: MSG.UNSUBSCRIBE, payload: { subscriptionId: activeSubId } })\n unregisterSub(activeSubId)\n }\n }\n }, [queryKey, query, store, sendMessage, registerSub, unregisterSub, collection])\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => store.subscribe(queryKey, onStoreChange),\n [store, queryKey],\n )\n\n const getSnapshot = useCallback(\n () => store.getSnapshot(queryKey) as RecordData<T>[],\n [store, queryKey],\n )\n\n const records = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n const status = store.getStatus(queryKey)\n const error = store.getError(queryKey)\n\n // Memoize the return object so consumers get a stable reference\n // (same rationale as useMutations — prevents spurious effect re-runs).\n return useMemo(() => ({ records, status, error }), [records, status, error])\n}\n","/**\n * useMutations Hook\n *\n * Get mutation functions for a collection.\n * Resolves the correct scope via ScopeRegistry (multi-scope)\n * or falls back to useRecordContext() (single-scope backward compat).\n */\n\nimport { useCallback, useContext, useMemo } from 'react'\nimport { RecordContext } from '../context'\nimport { useScopeRegistry } from '../ScopeRegistry'\nimport { MSG } from '@/shared/protocol/constants'\n\n/**\n * Get mutation functions for a collection.\n *\n * Type contract:\n * - `create(data)` requires the **full** record shape `T`. New records\n * have no existing data to merge with, so all fields the schema\n * considers required must be present.\n * - `put(recordId, patch)` accepts a **`Partial<T>`**. The server\n * merges the patch into the existing row (`{...existing, ...patch}`),\n * so callers should send only the fields they want to change.\n *\n * @example\n * ```tsx\n * const { create, put, remove } = useMutations<Task>('tasks')\n *\n * // create needs the full Task shape\n * const id = await create({ title: 'New task', completed: false, priority: 1 })\n *\n * // put is a partial update — only the fields you want to change\n * await put(id, { completed: true })\n * await remove(id)\n * ```\n */\nexport function useMutations<T = unknown>(collection: string): {\n create: (data: T) => Promise<string>\n put: (recordId: string, data: Partial<T>) => Promise<void>\n remove: (recordId: string) => Promise<void>\n createConfirmed: (data: T) => Promise<string>\n putConfirmed: (recordId: string, data: Partial<T>) => Promise<void>\n removeConfirmed: (recordId: string) => Promise<void>\n} {\n // Try scope resolution first (multi-scope), then fall back to RecordContext\n const registry = useScopeRegistry()\n const recordCtx = useContext(RecordContext)\n\n const scopeEntry = registry?.resolve(collection) ?? null\n\n // Prefer RecordContext when this scope handles the collection (avoids stale ScopeRegistry during navigation)\n const preferLocal = recordCtx?.registeredCollections?.has(collection) ?? false\n const sendMessage = preferLocal ? recordCtx!.sendMessage : (scopeEntry?.sendMessage ?? recordCtx?.sendMessage)\n const sendConfirmed = preferLocal ? recordCtx!.sendConfirmed : (scopeEntry?.sendConfirmed ?? recordCtx?.sendConfirmed)\n\n if (!sendMessage || !sendConfirmed) {\n throw new Error(\n `useMutations('${collection}'): No scope found. Wrap in a RecordProvider (with roomId) or a RecordScope that registers this collection.`,\n )\n }\n\n const create = useCallback(\n async (data: T): Promise<string> => {\n const recordId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n sendMessage({ type: MSG.PUT, payload: { collection, recordId, data } })\n return recordId\n },\n [sendMessage, collection],\n )\n\n const put = useCallback(\n async (recordId: string, data: Partial<T>): Promise<void> => {\n sendMessage({ type: MSG.PUT, payload: { collection, recordId, data } })\n },\n [sendMessage, collection],\n )\n\n const remove = useCallback(\n async (recordId: string): Promise<void> => {\n sendMessage({ type: MSG.DELETE, payload: { collection, recordId } })\n },\n [sendMessage, collection],\n )\n\n const createConfirmed = useCallback(\n async (data: T): Promise<string> => {\n const recordId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`\n await sendConfirmed({\n type: MSG.PUT,\n payload: { collection, recordId, data: data as Record<string, unknown> },\n })\n return recordId\n },\n [sendConfirmed, collection],\n )\n\n const putConfirmed = useCallback(\n async (recordId: string, data: Partial<T>): Promise<void> => {\n await sendConfirmed({\n type: MSG.PUT,\n payload: { collection, recordId, data: data as Record<string, unknown> },\n })\n },\n [sendConfirmed, collection],\n )\n\n const removeConfirmed = useCallback(\n async (recordId: string): Promise<void> => {\n await sendConfirmed({ type: MSG.DELETE, payload: { collection, recordId } })\n },\n [sendConfirmed, collection],\n )\n\n // Memoize the return object so consumers get a stable reference.\n // Without this, every render produces a new object, which breaks any\n // useCallback/useEffect that depends on the useMutations() result\n // (e.g., cleanup effects re-fire and delete records they shouldn't).\n return useMemo(\n () => ({ create, put, remove, createConfirmed, putConfirmed, removeConfirmed }),\n [create, put, remove, createConfirmed, putConfirmed, removeConfirmed],\n )\n}\n","/**\n * useUsers Hook\n *\n * Access all users in the current room.\n * User data (name, email, imageUrl, role) comes from the RecordRoom's users collection.\n */\n\nimport { useEffect, useMemo } from 'react'\nimport { useRecordContext } from '../context'\nimport type { RoomUser } from '../types'\n\nexport function useUsers(): {\n users: RoomUser[]\n usersLoaded: boolean\n setRole: (userId: string, role: string) => void\n refresh: () => void\n} {\n const { allUsers, usersLoaded, setUserRole, requestUserList, ready } = useRecordContext()\n\n useEffect(() => {\n if (ready) requestUserList()\n }, [ready, requestUserList])\n\n const users = useMemo(() => allUsers, [allUsers])\n\n return { users, usersLoaded, setRole: setUserRole, refresh: requestUserList }\n}\n","/**\n * Yjs Collaborative Editing Hooks\n * \n * Real-time collaborative editing using Yjs.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport * as Y from 'yjs'\nimport { useRecordContext } from '../context'\nimport { MSG_YJS_SYNC, MSG_YJS_AWARENESS, MSG } from '@/shared/protocol/constants'\nimport {\n MSG_SYNC_STEP1,\n MSG_SYNC_STEP2,\n MSG_SYNC_UPDATE,\n Awareness,\n createEncoder,\n createDecoder,\n toUint8Array,\n writeVarUint,\n writeVarUint8Array,\n readVarUint,\n readVarUint8Array,\n} from '@/shared/protocol/yjs'\n\n// ============================================================================\n// useYjsField\n// ============================================================================\n\nexport interface UseYjsFieldResult {\n /** The Yjs document for this field */\n doc: Y.Doc\n /** Awareness instance for cursor/presence sync */\n awareness: Awareness\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n /** Force re-render counter (changes when doc updates) */\n updateCount: number\n}\n\n/**\n * Hook for collaborative editing of a Yjs field.\n * \n * @param collection - Collection name\n * @param recordId - Record ID\n * @param fieldName - Field name (must be type: 'yjs' in schema)\n * \n * @example\n * const { doc, synced, canWrite } = useYjsField('documents', docId, 'content')\n * const text = doc.getText('content')\n */\nexport function useYjsField(\n collection: string,\n recordId: string,\n fieldName: string\n): UseYjsFieldResult {\n const { sendMessage, sendBinary, onBinaryMessage, registerYjsJoinHandler, ready } = useRecordContext()\n const [synced, setSynced] = useState(false)\n const [canWrite, setCanWrite] = useState(false)\n const [updateCount, setUpdateCount] = useState(0)\n const canWriteRef = useRef(false)\n\n // Stable Yjs doc instance\n const docRef = useRef<Y.Doc | null>(null)\n if (!docRef.current) {\n docRef.current = new Y.Doc()\n }\n const doc = docRef.current\n\n // Stable awareness instance (one per doc)\n const awarenessRef = useRef<Awareness | null>(null)\n if (!awarenessRef.current) {\n awarenessRef.current = new Awareness(doc)\n }\n const awareness = awarenessRef.current\n\n const docKey = `${collection}:${recordId}:${fieldName}`\n\n // Keep ref in sync with state for use in callbacks\n useEffect(() => {\n canWriteRef.current = canWrite\n }, [canWrite])\n\n // Handle join response from server\n useEffect(() => {\n return registerYjsJoinHandler(docKey, setCanWrite)\n }, [docKey, registerYjsJoinHandler])\n\n // Handle incoming binary messages (sync + awareness)\n useEffect(() => {\n const handleBinaryMessage = (data: ArrayBuffer) => {\n const decoder = createDecoder(new Uint8Array(data))\n const messageType = readVarUint(decoder)\n\n // Handle awareness messages\n if (messageType === MSG_YJS_AWARENESS) {\n const msgDocKey = new TextDecoder().decode(readVarUint8Array(decoder))\n if (msgDocKey !== docKey) return\n const payload = readVarUint8Array(decoder)\n awareness.applyUpdate(payload)\n return\n }\n\n if (messageType !== MSG_YJS_SYNC) return\n\n const msgDocKey = new TextDecoder().decode(readVarUint8Array(decoder))\n if (msgDocKey !== docKey) return\n\n const syncType = readVarUint(decoder)\n const payload = readVarUint8Array(decoder)\n\n switch (syncType) {\n case MSG_SYNC_STEP1: {\n // Server sent state vector - respond with our diff\n const ourDiff = Y.encodeStateAsUpdate(doc, payload)\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_SYNC)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint(encoder, MSG_SYNC_STEP2)\n writeVarUint8Array(encoder, ourDiff)\n sendBinary(toUint8Array(encoder))\n setSynced(true)\n break\n }\n case MSG_SYNC_STEP2: {\n // Server sent full state diff\n Y.applyUpdate(doc, payload, 'server')\n setSynced(true)\n break\n }\n case MSG_SYNC_UPDATE: {\n // Server relayed update from another client\n Y.applyUpdate(doc, payload, 'server')\n break\n }\n }\n }\n\n return onBinaryMessage(handleBinaryMessage)\n }, [doc, awareness, docKey, sendBinary, onBinaryMessage])\n\n // Send local awareness changes to server\n useEffect(() => {\n if (!ready) return\n\n const handleAwarenessUpdate = ({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {\n const changedClients = added.concat(updated).concat(removed)\n if (changedClients.length === 0) return\n\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_AWARENESS)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint8Array(encoder, awareness.encodeUpdate(changedClients))\n sendBinary(toUint8Array(encoder))\n }\n\n awareness.on('update', handleAwarenessUpdate)\n return () => { awareness.off('update', handleAwarenessUpdate) }\n }, [awareness, docKey, sendBinary, ready])\n\n // Join channel when ready - re-join on reconnect\n useEffect(() => {\n if (!ready) {\n // Reset state when disconnected\n console.log('[YJS] Not ready, resetting:', docKey)\n setSynced(false)\n setCanWrite(false)\n return\n }\n\n console.log('[YJS] Joining:', docKey)\n sendMessage({ type: MSG.YJS_JOIN, payload: { collection, recordId, fieldName } })\n\n return () => {\n // Clear local awareness state before leaving\n awareness.setLocalState(null)\n console.log('[YJS] Leaving:', docKey)\n sendMessage({ type: MSG.YJS_LEAVE, payload: { collection, recordId, fieldName } })\n }\n }, [ready, collection, recordId, fieldName, sendMessage, docKey, awareness])\n\n // Send local updates to server\n useEffect(() => {\n const handleUpdate = (update: Uint8Array, origin: unknown) => {\n setUpdateCount(c => c + 1)\n\n // Only send local updates when we have write permission\n if (origin === 'server' || !canWriteRef.current) return\n\n const encoder = createEncoder()\n writeVarUint(encoder, MSG_YJS_SYNC)\n writeVarUint8Array(encoder, new TextEncoder().encode(docKey))\n writeVarUint(encoder, MSG_SYNC_UPDATE)\n writeVarUint8Array(encoder, update)\n sendBinary(toUint8Array(encoder))\n }\n\n doc.on('update', handleUpdate)\n return () => { doc.off('update', handleUpdate) }\n }, [doc, docKey, sendBinary])\n\n // synced is only true when WebSocket is connected AND initial sync is complete\n return { doc, awareness, synced: ready && synced, canWrite, updateCount }\n}\n\n// ============================================================================\n// useYjsText\n// ============================================================================\n\nexport interface UseYjsTextResult {\n /** Current text content */\n text: string\n /** Set text content (replaces entire content) */\n setText: (value: string) => void\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n}\n\n/**\n * Simplified hook for collaborative text editing.\n * \n * Provides a string-based API instead of raw Yjs doc access.\n * Perfect for textarea/input fields.\n * \n * @param collection - Collection name\n * @param recordId - Record ID\n * @param fieldName - Field name (must be type: 'yjs' in schema)\n * \n * @example\n * const { text, setText, synced, canWrite } = useYjsText('documents', docId, 'content')\n * \n * <textarea \n * value={text} \n * onChange={(e) => setText(e.target.value)}\n * disabled={!synced || !canWrite}\n * />\n */\nexport function useYjsText(\n collection: string,\n recordId: string,\n fieldName: string\n): UseYjsTextResult {\n const { doc, synced, canWrite, updateCount } = useYjsField(collection, recordId, fieldName)\n const [text, setTextState] = useState('')\n const yTextRef = useRef<Y.Text | null>(null)\n const isLocalUpdateRef = useRef(false)\n\n // Get Y.Text instance once doc is ready\n useEffect(() => {\n yTextRef.current = doc.getText(fieldName)\n }, [doc, fieldName])\n\n // Sync Y.Text to local state when doc updates\n useEffect(() => {\n if (yTextRef.current && synced && !isLocalUpdateRef.current) {\n setTextState(yTextRef.current.toString())\n }\n isLocalUpdateRef.current = false\n }, [synced, updateCount])\n\n // setText function that updates both local state and Yjs\n const setText = useCallback((value: string) => {\n setTextState(value)\n \n if (yTextRef.current && canWrite) {\n isLocalUpdateRef.current = true\n doc.transact(() => {\n const yText = yTextRef.current!\n yText.delete(0, yText.length)\n yText.insert(0, value)\n })\n }\n }, [doc, canWrite])\n\n return { text, setText, synced, canWrite }\n}\n","/**\n * useUserLookup Hook\n * \n * Provides helper functions to look up user information by userId.\n * This is a convenience wrapper around useUsers() that provides O(1) lookups.\n * \n * The authoritative user data comes from the users collection.\n */\n\nimport { useMemo, useCallback } from 'react'\nimport { useUsers } from './useUsers'\n\nexport interface UserInfo {\n id: string\n email: string\n name: string\n imageUrl?: string\n role: string\n}\n\n/**\n * Hook for looking up user information by ID.\n * \n * @example\n * ```tsx\n * const { getUser, getEmail, getName } = useUserLookup()\n * \n * // Get full user info\n * const user = getUser(userId)\n * \n * // Get just email\n * const email = getEmail(userId)\n * ```\n */\nexport function useUserLookup() {\n const { users, usersLoaded } = useUsers()\n \n // Build a lookup map for O(1) access\n const userMap = useMemo(() => {\n const map = new Map<string, UserInfo>()\n for (const user of users) {\n map.set(user.id, {\n id: user.id,\n email: user.email,\n name: user.name,\n imageUrl: user.imageUrl,\n role: user.role,\n })\n }\n return map\n }, [users])\n \n /**\n * Get full user info by userId\n */\n const getUser = useCallback((userId: string): UserInfo | null => {\n return userMap.get(userId) ?? null\n }, [userMap])\n \n /**\n * Get user's email by userId\n */\n const getEmail = useCallback((userId: string): string | null => {\n return userMap.get(userId)?.email ?? null\n }, [userMap])\n \n /**\n * Get user's name by userId\n */\n const getName = useCallback((userId: string): string | null => {\n return userMap.get(userId)?.name ?? null\n }, [userMap])\n \n return {\n /** All users from the users collection */\n users,\n /** True once the user list has been received from the server. */\n usersLoaded,\n /** Map of userId -> UserInfo for direct access */\n userMap,\n /** Get full user info by userId */\n getUser,\n /** Get user email by userId */\n getEmail,\n /** Get user name by userId */\n getName,\n }\n}\n","/**\n * usePresence — Derives online/offline from lastSeenAt in users collection.\n *\n * Two mechanisms keep presence working:\n * 1. Heartbeat: Sends MSG.USER_UPDATE every 60s so the server refreshes\n * our lastSeenAt in the c_users table and broadcasts the change.\n * 2. Tick: A re-render trigger every 30s so isOnline() re-evaluates\n * Date.now() and users who stopped heartbeating transition to offline.\n */\n\nimport { useEffect, useCallback, useState } from 'react'\nimport { useUser } from './useUser'\nimport { useUsers } from './useUsers'\nimport { useRecordContext } from '../context'\nimport { MSG } from '@/shared/protocol/constants'\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nconst HEARTBEAT_INTERVAL_MS = 60 * 1000 // 1 minute\nconst TICK_INTERVAL_MS = 30 * 1000 // 30 seconds\n\ninterface UsePresenceOptions {\n timeoutMs?: number\n}\n\nexport function usePresence(opts?: UsePresenceOptions) {\n const { user } = useUser()\n const { users } = useUsers()\n const { sendMessage, ready } = useRecordContext()\n const [tick, setTick] = useState(0)\n\n const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n // Heartbeat: periodically send MSG.USER_UPDATE to refresh our lastSeenAt\n useEffect(() => {\n if (!user || !ready) return\n const interval = setInterval(() => {\n sendMessage({ type: MSG.USER_UPDATE, payload: {} })\n }, HEARTBEAT_INTERVAL_MS)\n return () => clearInterval(interval)\n }, [user, ready, sendMessage])\n\n // Tick: force re-render so isOnline() re-evaluates stale timestamps\n useEffect(() => {\n const interval = setInterval(() => {\n setTick((t) => t + 1)\n }, TICK_INTERVAL_MS)\n return () => clearInterval(interval)\n }, [])\n\n const isOnline = useCallback(\n (userId: string): boolean => {\n // tick is captured to ensure this callback refreshes on each tick\n void tick\n const u = users.find((u) => u.id === userId)\n if (!u?.lastSeenAt) return false\n return Date.now() - new Date(u.lastSeenAt).getTime() < timeoutMs\n },\n [users, timeoutMs, tick],\n )\n\n const getLastSeen = useCallback(\n (userId: string): string | null => {\n const u = users.find((u) => u.id === userId)\n return u?.lastSeenAt ?? null\n },\n [users],\n )\n\n return { isOnline, getLastSeen, users }\n}\n","/**\n * useYjsRoom — Connect to a dedicated YjsRoom Durable Object.\n *\n * Unlike useYjsField (which piggybacks on RecordRoom's WebSocket),\n * this hook opens a direct WebSocket to a YjsRoom DO at /ws/yjs/:docId.\n * Each document gets its own DO for horizontal scaling.\n *\n * Uses the shared yjs-protocol.ts encoding — no duplication.\n *\n * @example\n * const { doc, text, setText, synced, canWrite } = useYjsRoom(docId, 'content')\n */\n\nimport { useState, useEffect, useCallback, useRef, useMemo } from 'react'\nimport * as Y from 'yjs'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport {\n MSG_AWARENESS,\n MSG_SYNC,\n MSG_SYNC_STEP1,\n MSG_SYNC_STEP2,\n MSG_SYNC_UPDATE,\n Awareness,\n createEncoder,\n createDecoder,\n toUint8Array,\n encodeAwarenessMessage,\n handleAwarenessMessage,\n writeVarUint,\n writeVarUint8Array,\n readVarUint,\n readVarUint8Array,\n} from '@/shared/protocol/yjs'\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport interface UseYjsRoomResult {\n /** The Yjs document */\n doc: Y.Doc\n /** Awareness instance for presence/typing state */\n awareness: Awareness\n /** Current text content (for the specified field) */\n text: string\n /** Set text (replaces full content) */\n setText: (value: string) => void\n /** Whether initial sync is complete */\n synced: boolean\n /** Whether user has write access */\n canWrite: boolean\n}\n\n/**\n * Connect to a YjsRoom DO for collaborative editing.\n *\n * @param docId - Document identifier (maps to DO name)\n * @param fieldName - Y.Text field name within the Y.Doc\n */\nexport function useYjsRoom(docId: string, fieldName: string): UseYjsRoomResult {\n const [synced, setSynced] = useState(false)\n const [canWrite, setCanWrite] = useState(false)\n const [text, setTextState] = useState('')\n const [, setUpdateCount] = useState(0)\n\n const docRef = useRef<Y.Doc | null>(null)\n if (!docRef.current) docRef.current = new Y.Doc()\n const doc = docRef.current\n\n const awarenessRef = useRef<Awareness | null>(null)\n if (!awarenessRef.current) awarenessRef.current = new Awareness(doc)\n const awareness = awarenessRef.current\n\n const wsRef = useRef<WebSocket | null>(null)\n const isLocalRef = useRef(false)\n const applyingRemoteAwarenessRef = useRef(false)\n\n const yText = useMemo(() => doc.getText(fieldName), [doc, fieldName])\n\n // Observe remote Y.Text changes\n useEffect(() => {\n const observer = () => {\n if (isLocalRef.current) return\n setTextState(yText.toString())\n }\n yText.observe(observer)\n return () => yText.unobserve(observer)\n }, [yText])\n\n // WebSocket connection to YjsRoom DO\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/yjs/${encodeURIComponent(docId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `yjs:${docId}`)\n ws = new WebSocket(url.toString())\n ws.binaryType = 'arraybuffer'\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `yjs:${docId}`)\n setSynced(false)\n }\n\n ws.onmessage = (event) => {\n if (typeof event.data === 'string') {\n try {\n const msg = JSON.parse(event.data) as { type?: string; canWrite?: unknown }\n if (msg.type === 'auth' && typeof msg.canWrite === 'boolean') setCanWrite(msg.canWrite)\n } catch {\n /* ignore */\n }\n return\n }\n\n const data = new Uint8Array(event.data as ArrayBuffer)\n const decoder = createDecoder(data)\n const messageType = readVarUint(decoder)\n\n if (messageType === MSG_SYNC) {\n const syncType = readVarUint(decoder)\n const payload = readVarUint8Array(decoder)\n\n switch (syncType) {\n case MSG_SYNC_STEP1: {\n const diff = Y.encodeStateAsUpdate(doc, payload)\n const enc = createEncoder()\n writeVarUint(enc, MSG_SYNC)\n writeVarUint(enc, MSG_SYNC_STEP2)\n writeVarUint8Array(enc, diff)\n ws?.send(toUint8Array(enc).buffer)\n setSynced(true)\n break\n }\n case MSG_SYNC_STEP2: {\n Y.applyUpdate(doc, payload, 'server')\n setTextState(yText.toString())\n setSynced(true)\n break\n }\n case MSG_SYNC_UPDATE: {\n Y.applyUpdate(doc, payload, 'server')\n setUpdateCount((c) => c + 1)\n break\n }\n }\n return\n }\n\n if (messageType === MSG_AWARENESS) {\n applyingRemoteAwarenessRef.current = true\n try {\n handleAwarenessMessage(awareness, data)\n } finally {\n applyingRemoteAwarenessRef.current = false\n }\n }\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `yjs:${docId}`)\n wsRef.current = null\n setSynced(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `yjs:${docId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [doc, awareness, docId, yText])\n\n // Relay local awareness updates (presence, typing) through YjsRoom with shared MSG_AWARENESS encoding.\n useEffect(() => {\n const handler = ({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => {\n if (applyingRemoteAwarenessRef.current) return\n const changedClients = added.concat(updated).concat(removed)\n if (changedClients.length === 0) return\n\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n\n ws.send(encodeAwarenessMessage(awareness, changedClients).buffer)\n }\n\n awareness.on('update', handler)\n return () => {\n awareness.off('update', handler)\n awareness.setLocalState(null)\n }\n }, [awareness])\n\n // Send local Y.Doc updates to server\n useEffect(() => {\n const handler = (update: Uint8Array, origin: unknown) => {\n if (origin === 'server') return\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n\n const enc = createEncoder()\n writeVarUint(enc, MSG_SYNC)\n writeVarUint(enc, MSG_SYNC_UPDATE)\n writeVarUint8Array(enc, update)\n ws.send(toUint8Array(enc).buffer)\n }\n\n doc.on('update', handler)\n return () => { doc.off('update', handler) }\n }, [doc])\n\n // setText: update Y.Text + local state\n const setText = useCallback((value: string) => {\n setTextState(value)\n if (!canWrite) return\n\n isLocalRef.current = true\n doc.transact(() => {\n yText.delete(0, yText.length)\n yText.insert(0, value)\n })\n isLocalRef.current = false\n }, [doc, yText, canWrite])\n\n return { doc, awareness, text, setText, synced, canWrite }\n}\n","/**\n * useGameRoom — Connect to a GameRoom Durable Object.\n *\n * Opens a WebSocket to /ws/game/:roomId for real-time game state.\n *\n * @example\n * const { state, sendInput, players, connected } = useGameRoom('my-game')\n *\n * Implementation note: this hook uses the typed wire protocol helpers\n * (`clientBuild` for sends, `dispatch` for receives) from\n * `shared/protocol/messages`. Hand-rolled `switch (msg.type)` blocks and\n * raw `JSON.stringify({ type: MSG.X, payload: ... })` sends are a fast\n * route to the \"silent drop\" bug class when a payload shape drifts —\n * prefer the typed helpers instead.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface GamePlayer {\n userId: string\n userName: string\n ready: boolean\n connectedAt: string\n data: Record<string, unknown>\n}\n\nexport interface UseGameRoomResult {\n /** Current game state */\n state: Record<string, unknown>\n /** Current tick number */\n tick: number\n /** Connected players */\n players: GamePlayer[]\n /** Whether the game is currently running */\n running: boolean\n /** Whether WebSocket is connected */\n connected: boolean\n /**\n * Whether this connection has write access. False for viewers /\n * unauthenticated spectators — they receive state broadcasts but the\n * send callbacks below no-op. UIs should disable input controls when\n * false so spectators see why their actions don't take effect.\n */\n canWrite: boolean\n /** Send a game input (no-op for spectators) */\n sendInput: (action: string, data?: Record<string, unknown>) => void\n /** Mark self as ready (no-op for spectators) */\n setReady: () => void\n /** Request game start (no-op for spectators) */\n startGame: () => void\n /** Request game end (no-op for spectators) */\n endGame: () => void\n}\n\nexport function useGameRoom(roomId: string): UseGameRoomResult {\n const [gameState, setGameState] = useState<Record<string, unknown>>({})\n const [tick, setTick] = useState(0)\n const [players, setPlayers] = useState<GamePlayer[]>([])\n const [running, setRunning] = useState(false)\n const [connected, setConnected] = useState(false)\n // Default false: assume spectator until the server's AUTH frame\n // confirms otherwise. See GameRoom.onConnect.\n const [canWrite, setCanWrite] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/game/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `game:${roomId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `game:${roomId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.AUTH]: (p) => {\n setCanWrite(p.canWrite)\n },\n [MSG.GAME_STATE]: (p) => {\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n setPlayers(p.players as GamePlayer[])\n setRunning(p.running)\n },\n [MSG.GAME_TICK]: (p) => {\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n },\n [MSG.GAME_PLAYER_JOIN]: (p) => {\n const player = p.player as GamePlayer\n setPlayers((prev) => [...prev.filter((x) => x.userId !== player.userId), player])\n },\n [MSG.GAME_PLAYER_LEAVE]: (p) => {\n setPlayers((prev) => prev.filter((x) => x.userId !== p.userId))\n },\n [MSG.GAME_PLAYER_READY]: (p) => {\n setPlayers((prev) =>\n prev.map((x) => (x.userId === p.userId ? { ...x, ready: true } : x)),\n )\n },\n [MSG.GAME_START]: (p) => {\n setRunning(true)\n setGameState(p.state as Record<string, unknown>)\n setTick(p.tick)\n },\n [MSG.GAME_END]: (p) => {\n setRunning(false)\n setGameState(p.state as Record<string, unknown>)\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `game:${roomId}`)\n wsRef.current = null\n setConnected(false)\n // Reset to the safe default so a reconnect with a degraded role\n // doesn't leave input/control buttons enabled until the new AUTH\n // frame lands. See useCanvas onclose for the rationale.\n setCanWrite(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `game:${roomId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [roomId])\n\n // Local write-gate. The server enforces the same rule in\n // GameRoom.onMessage; this is the UX side so spectator clicks don't\n // even leave the browser.\n const send = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n if (!canWrite) return\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [canWrite],\n )\n\n const sendInput = useCallback(\n (action: string, data: Record<string, unknown> = {}) => send(clientBuild.gameInput(action, data)),\n [send],\n )\n\n const setReady = useCallback(() => send(clientBuild.gamePlayerReady()), [send])\n const startGame = useCallback(() => send(clientBuild.gameStart()), [send])\n const endGame = useCallback(() => send(clientBuild.gameEnd()), [send])\n\n return { state: gameState, tick, players, running, connected, canWrite, sendInput, setReady, startGame, endGame }\n}\n","/**\n * useCanvas — Connect to a CanvasRoom Durable Object.\n *\n * Opens a WebSocket to /ws/canvas/:roomId for collaborative spatial editing.\n *\n * @example\n * const { shapes, addShape, moveShape, deleteShape, viewports } = useCanvas('my-canvas')\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface CanvasShapeClient {\n id: string\n type: string\n x: number\n y: number\n width: number\n height: number\n rotation?: number\n props: Record<string, unknown>\n createdBy: string\n createdAt: string\n updatedAt: string\n}\n\nexport interface ViewportClient {\n userId: string\n x: number\n y: number\n width: number\n height: number\n zoom: number\n}\n\nexport interface UseCanvasResult {\n /** All shapes on the canvas */\n shapes: CanvasShapeClient[]\n /** Other users' viewports */\n viewports: ViewportClient[]\n /** Whether WebSocket is connected */\n connected: boolean\n /**\n * Whether this connection has write access (member/admin role). The\n * write callbacks below no-op when this is false; UIs should also use\n * it to disable controls so viewers see why their clicks do nothing.\n * Viewport reporting stays available regardless — it's presence info.\n */\n canWrite: boolean\n /** Add a shape (no-op when canWrite is false) */\n addShape: (shape: Partial<CanvasShapeClient>) => void\n /** Move a shape (no-op when canWrite is false) */\n moveShape: (shapeId: string, x: number, y: number) => void\n /** Resize a shape (no-op when canWrite is false) */\n resizeShape: (shapeId: string, width: number, height: number, x?: number, y?: number) => void\n /** Delete a shape (no-op when canWrite is false) */\n deleteShape: (shapeId: string) => void\n /** Update shape properties (no-op when canWrite is false) */\n updateShape: (shapeId: string, props: Record<string, unknown>) => void\n /** Report local viewport (allowed for viewers — presence-like) */\n setViewport: (viewport: Omit<ViewportClient, 'userId'>) => void\n /** Undo last action (no-op when canWrite is false) */\n undo: () => void\n /** Redo last undone action (no-op when canWrite is false) */\n redo: () => void\n}\n\nexport function useCanvas(roomId: string): UseCanvasResult {\n const [shapes, setShapes] = useState<CanvasShapeClient[]>([])\n const [viewports, setViewports] = useState<ViewportClient[]>([])\n const [connected, setConnected] = useState(false)\n // Defaults to false: until the server's AUTH frame arrives, assume the\n // safer no-write posture so UIs don't briefly enable controls for a\n // viewer mid-handshake.\n const [canWrite, setCanWrite] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/canvas/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `canvas:${roomId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `canvas:${roomId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n // Typed dispatch — handler payloads are narrowed by the SDK's\n // discriminated `ServerMessage` union. Shape/viewport objects\n // on the wire are typed as `unknown` (the protocol layer\n // doesn't know the app's domain types), so we cast to the\n // local `CanvasShapeClient` / `ViewportClient` where we use\n // them.\n dispatch<ServerMessage>(event.data, {\n [MSG.AUTH]: (p) => {\n setCanWrite(p.canWrite)\n },\n [MSG.CANVAS_SHAPES]: (p) => {\n setShapes(p.shapes as CanvasShapeClient[])\n setViewports(p.viewports as ViewportClient[])\n },\n [MSG.CANVAS_ADD]: (p) => {\n const shape = p.shape as CanvasShapeClient\n setShapes((prev) => [...prev.filter((s) => s.id !== shape.id), shape])\n },\n [MSG.CANVAS_MOVE]: (p) => {\n setShapes((prev) =>\n prev.map((s) => (s.id === p.shapeId ? { ...s, x: p.x, y: p.y } : s)),\n )\n },\n [MSG.CANVAS_RESIZE]: (p) => {\n setShapes((prev) =>\n prev.map((s) => {\n if (s.id !== p.shapeId) return s\n const updated = { ...s, width: p.width, height: p.height }\n if (p.x !== undefined) updated.x = p.x\n if (p.y !== undefined) updated.y = p.y\n return updated\n }),\n )\n },\n [MSG.CANVAS_DELETE]: (p) => {\n setShapes((prev) => prev.filter((s) => s.id !== p.shapeId))\n },\n [MSG.CANVAS_UPDATE]: (p) => {\n setShapes((prev) =>\n prev.map((s) =>\n s.id === p.shapeId ? { ...s, props: { ...s.props, ...p.props } } : s,\n ),\n )\n },\n [MSG.CANVAS_VIEWPORT]: (p) => {\n // The payload is a union of `{ viewport }` and\n // `{ userId, removed: true }` — narrow by presence.\n if ('removed' in p) {\n const removed = p\n setViewports((prev) => prev.filter((v) => v.userId !== removed.userId))\n } else {\n const viewport = p.viewport as ViewportClient\n setViewports((prev) => [\n ...prev.filter((v) => v.userId !== viewport.userId),\n viewport,\n ])\n }\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `canvas:${roomId}`)\n wsRef.current = null\n setConnected(false)\n // Reset to the safe default so a reconnect with a degraded role\n // (e.g. JWT expired, user now anon) doesn't leave write buttons\n // enabled until the new AUTH frame arrives. The fresh server\n // onConnect will re-send AUTH with the current canWrite value.\n setCanWrite(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `canvas:${roomId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [roomId])\n\n // Typed builders — `clientBuild.canvasX` returns a validated\n // `ClientMessage` that `encode` stringifies. No hand-rolled\n // `JSON.stringify({ type, payload })` calls here.\n const sendBuilt = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [],\n )\n\n // Local write-gate: write callbacks short-circuit when canWrite is\n // false. The server enforces the same rule (see CanvasRoom.onMessage),\n // so this is a UX layer — viewers click a button and get instant\n // \"nothing happened\" instead of a round-trip ERROR.\n const sendWrite = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n if (!canWrite) return\n sendBuilt(message)\n },\n [sendBuilt, canWrite],\n )\n\n const addShape = useCallback(\n (shape: Partial<CanvasShapeClient>) => sendWrite(clientBuild.canvasAdd(shape)),\n [sendWrite],\n )\n\n const moveShape = useCallback(\n (shapeId: string, x: number, y: number) =>\n sendWrite(clientBuild.canvasMove(shapeId, x, y)),\n [sendWrite],\n )\n\n const resizeShape = useCallback(\n (shapeId: string, width: number, height: number, x?: number, y?: number) =>\n sendWrite(clientBuild.canvasResize(shapeId, width, height, x, y)),\n [sendWrite],\n )\n\n const deleteShape = useCallback(\n (shapeId: string) => sendWrite(clientBuild.canvasDelete(shapeId)),\n [sendWrite],\n )\n\n const updateShape = useCallback(\n (shapeId: string, props: Record<string, unknown>) =>\n sendWrite(clientBuild.canvasUpdate(shapeId, props)),\n [sendWrite],\n )\n\n // Viewport stays on sendBuilt (not sendWrite): broadcasting \"I'm\n // looking here\" is presence-like and intentionally allowed for\n // viewers, matching the server's CanvasRoom gate.\n const setViewport = useCallback(\n (viewport: Omit<ViewportClient, 'userId'>) =>\n sendBuilt(clientBuild.canvasViewport(viewport)),\n [sendBuilt],\n )\n\n const undo = useCallback(() => sendWrite(clientBuild.canvasUndo()), [sendWrite])\n const redo = useCallback(() => sendWrite(clientBuild.canvasRedo()), [sendWrite])\n\n return { shapes, viewports, connected, canWrite, addShape, moveShape, resizeShape, deleteShape, updateShape, setViewport, undo, redo }\n}\n","/**\n * useCronMonitor — Connect to a CronRoom for monitoring scheduled tasks.\n *\n * Opens a WebSocket to /cron/:roomId for real-time task status.\n *\n * @example\n * const { tasks, history, trigger, pause, resume } = useCronMonitor('cron')\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\nexport interface CronTaskState {\n name: string\n intervalMinutes: number | null\n schedule: string | null\n timezone: string | null\n paused: boolean\n lastRunAt: string | null\n nextRunAt: string | null\n}\n\nexport interface CronHistoryEntry {\n taskName: string\n startedAt: string\n completedAt: string | null\n success: boolean\n durationMs: number\n error?: string\n}\n\nexport interface UseCronMonitorResult {\n /** Current task states */\n tasks: CronTaskState[]\n /** Execution history */\n history: CronHistoryEntry[]\n /** Whether WebSocket is connected */\n connected: boolean\n /**\n * Whether this connection can mutate cron state (trigger / pause /\n * resume). False for viewers and unauthenticated connections — the\n * mutation callbacks below no-op and UIs should disable those\n * controls. Reading tasks/history stays available either way.\n */\n canWrite: boolean\n /** Manually trigger a task (no-op when canWrite is false) */\n trigger: (taskName: string) => void\n /** Pause a task (no-op when canWrite is false) */\n pause: (taskName: string) => void\n /** Resume a paused task (no-op when canWrite is false) */\n resume: (taskName: string) => void\n}\n\nexport function useCronMonitor(roomId: string): UseCronMonitorResult {\n const [tasks, setTasks] = useState<CronTaskState[]>([])\n const [history, setHistory] = useState<CronHistoryEntry[]>([])\n const [connected, setConnected] = useState(false)\n // Default false: viewers/anon connections can read but not write. The\n // server's CronRoom.onConnect AUTH frame flips this for members/admins.\n const [canWrite, setCanWrite] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/cron/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => setConnected(true)\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.AUTH]: (p) => {\n setCanWrite(p.canWrite)\n },\n [MSG.CRON_TASKS]: (p) => {\n setTasks(p.tasks as CronTaskState[])\n },\n [MSG.CRON_HISTORY]: (p) => {\n setHistory(p.history as CronHistoryEntry[])\n },\n [MSG.CRON_STATUS]: (p) => {\n setTasks(p.tasks as CronTaskState[])\n setHistory(p.recentHistory as CronHistoryEntry[])\n },\n })\n }\n\n ws.onclose = () => {\n wsRef.current = null\n setConnected(false)\n // Reset to the safe default so a reconnect with a degraded role\n // doesn't leave trigger/pause/resume controls enabled until the\n // new AUTH frame lands. See useCanvas onclose for the rationale.\n setCanWrite(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n ws?.close()\n wsRef.current = null\n }\n }, [roomId])\n\n // Local write-gate. Mirrors the server check in CronRoom.onMessage so\n // viewer clicks short-circuit instead of round-tripping to ERROR.\n const sendWrite = useCallback(\n <M extends { type: string; payload: unknown }>(message: M) => {\n if (!canWrite) return\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [canWrite],\n )\n\n const trigger = useCallback(\n (taskName: string) => sendWrite(clientBuild.cronTrigger(taskName)),\n [sendWrite],\n )\n const pause = useCallback(\n (taskName: string) => sendWrite(clientBuild.cronPause(taskName)),\n [sendWrite],\n )\n const resume = useCallback(\n (taskName: string) => sendWrite(clientBuild.cronResume(taskName)),\n [sendWrite],\n )\n\n return { tasks, history, connected, canWrite, trigger, pause, resume }\n}\n","/**\n * useJobs — Connect to a JobRoom for enqueueing and tracking background\n * jobs in real time.\n *\n * Opens a WebSocket to /ws/jobs/:roomId. The DO pushes a snapshot on\n * connect and JOB_UPDATE messages for every state change after that, so\n * `jobs` stays current without polling. `enqueue` returns a promise that\n * resolves with the new jobId once the server acks.\n *\n * Client-side names (`JobView`, `JobStatusView`) differ from the\n * server-side equivalents (`Job`, `JobStatus` in `deepspace/worker`) so\n * apps importing from both ends don't get type collisions.\n *\n * @example\n * const { jobs, enqueue, getJob, cancel } = useJobs(`app:${APP_NAME}`)\n *\n * async function onClick() {\n * const jobId = await enqueue('ai-summarize', { text })\n * // Now `getJob(jobId)` is reactive until the job reaches a terminal state.\n * }\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\n/** How long enqueue() waits for a server ack before rejecting. */\nconst ENQUEUE_TIMEOUT_MS = 10_000\n\nexport type JobStatusView =\n | 'queued'\n | 'running'\n | 'succeeded'\n | 'failed'\n | 'canceled'\n\nexport interface JobView<P = unknown, R = unknown> {\n id: string\n type: string\n status: JobStatusView\n payload?: P\n result?: R\n error?: string\n progress?: number\n progressMessage?: string\n attempts: number\n maxAttempts: number\n enqueuedAt: string\n startedAt?: string | null\n completedAt?: string | null\n enqueuedBy?: string | null\n}\n\nexport interface UseJobsResult<P = unknown, R = unknown> {\n /** All jobs the room currently knows about, newest-first. */\n jobs: JobView<P, R>[]\n /** WebSocket connection state. */\n connected: boolean\n /**\n * Enqueue a new job. Resolves with the new jobId once the server acks\n * (typically <100ms). Rejects if:\n * - the WebSocket isn't connected\n * - the WebSocket closes before the ack arrives\n * - no ack arrives within 10s (server dropped the message)\n */\n enqueue(\n type: string,\n payload?: P,\n options?: { maxAttempts?: number },\n ): Promise<string>\n /**\n * Reactive single-job lookup. Returns undefined while the snapshot is\n * loading or if the job has been GC'd by the room's TTL sweep.\n */\n getJob(jobId: string): JobView<P, R> | undefined\n /** Best-effort cancel. The job is marked canceled even if the handler ignores `ctx.signal`. */\n cancel(jobId: string): void\n /** Manually re-queue a failed/canceled job. No-op for other statuses. */\n retry(jobId: string): void\n}\n\ninterface PendingEnqueue {\n resolve: (id: string) => void\n reject: (err: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/**\n * @param roomId DO room id, typically `app:<APP_NAME>`. Apps with sharded\n * queues pass different ids — each id maps to its own DO instance.\n */\nexport function useJobs<P = unknown, R = unknown>(\n roomId: string,\n): UseJobsResult<P, R> {\n const [jobs, setJobs] = useState<JobView<P, R>[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n /**\n * Pending enqueue promises keyed by requestId. Each entry carries a\n * timeout timer so the caller doesn't hang forever if the server drops\n * the enqueue (validation error swallowed, isolate restart, etc.).\n */\n const pendingEnqueueRef = useRef<Map<string, PendingEnqueue>>(new Map())\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const upsert = (next: JobView<P, R>) => {\n setJobs((prev) => {\n const idx = prev.findIndex((j) => j.id === next.id)\n if (idx === -1) return [next, ...prev]\n const copy = prev.slice()\n copy[idx] = next\n return copy\n })\n }\n\n const rejectAllPending = (err: Error) => {\n for (const [id, pending] of pendingEnqueueRef.current.entries()) {\n clearTimeout(pending.timer)\n pending.reject(err)\n pendingEnqueueRef.current.delete(id)\n }\n }\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/jobs/${encodeURIComponent(roomId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => setConnected(true)\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.JOB_UPDATE]: (p) => {\n if (p.kind === 'snapshot' && Array.isArray(p.jobs)) {\n setJobs(p.jobs as JobView<P, R>[])\n return\n }\n const job = p.job as JobView<P, R> | undefined\n if (!job) return\n upsert(job)\n // Resolve the enqueue promise once the server acks.\n if (p.kind === 'enqueued' && typeof p.requestId === 'string') {\n const pending = pendingEnqueueRef.current.get(p.requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingEnqueueRef.current.delete(p.requestId)\n pending.resolve(job.id)\n }\n }\n },\n })\n }\n\n ws.onclose = () => {\n wsRef.current = null\n setConnected(false)\n rejectAllPending(new Error('JobRoom WebSocket closed'))\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n rejectAllPending(new Error('useJobs unmounted'))\n ws?.close()\n wsRef.current = null\n }\n }, [roomId])\n\n const enqueue = useCallback(\n (type: string, payload?: P, options?: { maxAttempts?: number }) => {\n return new Promise<string>((resolve, reject) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n reject(new Error('JobRoom WebSocket not connected'))\n return\n }\n const requestId = crypto.randomUUID()\n const timer = setTimeout(() => {\n pendingEnqueueRef.current.delete(requestId)\n reject(\n new Error(\n `JobRoom enqueue timed out (no server ack within ${ENQUEUE_TIMEOUT_MS}ms)`,\n ),\n )\n }, ENQUEUE_TIMEOUT_MS)\n pendingEnqueueRef.current.set(requestId, { resolve, reject, timer })\n // ws.send can throw synchronously if the socket transitions between\n // the readyState check and the call (browser-specific, quota errors).\n // Without this guard the pending entry would sit until the 10s\n // timeout — fine for safety, bad for caller latency.\n try {\n ws.send(\n encode(clientBuild.jobEnqueue(requestId, type, payload, options?.maxAttempts)),\n )\n } catch (e) {\n clearTimeout(timer)\n pendingEnqueueRef.current.delete(requestId)\n reject(e instanceof Error ? e : new Error(String(e)))\n }\n })\n },\n [],\n )\n\n const sendBuilt = useCallback(\n <M extends { type: string; payload: unknown }>(message: M): void => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(message))\n },\n [],\n )\n\n const getJob = useCallback(\n (jobId: string) => jobs.find((j) => j.id === jobId),\n [jobs],\n )\n\n const cancel = useCallback(\n (jobId: string) => sendBuilt(clientBuild.jobCancel(jobId)),\n [sendBuilt],\n )\n\n const retry = useCallback(\n (jobId: string) => sendBuilt(clientBuild.jobRetry(jobId)),\n [sendBuilt],\n )\n\n return { jobs, connected, enqueue, getJob, cancel, retry }\n}\n","/**\n * usePresenceRoom — Connect to a PresenceRoom Durable Object.\n *\n * Opens a WebSocket to /ws/presence/:scopeId for real-time presence tracking.\n * Use with any scope: canvas, doc, thread, page, etc.\n *\n * Peers can share arbitrary state (cursor position, typing indicator,\n * viewport, selection) via updateState().\n *\n * @example\n * // Track who's on a canvas\n * const { peers, connected, updateState } = usePresenceRoom(`canvas:${canvasId}`)\n *\n * // Share cursor position\n * updateState({ cursor: { x: 100, y: 200 } })\n *\n * // Track who's viewing a thread\n * const { peers } = usePresenceRoom(`thread:${channelId}`)\n *\n * // Show typing indicator\n * updateState({ typing: true })\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react'\nimport { getAuthToken } from '../../auth'\nimport { wsLog } from '../ws-log'\nimport { MSG } from '@/shared/protocol/constants'\nimport {\n clientBuild,\n dispatch,\n encode,\n type ServerMessage,\n} from '@/shared/protocol/messages'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PresencePeerClient {\n userId: string\n userName: string\n userEmail: string\n userImageUrl?: string\n joinedAt: string\n state: Record<string, unknown>\n}\n\nexport interface UsePresenceRoomResult {\n /** All peers currently present in this scope (excludes self) */\n peers: PresencePeerClient[]\n /** Whether the WebSocket is connected */\n connected: boolean\n /** Send a state update (cursor, typing, viewport, etc.) — merges with existing state */\n updateState: (state: Record<string, unknown>) => void\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function usePresenceRoom(scopeId: string): UsePresenceRoomResult {\n const [peers, setPeers] = useState<PresencePeerClient[]>([])\n const [connected, setConnected] = useState(false)\n const wsRef = useRef<WebSocket | null>(null)\n\n useEffect(() => {\n let ws: WebSocket | null = null\n let reconnectTimer: ReturnType<typeof setTimeout> | null = null\n let alive = true\n\n const connect = async () => {\n if (!alive) return\n\n const token = await getAuthToken()\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const baseUrl = `${protocol}//${window.location.host}`\n const url = new URL(`/ws/presence/${encodeURIComponent(scopeId)}`, baseUrl)\n if (token) url.searchParams.set('token', token)\n\n wsLog('connecting', `presence:${scopeId}`)\n ws = new WebSocket(url.toString())\n wsRef.current = ws\n\n ws.onopen = () => {\n wsLog('connected', `presence:${scopeId}`)\n setConnected(true)\n }\n\n ws.onmessage = (event) => {\n dispatch<ServerMessage>(event.data, {\n [MSG.PRESENCE_SYNC]: (p) => {\n setPeers(p.peers as PresencePeerClient[])\n },\n [MSG.PRESENCE_JOIN]: (p) => {\n const peer = p.peer as PresencePeerClient\n setPeers((prev) => [...prev.filter((x) => x.userId !== peer.userId), peer])\n },\n [MSG.PRESENCE_LEAVE]: (p) => {\n setPeers((prev) => prev.filter((x) => x.userId !== p.userId))\n },\n [MSG.PRESENCE_UPDATE]: (p) => {\n setPeers((prev) =>\n prev.map((x) =>\n x.userId === p.userId ? { ...x, state: { ...x.state, ...p.state } } : x,\n ),\n )\n },\n })\n }\n\n ws.onclose = () => {\n wsLog('disconnected', `presence:${scopeId}`)\n wsRef.current = null\n setConnected(false)\n if (alive) reconnectTimer = setTimeout(connect, 1000)\n }\n\n ws.onerror = () => ws?.close()\n }\n\n connect()\n\n return () => {\n wsLog('closing', `presence:${scopeId}`)\n alive = false\n if (reconnectTimer) clearTimeout(reconnectTimer)\n if (ws) {\n ws.onclose = null\n ws.onmessage = null\n ws.onerror = null\n ws.close()\n }\n wsRef.current = null\n }\n }, [scopeId])\n\n const updateState = useCallback((state: Record<string, unknown>) => {\n const ws = wsRef.current\n if (!ws || ws.readyState !== WebSocket.OPEN) return\n ws.send(encode(clientBuild.presenceUpdate(state)))\n }, [])\n\n return { peers, connected, updateState }\n}\n","/**\n * ConnectionStatus type and utility for domain hooks.\n *\n * Maps useQuery() status to a simpler connection state\n * used by app-level platform providers.\n */\n\nexport type ConnectionStatus = 'connecting' | 'connected' | 'reconnecting' | 'error'\n\n/**\n * Map a useQuery() status string to a ConnectionStatus.\n *\n * useQuery returns: 'pending' | 'ready' | 'error'\n * This maps to the simplified connection states used by platform providers.\n */\nexport function toConnectionStatus(queryStatus: string): ConnectionStatus {\n if (queryStatus === 'ready') return 'connected'\n if (queryStatus === 'error') return 'error'\n return 'connecting'\n}\n","/**\n * useR2Files — Scoped file storage hook for DeepSpace apps.\n *\n * Provides upload, download, list, and delete for files in R2, scoped to\n * the current app (\"self\" — uses hostname-based scoping on the server).\n *\n * @example\n * ```tsx\n * const { upload, downloadFile, deleteFile, list } = useR2Files()\n * await upload(myFile, 'photo.png')\n *\n * const files = await list()\n * await downloadFile(files[0]) // uses originalName automatically\n * await deleteFile(files[0])\n * ```\n */\n\nimport { useCallback, useState, useMemo } from 'react'\nimport { getAuthToken } from '../auth'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface R2UploadResult {\n success: boolean\n key?: string\n url?: string\n name?: string\n error?: string\n}\n\nexport interface R2FileInfo {\n key: string\n size: number\n uploaded: string\n url: string\n originalName?: string\n uploadedBy?: string\n}\n\nexport interface UseR2FilesReturn {\n /** Upload a File or Blob. Optionally provide a display name. */\n upload: (file: File | Blob, name?: string) => Promise<R2UploadResult>\n /** Upload raw base64 data. */\n uploadBase64: (base64Data: string, name: string, mimeType?: string) => Promise<R2UploadResult>\n /**\n * Delete a file. Accepts an R2FileInfo from `list()` or a raw key string.\n *\n * @example\n * ```tsx\n * const files = await list()\n * await deleteFile(files[0]) // pass the object\n * await deleteFile('widgets/abc/f.pdf') // or a raw key\n * ```\n */\n deleteFile: (fileOrKey: R2FileInfo | string) => Promise<{ success: boolean; error?: string }>\n /** List files, optionally filtered by a sub-prefix within the scope. */\n list: (prefix?: string) => Promise<R2FileInfo[]>\n /**\n * Download a file. Accepts an R2FileInfo from `list()` or a raw key string.\n * Uses an authenticated fetch and triggers a browser download via blob URL.\n *\n * When an R2FileInfo is passed, `originalName` is used as the download\n * filename automatically. When a string key is passed, an optional\n * `fileName` override can be provided.\n *\n * @example\n * ```tsx\n * const files = await list()\n * await downloadFile(files[0]) // uses originalName\n * await downloadFile('widgets/abc/f.pdf', 'report.pdf') // explicit name\n * ```\n */\n downloadFile: (fileOrKey: R2FileInfo | string, fileName?: string) => Promise<{ success: boolean; error?: string }>\n /**\n * Read a file's contents with authentication. Returns the raw Response.\n * Unlike `downloadFile`, this does NOT trigger a browser download —\n * it returns the Response so you can call `.text()`, `.blob()`,\n * `.arrayBuffer()`, `.json()`, etc.\n *\n * @example\n * ```tsx\n * const resp = await readFile('data/cleaned.txt')\n * const text = await resp.text()\n * ```\n */\n readFile: (fileOrKey: R2FileInfo | string) => Promise<Response>\n /**\n * Build a plain URL for a file. Accepts an R2FileInfo or a raw key string.\n *\n * **Note**: This URL has no auth token attached. It only works for\n * unauthenticated reads on deployed sites where the prefix is derived\n * from the hostname. For authenticated access, use `downloadFile` or\n * `readFile` instead.\n */\n getUrl: (fileOrKey: R2FileInfo | string) => string\n /** Whether an upload is currently in progress. */\n isUploading: boolean\n}\n\nexport type R2Scope = { scope?: 'self' }\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/** Extract key (and optional original name) from an R2FileInfo or raw string. */\nfunction resolveFile(fileOrKey: R2FileInfo | string): { key: string; name: string | undefined } {\n if (typeof fileOrKey === 'string') {\n return { key: fileOrKey, name: undefined }\n }\n return { key: fileOrKey.key, name: fileOrKey.originalName }\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useR2Files(options?: R2Scope): UseR2FilesReturn {\n const [isUploading, setIsUploading] = useState(false)\n\n /** Query string that tells the worker which scope to use. */\n const scopeParams = useMemo(() => {\n const params = new URLSearchParams()\n params.set('scope', 'self')\n return params.toString()\n }, [])\n\n /** Get auth headers using the DeepSpace auth token. */\n const authHeaders = useCallback(async (): Promise<Record<string, string>> => {\n const token = await getAuthToken()\n if (token) {\n return { Authorization: `Bearer ${token}` }\n }\n return {}\n }, [])\n\n const upload = useCallback(async (file: File | Blob, name?: string): Promise<R2UploadResult> => {\n setIsUploading(true)\n try {\n const headers = await authHeaders()\n const formData = new FormData()\n formData.append('file', file)\n if (name) formData.append('name', name)\n\n const response = await fetch(`/api/files/upload?${scopeParams}`, {\n method: 'POST',\n headers,\n body: formData,\n })\n return await response.json() as R2UploadResult\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Upload failed' }\n } finally {\n setIsUploading(false)\n }\n }, [scopeParams, authHeaders])\n\n const uploadBase64 = useCallback(async (base64Data: string, name: string, mimeType?: string): Promise<R2UploadResult> => {\n setIsUploading(true)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/upload?${scopeParams}`, {\n method: 'POST',\n headers: { ...headers, 'Content-Type': 'application/json' },\n body: JSON.stringify({ data: base64Data, name, mimeType }),\n })\n return await response.json() as R2UploadResult\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Upload failed' }\n } finally {\n setIsUploading(false)\n }\n }, [scopeParams, authHeaders])\n\n const deleteFile = useCallback(async (fileOrKey: R2FileInfo | string): Promise<{ success: boolean; error?: string }> => {\n const { key } = resolveFile(fileOrKey)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { method: 'DELETE', headers })\n return await response.json() as { success: boolean; error?: string }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Delete failed' }\n }\n }, [scopeParams, authHeaders])\n\n const list = useCallback(async (prefix?: string): Promise<R2FileInfo[]> => {\n try {\n const headers = await authHeaders()\n const params = new URLSearchParams(scopeParams)\n if (prefix) params.set('prefix', prefix)\n const response = await fetch(`/api/files?${params.toString()}`, { headers })\n const result = await response.json() as { files: R2FileInfo[] }\n return result.files || []\n } catch {\n return []\n }\n }, [scopeParams, authHeaders])\n\n const downloadFile = useCallback(async (fileOrKey: R2FileInfo | string, fileName?: string): Promise<{ success: boolean; error?: string }> => {\n const { key, name: infoName } = resolveFile(fileOrKey)\n try {\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { headers })\n\n if (!response.ok) {\n const body = await response.json().catch(() => null) as { error?: string } | null\n return { success: false, error: body?.error ?? `Download failed (${response.status})` }\n }\n\n // Derive a display name: explicit arg > R2FileInfo.originalName > Content-Disposition > last key segment\n const disposition = response.headers.get('Content-Disposition')\n const dispositionName = disposition?.match(/filename=\"(.+?)\"/)?.[1]\n const fallbackName = key.split('/').pop() ?? 'download'\n const resolvedName = fileName ?? infoName ?? dispositionName ?? fallbackName\n\n const blob = await response.blob()\n const blobUrl = URL.createObjectURL(blob)\n\n const anchor = document.createElement('a')\n anchor.href = blobUrl\n anchor.download = resolvedName\n document.body.appendChild(anchor)\n anchor.click()\n\n // Clean up\n document.body.removeChild(anchor)\n URL.revokeObjectURL(blobUrl)\n\n return { success: true }\n } catch (err) {\n return { success: false, error: err instanceof Error ? err.message : 'Download failed' }\n }\n }, [scopeParams, authHeaders])\n\n const readFile = useCallback(async (fileOrKey: R2FileInfo | string): Promise<Response> => {\n const { key } = resolveFile(fileOrKey)\n const headers = await authHeaders()\n const response = await fetch(`/api/files/${key}?${scopeParams}`, { headers })\n if (!response.ok) {\n const body = await response.text().catch(() => '')\n throw new Error(`Failed to read file (${response.status}): ${body}`)\n }\n return response\n }, [scopeParams, authHeaders])\n\n const getUrl = useCallback((fileOrKey: R2FileInfo | string): string => {\n const { key } = resolveFile(fileOrKey)\n return `/api/files/${key}?${scopeParams}`\n }, [scopeParams])\n\n return { upload, uploadBase64, deleteFile, downloadFile, readFile, list, getUrl, isUploading }\n}\n","/**\n * Shared types and utilities for file attachments across miniapps.\n */\n\nexport interface FileAttachment {\n key: string\n url: string\n name: string\n size: number\n mimeType: string\n}\n\nconst IMAGE_MIME_PREFIXES = ['image/']\n\nexport function isImageFile(mimeType: string): boolean {\n return IMAGE_MIME_PREFIXES.some(prefix => mimeType.startsWith(prefix))\n}\n\nexport function formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n","/**\n * Deterministic user color assignment.\n * Same user ID always maps to the same color across sessions.\n */\n\nexport const DEFAULT_USER_COLORS = [\n '#f87171', '#fb923c', '#fbbf24', '#34d399',\n '#22d3ee', '#60a5fa', '#a78bfa', '#f472b6',\n '#e879f9', '#4ade80', '#38bdf8', '#facc15',\n] as const\n\nexport function getUserColor(userId: string, palette: readonly string[] = DEFAULT_USER_COLORS): string {\n let hash = 0\n for (let i = 0; i < userId.length; i++) {\n hash = ((hash << 5) - hash + userId.charCodeAt(i)) | 0\n }\n return palette[Math.abs(hash) % palette.length]\n}\n","/**\n * useMessages — subscribe to messages in a channel with send/edit/remove.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Message } from './channel-types'\n\nexport function useMessages(\n channelId: string | undefined,\n options?: { parentMessageId?: string }\n) {\n const where = useMemo(() => {\n if (!channelId) return { channelId: '__none__' }\n const w: Record<string, unknown> = { channelId }\n if (options?.parentMessageId !== undefined) {\n w.parentMessageId = options.parentMessageId\n }\n return w\n }, [channelId, options?.parentMessageId])\n\n const { user } = useUser()\n\n const { records, status, error } = useQuery<Message>('messages', {\n where,\n orderBy: 'createdAt',\n orderDir: 'asc',\n })\n\n const { create, put, remove: removeMutation } = useMutations<Message>('messages')\n\n const send = useCallback(\n (content: string, parentMessageId?: string) => {\n if (!channelId || !user) return\n const data: Record<string, unknown> = { channelId, content, authorId: user.id, edited: false }\n if (parentMessageId) data.parentMessageId = parentMessageId\n return create(data as unknown as Message)\n },\n [channelId, create],\n )\n\n const edit = useCallback(\n (messageId: string, newContent: string) => {\n put(messageId, { content: newContent, edited: true } as unknown as Message)\n },\n [put],\n )\n\n /** Hard-delete: drops the row entirely. Use when threads/replies don't matter. */\n const remove = useCallback(\n (messageId: string) => { removeMutation(messageId) },\n [removeMutation],\n )\n\n /**\n * Soft-delete: sets `deleted: true` on the message. The row stays so threads,\n * read-receipts, and parent links remain coherent. UIs render a tombstone\n * (e.g. \"This message was deleted.\") for messages with `deleted === true`.\n */\n const softDelete = useCallback(\n (messageId: string) => {\n put(messageId, { deleted: true } as unknown as Message)\n },\n [put],\n )\n\n return { messages: records as RecordData<Message>[], status, error, send, edit, remove, softDelete }\n}\n","/**\n * useChannels — subscribe to channels with create/archive/update.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Channel } from './channel-types'\n\nexport function useChannels() {\n const { user } = useUser()\n const { records, status, error } = useQuery<Channel>('channels', {\n orderBy: 'createdAt',\n orderDir: 'asc',\n })\n\n const { create: createMutation, put, remove } = useMutations<Channel>('channels')\n\n const create = useCallback(\n (data: { name: string; type: Channel['type']; description?: string }) => {\n return createMutation({\n name: data.name,\n type: data.type,\n description: data.description ?? '',\n createdBy: user?.id ?? '',\n archived: false,\n } as unknown as Channel)\n },\n [createMutation],\n )\n\n const archive = useCallback(\n (channelId: string) => { put(channelId, { archived: true } as unknown as Channel) },\n [put],\n )\n\n const update = useCallback(\n (channelId: string, data: Partial<Pick<Channel, 'name' | 'description'>>) => {\n put(channelId, data as unknown as Channel)\n },\n [put],\n )\n\n return { channels: records as RecordData<Channel>[], status, error, create, archive, update, remove }\n}\n","/**\n * useReactions — subscribe to reactions in a channel with toggle.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { Reaction } from './channel-types'\nimport type { GroupedReaction } from './types'\n\nexport function useReactions(channelId: string | undefined) {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<Reaction>('reactions', {\n where: channelId ? { channelId } : { channelId: '__none__' },\n })\n\n const { create, remove: removeMutation } = useMutations<Reaction>('reactions')\n\n const getReactionsForMessage = useCallback(\n (messageId: string): GroupedReaction[] => {\n const messageReactions = records.filter((r) => r.data.messageId === messageId)\n const grouped = new Map<string, string[]>()\n\n for (const r of messageReactions) {\n if (!grouped.has(r.data.emoji)) grouped.set(r.data.emoji, [])\n grouped.get(r.data.emoji)!.push(r.data.userId)\n }\n\n return Array.from(grouped.entries()).map(([emoji, userIds]) => ({\n emoji,\n count: userIds.length,\n userIds,\n currentUserReacted: user ? userIds.includes(user.id) : false,\n }))\n },\n [records, user],\n )\n\n const toggle = useCallback(\n (messageId: string, emoji: string) => {\n if (!channelId || !user) return\n const existing = records.find(\n (r) => r.data.messageId === messageId && r.data.emoji === emoji && r.data.userId === user.id,\n )\n if (existing) {\n removeMutation(existing.recordId)\n } else {\n create({ messageId, channelId, emoji, userId: user.id } as unknown as Reaction)\n }\n },\n [channelId, user, records, create, removeMutation],\n )\n\n return { reactions: records as RecordData<Reaction>[], status, error, getReactionsForMessage, toggle }\n}\n","/**\n * useChannelMembers — subscribe to channel membership with join/leave.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { ChannelMember } from './channel-types'\n\nexport function useChannelMembers(channelId: string | undefined) {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<ChannelMember>('channel-members', {\n where: channelId ? { channelId } : { channelId: '__none__' },\n })\n\n const { create, remove: removeMutation } = useMutations<ChannelMember>('channel-members')\n\n const join = useCallback(() => {\n if (!channelId || !user) return\n const existing = records.find((r) => r.data.userId === user.id)\n if (existing) return\n create({ channelId, userId: user.id, joinedAt: new Date().toISOString() } as unknown as ChannelMember)\n }, [channelId, user, records, create])\n\n const leave = useCallback(() => {\n if (!channelId || !user) return\n const membership = records.find((r) => r.data.userId === user.id)\n if (membership) removeMutation(membership.recordId)\n }, [channelId, user, records, removeMutation])\n\n const isMember = user ? records.some((r) => r.data.userId === user.id) : false\n\n return { members: records as RecordData<ChannelMember>[], status, error, join, leave, isMember }\n}\n","/**\n * useReadReceipts — track read state per channel for the current user.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { ReadReceipt, Message } from './channel-types'\n\nexport function useReadReceipts() {\n const { user } = useUser()\n\n const { records, status, error } = useQuery<ReadReceipt>('read-receipts', {\n where: user ? { userId: user.id } : { userId: '__none__' },\n })\n\n const { create, put } = useMutations<ReadReceipt>('read-receipts')\n\n const markAsRead = useCallback(\n (channelId: string) => {\n if (!user) return\n const existing = records.find((r) => r.data.channelId === channelId)\n const now = new Date().toISOString()\n if (existing) {\n put(existing.recordId, { lastReadAt: now } as unknown as ReadReceipt)\n } else {\n create({ channelId, userId: user.id, lastReadAt: now } as unknown as ReadReceipt)\n }\n },\n [user, records, create, put],\n )\n\n const getUnreadCount = useCallback(\n (channelId: string, messages: RecordData<Message>[]): number => {\n const receipt = records.find((r) => r.data.channelId === channelId)\n if (!receipt) return messages.length\n const lastReadAt = new Date(receipt.data.lastReadAt).getTime()\n return messages.filter((m) => new Date(m.createdAt).getTime() > lastReadAt).length\n },\n [records],\n )\n\n return { receipts: records as RecordData<ReadReceipt>[], status, error, markAsRead, getUnreadCount }\n}\n","/**\n * useConversation — Shared hook for conversation messaging.\n *\n * Wraps useQuery/useMutations for conv_messages, conv_reactions, conv_members\n * and returns a ConversationObject. Must be used inside a RecordScope for the\n * conversation DO (conv:{channelId}).\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useRecordContext } from '../storage/context'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { ConvMessageData, ConvReactionData, ConvMemberData } from '../../shared/types'\nimport type { MessageRecord, ReactionRecord, MemberRecord, ConversationObject } from './types'\n\ninterface UseConversationOptions {\n onMessageSent?: (content: string, parentMessageId?: string) => void\n}\n\nexport function useConversation(opts?: UseConversationOptions): ConversationObject {\n const { user } = useUser()\n const { ready } = useRecordContext()\n\n const { records: allMessages } = useQuery<ConvMessageData>('conv_messages', { orderBy: '_created_at' })\n const { records: allReactions } = useQuery<ConvReactionData>('conv_reactions')\n const { records: members } = useQuery<ConvMemberData>('conv_members')\n\n const messageMut = useMutations<ConvMessageData>('conv_messages')\n const reactionMut = useMutations<ConvReactionData>('conv_reactions')\n\n const send = useCallback(\n (content: string, parentMessageId?: string, messageType?: string, metadata?: Record<string, unknown>) => {\n messageMut.create({\n Content: content,\n AuthorId: user?.id ?? '',\n ParentId: parentMessageId ?? '',\n Edited: 0,\n MessageType: messageType ?? 'message',\n Metadata: metadata ? JSON.stringify(metadata) : '',\n })\n opts?.onMessageSent?.(content, parentMessageId)\n },\n [messageMut, user?.id, opts?.onMessageSent],\n )\n\n const edit = useCallback(\n (recordId: string, content: string) => {\n const existing = allMessages.find((m) => m.recordId === recordId)\n if (!existing) return\n messageMut.put(recordId, { ...existing.data, Content: content, Edited: 1 })\n },\n [messageMut, allMessages],\n )\n\n const remove = useCallback(\n (recordId: string) => {\n const existing = allMessages.find((m) => m.recordId === recordId)\n if (!existing) return\n messageMut.put(recordId, {\n ...existing.data,\n Content: '',\n MessageType: 'deleted',\n Metadata: '',\n })\n },\n [messageMut, allMessages],\n )\n\n const toggleReaction = useCallback(\n (messageId: string, emoji: string) => {\n const existing = allReactions.find(\n (r) => r.data.MessageId === messageId && r.data.Emoji === emoji && r.data.UserId === user?.id,\n )\n if (existing) {\n reactionMut.remove(existing.recordId)\n } else {\n reactionMut.create({ MessageId: messageId, Emoji: emoji, UserId: user?.id ?? '' })\n }\n },\n [reactionMut, allReactions, user?.id],\n )\n\n return useMemo(\n () => ({\n messages: allMessages as MessageRecord[],\n reactions: allReactions as ReactionRecord[],\n members: members as MemberRecord[],\n status: ready ? ('connected' as const) : ('connecting' as const),\n send,\n edit,\n remove,\n toggleReaction,\n }),\n [allMessages, allReactions, members, ready, send, edit, remove, toggleReaction],\n )\n}\n","/**\n * Shared messaging utility functions.\n */\n\nimport type { ReactionRecord, GroupedReaction, MessageRecord } from './types'\n\nexport function groupReactionsForMessage(\n reactions: ReactionRecord[],\n messageId: string,\n currentUserId: string,\n): GroupedReaction[] {\n const forMessage = reactions.filter((r) => r.data.MessageId === messageId)\n const groups = new Map<string, { count: number; currentUserReacted: boolean; userIds: string[] }>()\n\n for (const r of forMessage) {\n const existing = groups.get(r.data.Emoji) ?? { count: 0, currentUserReacted: false, userIds: [] }\n existing.count++\n existing.userIds.push(r.data.UserId)\n if (r.data.UserId === currentUserId) existing.currentUserReacted = true\n groups.set(r.data.Emoji, existing)\n }\n\n return Array.from(groups.entries()).map(([emoji, data]) => ({\n emoji,\n count: data.count,\n currentUserReacted: data.currentUserReacted,\n userIds: data.userIds,\n }))\n}\n\n/** Default grouping threshold: 5 minutes */\nconst GROUPING_THRESHOLD_MS = 5 * 60 * 1000\n\n/**\n * Determine whether a message should be visually grouped with the previous one\n * (same author, within threshold, no date boundary).\n */\nexport function shouldGroupMessages(\n current: MessageRecord,\n previous: MessageRecord | null | undefined,\n options?: { thresholdMs?: number; dateChanged?: boolean },\n): boolean {\n if (!previous) return false\n if (options?.dateChanged) return false\n if (previous.data.AuthorId !== current.data.AuthorId) return false\n const timeDiff = new Date(current.createdAt).getTime() - new Date(previous.createdAt).getTime()\n return timeDiff < (options?.thresholdMs ?? GROUPING_THRESHOLD_MS)\n}\n\n/**\n * Compute thread reply counts from a flat message array.\n */\nexport function getThreadCounts(messages: MessageRecord[]): Map<string, number> {\n const counts = new Map<string, number>()\n for (const m of messages) {\n if (m.data.ParentId) {\n counts.set(m.data.ParentId, (counts.get(m.data.ParentId) ?? 0) + 1)\n }\n }\n return counts\n}\n\n/**\n * Format a message timestamp for display.\n * Returns \"2:30 PM\" style short time.\n */\nexport function formatMessageTime(dateStr: string): string {\n return new Date(dateStr).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n}\n\n/**\n * Format a full message timestamp.\n * Returns \"Mar 5, 2026 at 2:30 PM\" style.\n */\nexport function formatFullTimestamp(dateStr: string): string {\n const date = new Date(dateStr)\n const datePart = date.toLocaleDateString([], { month: 'short', day: 'numeric', year: 'numeric' })\n const timePart = date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })\n return `${datePart} at ${timePart}`\n}\n","/**\n * Conversation Display Utilities\n *\n * Shared helpers for rendering conversation names, participant lists,\n * and type checks across apps (slack-clone, discord-clone, etc.).\n */\n\nimport type { UserInfo } from '../storage/hooks/useUserLookup'\n\ninterface ConversationData {\n Name: string\n Type: string\n ParticipantIds: string\n ParticipantHash: string\n}\n\n/**\n * Get a display name for a conversation.\n *\n * - Channels: use Name field\n * - DMs: look up the other participant's name\n * - Group DMs: \"User A, User B, +N\"\n */\nexport function getConversationDisplayName(\n conversation: { data: ConversationData },\n currentUserId: string,\n getUser: (id: string) => UserInfo | undefined,\n): string {\n const { Type, Name, ParticipantIds } = conversation.data\n\n if (Type !== 'dm' && Type !== 'group') {\n return Name || 'Untitled'\n }\n\n const ids = getConversationParticipantIds(conversation, currentUserId)\n\n if (ids.length === 0) return 'Unknown'\n\n if (Type === 'dm') {\n const other = getUser(ids[0])\n return other?.name ?? 'Unknown'\n }\n\n // Group DM\n const MAX_NAMES = 3\n const names: string[] = []\n for (let i = 0; i < Math.min(ids.length, MAX_NAMES); i++) {\n const u = getUser(ids[i])\n names.push(u?.name?.split(' ')[0] ?? 'Unknown')\n }\n const remaining = ids.length - MAX_NAMES\n if (remaining > 0) {\n return `${names.join(', ')}, +${remaining}`\n }\n return names.join(', ')\n}\n\n/**\n * Check if a conversation type is a DM or group DM.\n */\nexport function isDMConversation(type: string): boolean {\n return type === 'dm' || type === 'group'\n}\n\n/**\n * Parse participant IDs from a conversation.\n * Tries ParticipantIds JSON first, falls back to ParticipantHash (colon-separated).\n */\nexport function getConversationParticipantIds(\n conversation: { data: Pick<ConversationData, 'ParticipantIds' | 'ParticipantHash'> },\n excludeUserId?: string,\n): string[] {\n let ids: string[] = []\n\n // Try ParticipantIds JSON first\n try {\n const parsed = JSON.parse(conversation.data.ParticipantIds)\n if (Array.isArray(parsed) && parsed.length > 0) {\n ids = parsed\n }\n } catch {\n // fall through to ParticipantHash\n }\n\n // Fallback to ParticipantHash (colon-separated user IDs)\n if (ids.length === 0 && conversation.data.ParticipantHash) {\n ids = conversation.data.ParticipantHash.split(':')\n }\n\n if (excludeUserId) {\n return ids.filter((id) => id !== excludeUserId)\n }\n return ids\n}\n","/**\n * Safely parse a Metadata field that may be a JSON string, an object, or null/undefined.\n * Returns the parsed object or null on failure.\n */\nexport function parseMessageMetadata(raw: unknown): Record<string, unknown> | null {\n if (!raw) return null\n if (typeof raw === 'object') return raw as Record<string, unknown>\n if (typeof raw === 'string') {\n try { return JSON.parse(raw) } catch { return null }\n }\n return null\n}\n","/**\n * useConversations Hook\n *\n * Standardized conversation directory backed by the `conversations` and\n * `conversation_state` collections in the dir:{appName} DO.\n *\n * Apps that need a sidebar list of channels / DMs / threads should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call useConversations() inside a RecordProvider.\n */\n\nimport { useCallback, useMemo, useRef } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryConversationData, ConversationStateData } from '../../shared/types'\n\nexport function useConversations() {\n const { records: conversations, status } = useQuery<DirectoryConversationData>('conversations')\n const { create, put } = useMutations<DirectoryConversationData>('conversations')\n const { records: stateRecords } = useQuery<ConversationStateData>('conversation_state')\n const stateMut = useMutations<ConversationStateData>('conversation_state')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const recentCreationsRef = useRef(new Map<string, DirectoryConversationData>())\n for (const [id] of recentCreationsRef.current) {\n if (conversations.find((c) => c.recordId === id)) {\n recentCreationsRef.current.delete(id)\n }\n }\n\n const readStateMap = useMemo(\n () => new Map(stateRecords.map((r) => [r.data.ConversationId, r.data.LastReadAt])),\n [stateRecords],\n )\n\n const readMessageCountMap = useMemo(\n () => new Map(stateRecords.map((r) => [r.data.ConversationId, r.data.LastReadMessageCount ?? 0])),\n [stateRecords],\n )\n\n const starredSet = useMemo(\n () => new Set(stateRecords.filter((r) => r.data.Starred).map((r) => r.data.ConversationId)),\n [stateRecords],\n )\n\n const archivedSet = useMemo(\n () => new Set(stateRecords.filter((r) => r.data.Archived).map((r) => r.data.ConversationId)),\n [stateRecords],\n )\n\n\n const getConversationState = useCallback(\n (conversationId: string): ConversationStateData | undefined => {\n return stateRecords.find((r) => r.data.ConversationId === conversationId)?.data\n },\n [stateRecords],\n )\n\n const defaultConvFields = {\n Visibility: 'public',\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n MessageCount: 0,\n }\n\n const createChannel = useCallback(\n async (name: string, description?: string) => {\n const existing = conversations.find((r) => r.data.Name === name && r.data.Type !== 'dm')\n if (existing) return existing.recordId\n\n const recordId = await create({\n Name: name,\n Description: description ?? '',\n Type: 'public',\n CreatedBy: user?.id ?? '',\n ParticipantHash: '',\n ParticipantIds: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n ...defaultConvFields,\n })\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const createDM = useCallback(\n async (otherUserId: string) => {\n if (!user?.id) return null\n const hash = [user.id, otherUserId].sort().join(':')\n\n const existing = conversations.find((r) => r.data.ParticipantHash === hash)\n if (existing) return existing.recordId\n\n const data: DirectoryConversationData = {\n Name: '',\n Description: '',\n Type: 'dm',\n Visibility: 'private',\n CreatedBy: user.id,\n ParticipantHash: hash,\n ParticipantIds: JSON.stringify([user.id, otherUserId]),\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n MessageCount: 0,\n }\n const recordId = await create(data)\n recentCreationsRef.current.set(recordId, data)\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const createGroupDM = useCallback(\n async (participantIds: string[]) => {\n if (!user?.id) return null\n // Add current user + deduplicate\n const allIds = [...new Set([user.id, ...participantIds])]\n if (allIds.length < 3) return null // Use createDM for 2 participants\n\n const hash = allIds.sort().join(':')\n\n const existing = conversations.find((r) => r.data.ParticipantHash === hash)\n if (existing) return existing.recordId\n\n const data: DirectoryConversationData = {\n Name: '',\n Description: '',\n Type: 'group',\n Visibility: 'private',\n CreatedBy: user.id,\n ParticipantHash: hash,\n ParticipantIds: JSON.stringify(allIds),\n Status: 'active',\n AssigneeId: '',\n LinkedRef: '',\n LastMessageAt: '',\n LastMessagePreview: '',\n LastMessageAuthor: '',\n MessageCount: 0,\n }\n const recordId = await create(data)\n recentCreationsRef.current.set(recordId, data)\n return recordId\n },\n [create, user?.id, conversations],\n )\n\n const lookupByName = useCallback(\n (name: string) => {\n const found = conversations.find((r) => r.data.Name === name)\n return found?.recordId ?? null\n },\n [conversations],\n )\n\n const updateLastMessage = useCallback(\n (conversationId: string, preview: string, authorId?: string) => {\n const conv = conversations.find((c) => c.recordId === conversationId)\n const baseData = conv?.data ?? recentCreationsRef.current.get(conversationId)\n if (!baseData) return\n const updatedData = {\n ...baseData,\n LastMessageAt: new Date().toISOString(),\n LastMessagePreview: preview.slice(0, 100),\n LastMessageAuthor: authorId ?? baseData.LastMessageAuthor,\n MessageCount: (baseData.MessageCount ?? 0) + 1,\n }\n put(conversationId, updatedData)\n if (recentCreationsRef.current.has(conversationId)) {\n recentCreationsRef.current.set(conversationId, updatedData)\n }\n },\n [put, conversations],\n )\n\n /** Upsert the user's conversation_state row for a conversation. */\n const upsertState = useCallback(\n (conversationId: string, partial: Partial<ConversationStateData>) => {\n if (!user?.id) return\n const existing = stateRecords.find(\n (r) => r.data.ConversationId === conversationId && r.data.UserId === user.id,\n )\n const base: ConversationStateData = existing?.data ?? {\n ConversationId: conversationId,\n UserId: user.id,\n LastReadAt: '',\n LastReadMessageCount: 0,\n Starred: 0,\n Archived: 0,\n Trashed: 0,\n Labels: '',\n Folder: '',\n }\n const recordId = existing?.recordId ?? `state-${user.id}-${conversationId}`\n stateMut.put(recordId, { ...base, ...partial })\n },\n [stateMut, stateRecords, user?.id],\n )\n\n const markRead = useCallback(\n (conversationId: string) => {\n const conv = conversations.find((c) => c.recordId === conversationId)\n const msgCount = conv?.data.MessageCount ?? recentCreationsRef.current.get(conversationId)?.MessageCount ?? 0\n upsertState(conversationId, {\n LastReadAt: new Date().toISOString(),\n LastReadMessageCount: msgCount,\n })\n },\n [upsertState, conversations],\n )\n\n const toggleStar = useCallback(\n (conversationId: string) => {\n const isStarred = starredSet.has(conversationId)\n upsertState(conversationId, { Starred: isStarred ? 0 : 1 })\n },\n [upsertState, starredSet],\n )\n\n const setArchived = useCallback(\n (conversationId: string, archived: boolean) => {\n upsertState(conversationId, { Archived: archived ? 1 : 0 })\n },\n [upsertState],\n )\n\n const setTrashed = useCallback(\n (conversationId: string, trashed: boolean) => {\n upsertState(conversationId, { Trashed: trashed ? 1 : 0 })\n },\n [upsertState],\n )\n\n const setLabels = useCallback(\n (conversationId: string, labels: string[]) => {\n upsertState(conversationId, { Labels: JSON.stringify(labels) })\n },\n [upsertState],\n )\n\n const setFolder = useCallback(\n (conversationId: string, folder: string) => {\n upsertState(conversationId, { Folder: folder })\n },\n [upsertState],\n )\n\n return {\n conversations: conversations as RecordData<DirectoryConversationData>[],\n ready,\n createChannel,\n createDM,\n createGroupDM,\n lookupByName,\n updateLastMessage,\n readStateMap,\n readMessageCountMap,\n starredSet,\n archivedSet,\n getConversationState,\n upsertState,\n markRead,\n toggleStar,\n setArchived,\n setTrashed,\n setLabels,\n setFolder,\n }\n}\n","/**\n * useCommunities Hook\n *\n * CRUD operations for the `communities` and `memberships` collections\n * in the dir:{appName} DO.\n *\n * Apps that need forums, groups, or boards should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call useCommunities() inside a RecordProvider.\n */\n\nimport { useCallback, useMemo } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryCommunityData, DirectoryMembershipData } from '../../shared/types'\n\nexport function useCommunities() {\n const { records: communities, status } = useQuery<DirectoryCommunityData>('communities')\n const communityMut = useMutations<DirectoryCommunityData>('communities')\n const { records: memberships } = useQuery<DirectoryMembershipData>('memberships')\n const membershipMut = useMutations<DirectoryMembershipData>('memberships')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const membershipMap = useMemo(() => {\n const map = new Map<string, DirectoryMembershipData[]>()\n for (const m of memberships) {\n const list = map.get(m.data.CommunityId) ?? []\n list.push(m.data)\n map.set(m.data.CommunityId, list)\n }\n return map\n }, [memberships])\n\n const myMemberships = useMemo(\n () => new Set(\n memberships\n .filter((m) => m.data.UserId === user?.id)\n .map((m) => m.data.CommunityId),\n ),\n [memberships, user?.id],\n )\n\n const createCommunity = useCallback(\n async (name: string, opts?: { description?: string; type?: string; visibility?: string; rules?: string }) => {\n const existing = communities.find((c) => c.data.Name === name)\n if (existing) return existing.recordId\n\n const recordId = await communityMut.create({\n Name: name,\n Description: opts?.description ?? '',\n CreatedBy: user?.id ?? '',\n Type: opts?.type ?? 'community',\n Visibility: opts?.visibility ?? 'public',\n MemberCount: 0,\n Rules: opts?.rules ?? '',\n IconUrl: '',\n CoverUrl: '',\n })\n return recordId\n },\n [communityMut, user?.id, communities],\n )\n\n const updateCommunity = useCallback(\n (communityId: string, updates: Partial<DirectoryCommunityData>) => {\n const existing = communities.find((c) => c.recordId === communityId)\n if (!existing) return\n communityMut.put(communityId, { ...existing.data, ...updates })\n },\n [communityMut, communities],\n )\n\n const joinCommunity = useCallback(\n async (communityId: string, userName: string) => {\n if (!user?.id) return null\n const existing = memberships.find(\n (m) => m.data.CommunityId === communityId && m.data.UserId === user.id,\n )\n if (existing) return existing.recordId\n\n const recordId = await membershipMut.create({\n CommunityId: communityId,\n UserId: user.id,\n UserName: userName,\n Role: 'member',\n JoinedAt: new Date().toISOString(),\n })\n return recordId\n },\n [membershipMut, memberships, user?.id],\n )\n\n const leaveCommunity = useCallback(\n (communityId: string) => {\n if (!user?.id) return\n const membership = memberships.find(\n (m) => m.data.CommunityId === communityId && m.data.UserId === user.id,\n )\n if (membership) {\n membershipMut.remove(membership.recordId)\n }\n },\n [membershipMut, memberships, user?.id],\n )\n\n const getMembersOf = useCallback(\n (communityId: string): DirectoryMembershipData[] => {\n return membershipMap.get(communityId) ?? []\n },\n [membershipMap],\n )\n\n const lookupByName = useCallback(\n (name: string) => {\n const found = communities.find((c) => c.data.Name === name)\n return found?.recordId ?? null\n },\n [communities],\n )\n\n return {\n communities: communities as RecordData<DirectoryCommunityData>[],\n memberships: memberships as RecordData<DirectoryMembershipData>[],\n ready,\n myMemberships,\n createCommunity,\n updateCommunity,\n joinCommunity,\n leaveCommunity,\n getMembersOf,\n lookupByName,\n }\n}\n","/**\n * usePosts Hook\n *\n * CRUD operations for the `posts` collection in the dir:{appName} DO.\n *\n * Apps that need feeds, Q&A, or tweet-style content should:\n * 1. Add { type: 'dir', instanceId: APP_ID } to SHARED_CONNECTIONS.\n * 2. Call usePosts() inside a RecordProvider.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery } from '../storage/hooks/useQuery'\nimport { useMutations } from '../storage/hooks/useMutations'\nimport { useUser } from '../storage/hooks/useUser'\nimport type { RecordData } from '../storage/types'\nimport type { DirectoryPostData } from '../../shared/types'\n\nexport function usePosts(opts?: { communityId?: string }) {\n const { records: allPosts, status } = useQuery<DirectoryPostData>('posts')\n const postMut = useMutations<DirectoryPostData>('posts')\n const { user } = useUser()\n\n const ready = status === 'ready'\n\n const posts = opts?.communityId\n ? allPosts.filter((p) => p.data.CommunityId === opts.communityId)\n : allPosts\n\n const createPost = useCallback(\n async (data: {\n title: string\n content: string\n type?: string\n communityId?: string\n parentId?: string\n tags?: string[]\n linkUrl?: string\n }) => {\n const recordId = await postMut.create({\n Title: data.title,\n Content: data.content,\n AuthorId: user?.id ?? '',\n Type: data.type ?? 'post',\n CommunityId: data.communityId ?? '',\n ParentId: data.parentId ?? '',\n ConversationId: '',\n Status: 'published',\n Tags: data.tags ? JSON.stringify(data.tags) : '',\n LinkUrl: data.linkUrl ?? '',\n })\n return recordId\n },\n [postMut, user?.id],\n )\n\n const updatePost = useCallback(\n (postId: string, updates: Partial<DirectoryPostData>) => {\n const existing = allPosts.find((p) => p.recordId === postId)\n if (!existing) return\n postMut.put(postId, { ...existing.data, ...updates })\n },\n [postMut, allPosts],\n )\n\n const deletePost = useCallback(\n (postId: string) => {\n postMut.remove(postId)\n },\n [postMut],\n )\n\n const setConversationId = useCallback(\n (postId: string, conversationId: string) => {\n updatePost(postId, { ConversationId: conversationId })\n },\n [updatePost],\n )\n\n return {\n posts: posts as RecordData<DirectoryPostData>[],\n ready,\n createPost,\n updatePost,\n deletePost,\n setConversationId,\n }\n}\n","'use client';\n\nimport React, { useEffect, type ReactNode } from 'react';\nimport type { DeepSpaceThemeConfig } from './types';\nimport { applyDeepSpaceTheme, readThemeFromDOM } from './applyTheme';\n\nexport interface DeepSpaceThemeProviderProps {\n children: ReactNode;\n /**\n * Explicit theme config. If omitted, auto-detects from the widget's\n * --color-* CSS custom properties (defined in the @theme block of styles.css).\n */\n theme?: DeepSpaceThemeConfig;\n}\n\n/**\n * DeepSpaceThemeProvider — sets --theme-* CSS variables for pill,\n * and other DeepSpace UI components on deployed sites and mini-apps.\n *\n * **Zero-config**: reads colors from the widget's @theme CSS block.\n * **Explicit**: pass a `theme` prop to override.\n *\n * @example\n * ```tsx\n * // Zero-config — reads from styles.css @theme block\n * <DeepSpaceThemeProvider>\n * <App />\n * </DeepSpaceThemeProvider>\n *\n * // Explicit theme\n * <DeepSpaceThemeProvider theme={{\n * primaryColor: '#0f172a',\n * secondaryColor: '#1e293b',\n * accentColor: '#8b5cf6',\n * textColor: '#f1f5f9',\n * }}>\n * <App />\n * </DeepSpaceThemeProvider>\n * ```\n */\nexport function DeepSpaceThemeProvider({\n children,\n theme,\n}: DeepSpaceThemeProviderProps): React.ReactElement {\n useEffect(() => {\n const root = document.documentElement;\n const config = theme ?? readThemeFromDOM(root);\n applyDeepSpaceTheme(config, root);\n }, [theme]);\n\n return <>{children}</>;\n}\n","import type { DeepSpaceThemeConfig } from './types';\n\n/**\n * CSS color-mix helper — produces `color-mix(in srgb, color pct%, base)`.\n * Works with any valid CSS color format (hex, rgb, rgba, hsl, named).\n */\nfunction mix(color: string, pct: number, base = 'transparent'): string {\n return `color-mix(in srgb, ${color} ${Math.round(pct * 100)}%, ${base})`;\n}\n\n/**\n * Determine whether a CSS color is \"dark\" using relative luminance.\n */\nexport function isDarkColor(color: string): boolean {\n const c = color.trim();\n\n // getComputedStyle normalises colors to rgb()/rgba() — handle that first.\n const rgbMatch = c.match(/^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)/);\n if (rgbMatch) {\n const r = parseFloat(rgbMatch[1]) / 255;\n const g = parseFloat(rgbMatch[2]) / 255;\n const b = parseFloat(rgbMatch[3]) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.5;\n }\n\n // #hex (#rgb / #rrggbb)\n if (!c.startsWith('#')) return true; // unrecognised format — assume dark\n let hex = c.slice(1);\n if (hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];\n if (hex.length !== 6) return true;\n const r = parseInt(hex.slice(0, 2), 16) / 255;\n const g = parseInt(hex.slice(2, 4), 16) / 255;\n const b = parseInt(hex.slice(4, 6), 16) / 255;\n return 0.2126 * r + 0.7152 * g + 0.0722 * b < 0.5;\n}\n\n/**\n * Static UI tokens for light themes.\n *\n * KEEP IN SYNC with apps/web/app/styles/tokens.css (:root block)\n *\n * Two delivery paths use these same values:\n * - Web app (SSR): defined in tokens.css (instant, no flash)\n * - Deployed sites: applyDeepSpaceTheme() sets them via JS from these constants\n */\nconst UI_TOKENS_LIGHT: Record<string, string> = {\n '--ui-overlay': 'rgba(0, 0, 0, 0.5)',\n '--ui-bg-primary': '#ffffff',\n '--ui-bg-secondary': '#f9fafb',\n '--ui-bg-tertiary': '#f3f4f6',\n '--ui-bg-elevated': '#ffffff',\n '--ui-border': '#e5e7eb',\n '--ui-border-strong': '#d1d5db',\n '--ui-text-primary': '#111827',\n '--ui-text-secondary': '#6b7280',\n '--ui-text-muted': '#9ca3af',\n '--ui-text-disabled': '#d1d5db',\n '--ui-hover-bg': '#f3f4f6',\n '--ui-success': '#10b981',\n '--ui-warning': '#f59e0b',\n '--ui-error': '#ef4444',\n '--ui-shadow-sm': '0 1px 3px rgba(0, 0, 0, 0.1)',\n '--ui-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.1)',\n '--ui-shadow-lg': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',\n '--ui-vote-up': '#f97316',\n '--ui-vote-down': '#3b82f6',\n};\n\n/** Static UI tokens for dark themes — KEEP IN SYNC with [data-ui-theme=\"dark\"] in tokens.css */\nconst UI_TOKENS_DARK: Record<string, string> = {\n '--ui-overlay': 'rgba(0, 0, 0, 0.7)',\n '--ui-bg-primary': '#1a1a1b',\n '--ui-bg-secondary': '#1e1f20',\n '--ui-bg-tertiary': '#2d2e30',\n '--ui-bg-elevated': '#1e1f20',\n '--ui-border': '#3c4043',\n '--ui-border-strong': '#5a5d61',\n '--ui-text-primary': '#e8eaed',\n '--ui-text-secondary': '#bdc1c6',\n '--ui-text-muted': '#9aa0a6',\n '--ui-text-disabled': '#5a5d61',\n '--ui-hover-bg': '#3c4043',\n '--ui-success': '#34d399',\n '--ui-warning': '#fbbf24',\n '--ui-error': '#f87171',\n '--ui-shadow-sm': '0 1px 3px rgba(0, 0, 0, 0.25)',\n '--ui-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.3)',\n '--ui-shadow-lg': '0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.3)',\n '--ui-vote-up': '#f97316',\n '--ui-vote-down': '#60a5fa',\n};\n\n/** All --ui-* property names for cleanup */\nconst UI_TOKEN_PROPERTIES = [\n '--ui-overlay', '--ui-bg-primary', '--ui-bg-secondary', '--ui-bg-tertiary', '--ui-bg-elevated',\n '--ui-border', '--ui-border-strong',\n '--ui-text-primary', '--ui-text-secondary', '--ui-text-muted', '--ui-text-disabled',\n '--ui-accent', '--ui-accent-hover', '--ui-accent-secondary',\n '--ui-hover-bg', '--ui-active-bg', '--ui-active-text',\n '--ui-success', '--ui-warning', '--ui-error',\n '--ui-shadow-sm', '--ui-shadow-md', '--ui-shadow-lg',\n '--ui-vote-up', '--ui-vote-down',\n] as const;\n\n/**\n * All CSS custom properties set by applyDeepSpaceTheme.\n * Used by clearDeepSpaceTheme to remove stale values on theme switch.\n */\nexport const DEEPSPACE_THEME_PROPERTIES = [\n // Panel & background\n '--theme-panel-bg', '--theme-panel-bg-opaque', '--theme-panel-bg-secondary',\n '--theme-panel-solid', '--theme-top-panel-bg', '--theme-panel-border',\n '--theme-panel-highlight', '--theme-background',\n // Buttons\n '--theme-button-bg', '--theme-button-border', '--theme-button-hover',\n '--theme-button-border-hover', '--theme-button-active', '--theme-button-fg',\n // Text\n '--theme-text', '--theme-text-hover', '--theme-text-secondary', '--theme-text-tertiary',\n // Accent & colors\n '--theme-accent', '--theme-accent-contrast', '--theme-accent-hover',\n '--theme-secondary', '--theme-secondary-hover', '--theme-primary-hover',\n // Shadows\n '--theme-shadow-primary', '--theme-shadow-secondary', '--theme-shadow-accent',\n '--theme-component-shadow',\n // Surfaces\n '--theme-surface', '--theme-surface-solid',\n '--theme-library-card-bg', '--theme-library-surface', '--theme-library-panel-glass',\n // Borders\n '--theme-border',\n // Status\n '--theme-destructive', '--theme-destructive-hover',\n '--theme-success', '--theme-warning', '--theme-warning-bg', '--theme-warning-fg',\n // Glass\n '--theme-highlight', '--theme-font',\n '--beveled-gradient', '--beveled-glass-shadow',\n // UI component tokens\n ...UI_TOKEN_PROPERTIES,\n] as const;\n\n/**\n * Remove all CSS custom properties previously set by applyDeepSpaceTheme.\n * Call before re-applying a new theme to prevent stale variable bleed.\n */\nexport function clearDeepSpaceTheme(\n root: HTMLElement = document.documentElement,\n): void {\n for (const prop of DEEPSPACE_THEME_PROPERTIES) {\n root.style.removeProperty(prop);\n }\n}\n\n/**\n * Apply the correct set of --ui-* inline styles for the given UI theme.\n *\n * Single source of truth for --ui-* token application. Called by:\n * - `applyDeepSpaceTheme()` (initial theme setup, canvas theme changes)\n * - `useUITheme` toggle (user switches dark <-> light)\n *\n * When `accent` overrides are provided they are used directly (the\n * `applyDeepSpaceTheme` path). Otherwise the current --theme-accent /\n * --theme-secondary values are read from computed styles.\n */\nexport function applyUIThemeTokens(\n theme: 'dark' | 'light',\n root: HTMLElement = document.documentElement,\n accent?: { color: string; hover: string; secondary: string },\n): void {\n const dark = theme === 'dark';\n\n // Base tokens (surfaces, text, borders, etc.)\n const base = dark ? UI_TOKENS_DARK : UI_TOKENS_LIGHT;\n for (const [prop, val] of Object.entries(base)) {\n root.style.setProperty(prop, val);\n }\n\n // Accent-derived tokens\n const accentColor = accent?.color\n ?? (getComputedStyle(root).getPropertyValue('--theme-accent').trim() || (dark ? '#818cf8' : '#3b82f6'));\n const accentHover = accent?.hover\n ?? `color-mix(in srgb, ${accentColor} 90%, black)`;\n const secondary = accent?.secondary\n ?? (getComputedStyle(root).getPropertyValue('--theme-secondary').trim() || accentColor);\n\n root.style.setProperty('--ui-accent', accentColor);\n root.style.setProperty('--ui-accent-hover', accentHover);\n root.style.setProperty('--ui-accent-secondary', secondary);\n root.style.setProperty('--ui-active-bg', `color-mix(in srgb, ${accentColor} ${dark ? 15 : 10}%, transparent)`);\n root.style.setProperty('--ui-active-text', dark ? secondary : accentColor);\n}\n\n/**\n * Apply a DeepSpace theme by setting CSS custom properties on the given root element.\n *\n * Maps a simplified theme config to the full set of --theme-* CSS variables\n * consumed by DeepSpace UI components, pills, and panels.\n *\n * Uses CSS color-mix() for derived colors so any valid CSS color format works\n * (hex, rgb, rgba, hsl, etc.).\n */\nexport function applyDeepSpaceTheme(\n config: DeepSpaceThemeConfig,\n root: HTMLElement = document.documentElement,\n): void {\n const {\n primaryColor,\n panelColor = primaryColor,\n secondaryColor,\n accentColor,\n accentContrastColor = '#ffffff',\n textColor,\n shadowColor = '#000000',\n borderColor = secondaryColor,\n backgroundColor = primaryColor,\n highlightColor = '#ffffff',\n glassmorphism = true,\n } = config;\n\n // ---------- derived colors ----------\n\n // Panel backgrounds\n const panelBg = glassmorphism ? mix(panelColor, 0.4) : panelColor;\n const panelBgOpaque = glassmorphism ? mix(panelColor, 0.85) : panelColor;\n const panelSolid = glassmorphism ? mix(panelColor, 0.6, 'white') : panelColor;\n const panelBgSecondary = glassmorphism ? mix(secondaryColor, 0.5) : secondaryColor;\n const topPanelBg = glassmorphism ? mix(panelColor, 0.6) : panelColor;\n\n // Borders\n const panelBorder = glassmorphism ? mix(borderColor, 0.3) : borderColor;\n\n // Buttons\n const buttonBg = glassmorphism ? mix(secondaryColor, 0.4) : secondaryColor;\n const buttonBorder = glassmorphism ? mix(borderColor, 0.3) : borderColor;\n const buttonBorderHover = glassmorphism ? mix(borderColor, 0.7) : borderColor;\n const buttonHover = mix(accentColor, 0.2);\n const buttonActive = mix(accentColor, 0.3);\n\n // Text\n const textSecondary = mix(textColor, 0.8);\n const textTertiary = mix(textColor, 0.6);\n\n // Accents\n const accentHover = mix(accentColor, 0.9, 'black');\n const secondary = mix(secondaryColor, 0.9);\n const secondaryHover = mix(secondaryColor, 0.9, 'black');\n const primaryHover = mix(primaryColor, 0.9, 'black');\n\n // Shadows\n const shadowPrimary = mix(shadowColor, 0.1);\n const shadowSecondary = mix(shadowColor, 0.2);\n const shadowAccent = mix(shadowColor, 0.01);\n const componentShadow =\n `0 1px 3px ${mix(shadowColor, 0.12)}, 0 1px 2px ${mix(shadowColor, 0.24)}`;\n\n // Surfaces & highlights\n const surface = mix(primaryColor, 0.95);\n const panelHighlight = glassmorphism ? mix(textColor, 0.05) : 'transparent';\n\n // Glass gradients\n const beveledGradient = `linear-gradient(180deg,color-mix(in srgb, ${highlightColor} 40%, transparent) 0%,color-mix(in srgb, ${highlightColor} 15%, transparent) 15%,color-mix(in srgb, ${highlightColor} 5%, transparent) 50%,color-mix(in srgb, ${highlightColor} 8%, transparent) 85%,color-mix(in srgb, ${highlightColor} 25%, transparent) 100%)`;\n\n // Glass shadows\n const beveledGlassShadow = [\n `inset 0 1px 1px color-mix(in srgb, ${highlightColor} 80%, transparent)`,\n `inset 0 2px 4px color-mix(in srgb, ${highlightColor} 40%, transparent)`,\n `inset 0 -1px 2px rgba(0, 0, 0, 0.08)`,\n `inset 0 -0.5px 0.5px rgba(0, 0, 0, 0.12)`,\n `0 4px 2px -2px rgba(0, 0, 0, 0.12)`,\n `0 8px 16px -4px rgba(0, 0, 0, 0.1)`,\n `0 0 0 0.5px color-mix(in srgb, ${highlightColor} 20%, transparent) inset`,\n ].join(', ');\n\n // ---------- dark/light detection for UI tokens ----------\n // Respect the user's explicit UI theme preference (set by useUITheme via\n // localStorage) if one exists. Only auto-detect from background luminance\n // when no preference has been set (e.g. deployed sites / mini-apps).\n const preferredUITheme = root.dataset.uiTheme;\n const dark = (preferredUITheme === 'dark' || preferredUITheme === 'light')\n ? preferredUITheme === 'dark'\n : isDarkColor(backgroundColor);\n\n // ---------- data attributes ----------\n root.dataset.glassmorphism = glassmorphism ? 'enabled' : 'disabled';\n if (!preferredUITheme) {\n root.dataset.uiTheme = dark ? 'dark' : 'light';\n }\n\n // ---------- batch set CSS properties ----------\n const updates: [string, string][] = [\n // Panel & background\n ['--theme-panel-bg', panelBg],\n ['--theme-panel-bg-opaque', panelBgOpaque],\n ['--theme-panel-bg-secondary', panelBgSecondary],\n ['--theme-panel-solid', panelSolid],\n ['--theme-top-panel-bg', topPanelBg],\n ['--theme-panel-border', panelBorder],\n ['--theme-panel-highlight', panelHighlight],\n ['--theme-background', backgroundColor],\n\n // Buttons\n ['--theme-button-bg', buttonBg],\n ['--theme-button-border', buttonBorder],\n ['--theme-button-hover', buttonHover],\n ['--theme-button-border-hover', buttonBorderHover],\n ['--theme-button-active', buttonActive],\n ['--theme-button-fg', textColor],\n\n // Text\n ['--theme-text', textColor],\n ['--theme-text-hover', textColor],\n ['--theme-text-secondary', textSecondary],\n ['--theme-text-tertiary', textTertiary],\n\n // Accent & colors\n ['--theme-accent', accentColor],\n ['--theme-accent-contrast', accentContrastColor],\n ['--theme-accent-hover', accentHover],\n ['--theme-secondary', secondary],\n ['--theme-secondary-hover', secondaryHover],\n ['--theme-primary-hover', primaryHover],\n\n // Shadows\n ['--theme-shadow-primary', shadowPrimary],\n ['--theme-shadow-secondary', shadowSecondary],\n ['--theme-shadow-accent', shadowAccent],\n ['--theme-component-shadow', componentShadow],\n\n // Surfaces\n ['--theme-surface', surface],\n ['--theme-surface-solid', primaryColor],\n ['--theme-library-card-bg', 'rgba(24, 24, 27, 0.95)'],\n ['--theme-library-surface', 'rgba(9, 9, 11, 0.92)'],\n ['--theme-library-panel-glass', 'rgba(24, 24, 27, 0.85)'],\n\n // Borders\n ['--theme-border', mix(borderColor, 0.8)],\n\n // Status\n ['--theme-destructive', '#FF3B30'],\n ['--theme-destructive-hover', 'rgba(255, 59, 48, 0.1)'],\n ['--theme-success', '#34C759'],\n ['--theme-warning', '#FF9500'],\n ['--theme-warning-bg', 'rgba(245, 158, 11, 0.15)'],\n ['--theme-warning-fg', '#f59e0b'],\n\n // Glass highlight\n ['--theme-highlight', highlightColor],\n\n // Font\n ['--theme-font', \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"],\n\n // Glass gradients & shadows\n ['--beveled-gradient', beveledGradient],\n ['--beveled-glass-shadow', beveledGlassShadow],\n ];\n\n for (const [property, value] of updates) {\n root.style.setProperty(property, value);\n }\n\n // ---------- UI component tokens (modals, profile, library, etc.) ----------\n applyUIThemeTokens(dark ? 'dark' : 'light', root, {\n color: accentColor,\n hover: accentHover,\n secondary,\n });\n}\n\n/**\n * Read a DeepSpace theme config from CSS custom properties on the DOM.\n *\n * Reads the widget template's --color-* variables (from the @theme block)\n * and maps them to a DeepSpaceThemeConfig.\n *\n * Falls back to sensible dark-theme defaults if variables are missing.\n */\nexport function readThemeFromDOM(\n root: HTMLElement = document.documentElement,\n): DeepSpaceThemeConfig {\n const styles = getComputedStyle(root);\n const get = (name: string, fallback: string): string =>\n styles.getPropertyValue(name).trim() || fallback;\n\n return {\n primaryColor: get('--color-surface-elevated', '#0f172a'),\n secondaryColor: get('--color-surface-overlay', '#1e293b'),\n accentColor: get('--color-primary', '#818cf8'),\n textColor: get('--color-content', '#f1f5f9'),\n borderColor: get('--color-border', 'rgba(51, 65, 85, 0.5)'),\n backgroundColor: get('--color-surface', '#0a0f1a'),\n highlightColor: '#ffffff',\n shadowColor: '#000000',\n accentContrastColor: '#ffffff',\n };\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\n/**\n * Reads `data-ui-theme` from the root element (set by `applyDeepSpaceTheme`)\n * and re-evaluates when a `canvas-theme-changed` event fires.\n */\nexport function useIsDarkTheme(): boolean {\n const [isDark, setIsDark] = useState(() =>\n typeof document === 'undefined' || document.documentElement.dataset.uiTheme !== 'light',\n );\n\n useEffect(() => {\n const update = (): void => {\n setIsDark(document.documentElement.dataset.uiTheme !== 'light');\n };\n update();\n window.addEventListener('canvas-theme-changed', update);\n return () => window.removeEventListener('canvas-theme-changed', update);\n }, []);\n\n return isDark;\n}\n","/**\n * PlatformProvider — Zero-cost context for platform worker integration.\n *\n * Always present in the component tree (via template main.tsx), but only\n * activates expensive features (WebSocket connections, polling) when a\n * component subscribes via the corresponding hook.\n *\n * Always available (zero overhead):\n * platformFetch(path, init) — authenticated fetch, prepends /platform\n *\n * Subscription-activated (zero cost until first subscriber):\n * useInbox() — inbox entries from InboxRoom WebSocket\n *\n * Auth uses getAuthToken() from deepspace on demand.\n * The template already provides DeepSpaceAuthProvider.\n *\n * Usage:\n * import { PlatformProvider, usePlatform, useInbox } from 'deepspace'\n *\n * // Already in template main.tsx:\n * <PlatformProvider>\n * <App />\n * </PlatformProvider>\n *\n * // In any component:\n * const { platformFetch } = usePlatform()\n * const inbox = useInbox() // activates WebSocket on mount\n */\n\nimport { createContext, useContext, useState, useEffect, useRef, useCallback } from 'react'\nimport { getAuthToken } from '../auth/token'\n\nexport interface InboxEntry {\n conversationId: string\n scope: { type: string; participants?: string[]; appId?: string; contentRef?: string; ticketNumber?: string }\n displayName: string\n muted: boolean\n joinedAt: string\n lastMessageAt: string | null\n lastMessagePreview: string | null\n lastMessageAuthor: string | null\n unreadCount: number\n}\n\nexport interface PlatformContextValue {\n /** Authenticated fetch — prepends /platform, sets Authorization + Content-Type */\n platformFetch: (path: string, init?: RequestInit) => Promise<Response>\n /** Subscribe to inbox — returns unsubscribe. Internal use by useInbox(). */\n subscribeInbox: () => () => void\n /** Current inbox entries (populated when at least one subscriber is active) */\n inbox: InboxEntry[]\n}\n\nexport const PlatformContext = createContext<PlatformContextValue | null>(null)\n\nexport function usePlatform(): PlatformContextValue {\n const ctx = useContext(PlatformContext)\n if (!ctx) throw new Error('usePlatform must be used within a PlatformProvider')\n return ctx\n}\n\n/**\n * Subscribe to inbox entries from the InboxRoom WebSocket.\n * The WebSocket connects when the first component calls useInbox()\n * and disconnects when the last one unmounts.\n */\nexport function useInbox(): InboxEntry[] {\n const { inbox, subscribeInbox } = usePlatform()\n useEffect(() => subscribeInbox(), [subscribeInbox])\n return inbox\n}\n\nexport function PlatformProvider({ children }: { children: React.ReactNode }) {\n const [inbox, setInbox] = useState<InboxEntry[]>([])\n\n // --- Subscription-activated inbox WebSocket ---\n const inboxSubscribers = useRef(0)\n const [inboxActive, setInboxActive] = useState(false)\n\n const subscribeInbox = useCallback(() => {\n inboxSubscribers.current++\n if (inboxSubscribers.current === 1) setInboxActive(true)\n return () => {\n inboxSubscribers.current--\n if (inboxSubscribers.current === 0) setInboxActive(false)\n }\n }, [])\n\n useEffect(() => {\n if (!inboxActive) return\n\n let mounted = true\n let ws: WebSocket | null = null\n let pingInterval: ReturnType<typeof setInterval>\n let retryTimer: ReturnType<typeof setTimeout>\n\n async function connect() {\n const token = await getAuthToken()\n if (!mounted) return\n if (!token) {\n // Auth not ready yet — retry\n retryTimer = setTimeout(connect, 2_000)\n return\n }\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n ws = new WebSocket(\n `${protocol}//${window.location.host}/platform/ws/inbox?token=${encodeURIComponent(token)}`,\n )\n\n ws.onmessage = (e) => {\n if (e.data === 'pong') return\n try {\n const msg = JSON.parse(e.data)\n switch (msg.type) {\n case 'inbox_init':\n setInbox(msg.entries)\n break\n case 'inbox_added':\n setInbox(prev => [...prev, msg.entry])\n break\n case 'inbox_removed':\n setInbox(prev => prev.filter(x => x.conversationId !== msg.conversationId))\n break\n case 'inbox_updated':\n setInbox(prev =>\n prev.map(x => (x.conversationId === msg.entry.conversationId ? msg.entry : x)),\n )\n break\n }\n } catch {\n // ignore\n }\n }\n\n ws.onclose = () => {\n if (mounted) {\n // Reconnect after brief delay\n retryTimer = setTimeout(connect, 3_000)\n }\n }\n\n pingInterval = setInterval(() => {\n if (ws?.readyState === WebSocket.OPEN) ws.send('ping')\n }, 30_000)\n }\n\n connect()\n\n return () => {\n mounted = false\n clearTimeout(retryTimer)\n clearInterval(pingInterval)\n ws?.close()\n setInbox([])\n }\n }, [inboxActive])\n\n // --- platformFetch — always available, zero overhead until called ---\n const platformFetch = useCallback(async (path: string, init?: RequestInit) => {\n const token = await getAuthToken()\n const headers = new Headers(init?.headers)\n if (token) headers.set('Authorization', `Bearer ${token}`)\n if (!headers.has('Content-Type') && init?.body) headers.set('Content-Type', 'application/json')\n return fetch(`/platform${path}`, { ...init, headers })\n }, [])\n\n return (\n <PlatformContext.Provider value={{ platformFetch, subscribeInbox, inbox }}>\n {children}\n </PlatformContext.Provider>\n )\n}\n","/**\n * usePlatformWS — Generic WebSocket hook for platform DO connections.\n *\n * Handles all the boilerplate:\n * - Auth token fetch\n * - WebSocket connection with wss:// protocol detection\n * - Exponential backoff reconnect (500ms -> 10s max)\n * - Ping every 30s\n * - Cleanup on unmount or scopeId change\n *\n * Usage:\n * const state = usePlatformWS({\n * path: 'orders', // -> /platform/ws/orders/{scopeId}\n * scopeId: 'app:demo-corp',\n * initialState: { orders: [], items: {}, status: 'connecting' },\n * onMessage: (msg, prev) => {\n * switch (msg.type) {\n * case 'init': return { orders: msg.orders, items: msg.items, status: 'connected' }\n * case 'order_created': return { ...prev, orders: [...prev.orders, msg.order] }\n * default: return prev\n * }\n * },\n * })\n */\n\nimport { useState, useEffect, useRef } from 'react'\nimport { getAuthToken } from '../auth/token'\nimport type { ConnectionStatus } from '../storage/connection-status'\n\nconst MAX_RECONNECT_DELAY = 10_000\nconst BASE_RECONNECT_DELAY = 500\n\nexport interface PlatformWSOptions<S> {\n /** DO path segment — e.g. 'orders' for /platform/ws/orders/{scopeId} */\n path: string\n /** Scope ID — e.g. 'app:demo-corp'. Passing undefined skips connection. */\n scopeId: string | undefined\n /** Initial state before WS connects */\n initialState: S\n /**\n * Message handler. Receives the parsed message and current state.\n * Return a new state to update, or the same `prev` reference to skip.\n * The 'init' message should reset reconnect (handled automatically)\n * and return state with status: 'connected'.\n */\n onMessage: (msg: Record<string, unknown>, prev: S) => S\n}\n\nexport interface PlatformWSResult<S> {\n state: S\n /** Send a JSON message to the WebSocket */\n send: (msg: Record<string, unknown>) => void\n}\n\nexport function usePlatformWS<S extends { status: ConnectionStatus }>(\n options: PlatformWSOptions<S>,\n): PlatformWSResult<S> {\n const { path, scopeId, initialState, onMessage } = options\n const wsRef = useRef<WebSocket | null>(null)\n const pingIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n const [state, setState] = useState<S>(initialState)\n const reconnectAttemptRef = useRef(0)\n const reconnectTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const mountedRef = useRef(true)\n\n // Keep onMessage ref stable to avoid reconnecting when handler identity changes\n const onMessageRef = useRef(onMessage)\n onMessageRef.current = onMessage\n\n const initialStateRef = useRef(initialState)\n initialStateRef.current = initialState\n\n useEffect(() => {\n mountedRef.current = true\n return () => { mountedRef.current = false }\n }, [])\n\n useEffect(() => {\n if (!scopeId) return\n\n setState(initialStateRef.current)\n reconnectAttemptRef.current = 0\n\n async function connect() {\n if (!mountedRef.current || !scopeId) return\n\n const token = await getAuthToken()\n if (!token || !mountedRef.current) {\n reconnectTimerRef.current = setTimeout(connect, 2_000)\n return\n }\n\n const params = new URLSearchParams()\n params.set('token', token)\n\n const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\n const ws = new WebSocket(\n `${protocol}//${window.location.host}/platform/ws/${path}/${scopeId}?${params}`,\n )\n wsRef.current = ws\n\n ws.onmessage = (e) => {\n if (e.data === 'pong') return\n try {\n const msg = JSON.parse(e.data)\n if (msg.type === 'init') {\n reconnectAttemptRef.current = 0\n }\n setState(prev => onMessageRef.current(msg, prev))\n } catch (err) {\n console.error(`[usePlatformWS:${path}] message parse error:`, err)\n }\n }\n\n ws.onclose = () => {\n if (!mountedRef.current) return\n const attempt = reconnectAttemptRef.current++\n const delay = Math.min(BASE_RECONNECT_DELAY * Math.pow(2, attempt), MAX_RECONNECT_DELAY)\n setState(prev => ({\n ...prev,\n status: (attempt === 0 ? 'connecting' : 'reconnecting') as ConnectionStatus,\n }))\n reconnectTimerRef.current = setTimeout(connect, delay)\n }\n\n if (pingIntervalRef.current) clearInterval(pingIntervalRef.current)\n pingIntervalRef.current = setInterval(() => {\n if (ws.readyState === WebSocket.OPEN) ws.send('ping')\n }, 30_000)\n }\n\n connect()\n\n return () => {\n if (reconnectTimerRef.current) {\n clearTimeout(reconnectTimerRef.current)\n reconnectTimerRef.current = null\n }\n if (pingIntervalRef.current) {\n clearInterval(pingIntervalRef.current)\n pingIntervalRef.current = null\n }\n wsRef.current?.close()\n wsRef.current = null\n }\n }, [scopeId, path])\n\n const send = useRef((msg: Record<string, unknown>) => {\n wsRef.current?.send(JSON.stringify(msg))\n }).current\n\n return { state, send }\n}\n","/**\n * Integration API client.\n *\n * Plain functions for calling third-party integrations (OpenAI, weather, etc.)\n * through the DeepSpace API worker. Works anywhere — React components,\n * event handlers, server actions, outside React entirely.\n *\n * Usage:\n * import { integration } from 'deepspace'\n * const result = await integration.post('openai/chat-completion', { messages })\n */\n\nimport { getAuthToken } from '../auth/token'\n\nconst ENDPOINT_PREFIX = '/api/integrations'\nconst DEFAULT_TIMEOUT_MS = 120_000\n\ninterface IntegrationResponse<T = unknown> {\n success: boolean\n data?: T\n error?: string\n issues?: Array<{ path?: string[]; message: string; code?: string }>\n}\n\ninterface RequestOptions {\n headers?: Record<string, string>\n timeoutMs?: number\n}\n\nfunction resolveUrl(endpoint: string): string {\n if (endpoint.startsWith('http://') || endpoint.startsWith('https://')) {\n return endpoint\n }\n const path = endpoint.startsWith('/') ? endpoint : endpoint ? `${ENDPOINT_PREFIX}/${endpoint}` : ENDPOINT_PREFIX\n if (typeof window !== 'undefined') {\n return `${window.location.origin}${path}`\n }\n return path\n}\n\nasync function request<T>(\n method: string,\n endpoint: string,\n body?: unknown,\n options?: RequestOptions,\n): Promise<IntegrationResponse<T>> {\n const url = resolveUrl(endpoint)\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options?.headers,\n }\n\n // Attach auth token if available\n try {\n const token = await getAuthToken()\n if (token) headers['Authorization'] = `Bearer ${token}`\n } catch {\n // Not signed in — continue without auth\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), timeoutMs)\n\n try {\n const res = await fetch(url, {\n method,\n headers,\n body: body != null ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n })\n\n let payload: Record<string, unknown>\n try {\n payload = (await res.json()) as Record<string, unknown>\n } catch {\n return { success: false, error: `Request failed (${res.status})` }\n }\n\n if (!res.ok || payload.success === false) {\n return {\n success: false,\n error: (payload.error as string) ?? (payload.message as string) ?? `Request failed (${res.status})`,\n ...(payload.issues ? { issues: payload.issues as IntegrationResponse['issues'] } : {}),\n }\n }\n\n // Normalize response — handle both { success, data } and { success, ...rest }\n if ('data' in payload) {\n return { success: true, data: payload.data as T }\n }\n const { success: _success, ...rest } = payload\n return { success: true, data: rest as T }\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') {\n return { success: false, error: `Request timed out after ${timeoutMs}ms` }\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : 'Request failed',\n }\n } finally {\n clearTimeout(timeout)\n }\n}\n\nexport const integration = {\n post<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('POST', endpoint, data, options)\n },\n get<T = unknown>(endpoint: string, params?: Record<string, string | number | boolean | null | undefined>, options?: RequestOptions) {\n let url = endpoint\n if (params) {\n const searchParams = new URLSearchParams()\n for (const [k, v] of Object.entries(params)) {\n if (v != null) searchParams.set(k, String(v))\n }\n const qs = searchParams.toString()\n if (qs) url = `${endpoint}?${qs}`\n }\n return request<T>('GET', url, undefined, options)\n },\n put<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('PUT', endpoint, data, options)\n },\n delete<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions) {\n return request<T>('DELETE', endpoint, data, options)\n },\n}\n\nexport type { IntegrationResponse, RequestOptions }\n","/**\n * Pure decoders for the Vercel AI SDK v5 `toUIMessageStreamResponse` body.\n *\n * The wire format is SSE: each event is `data: <json>\\n\\n`, terminated by\n * `data: [DONE]\\n\\n`. Each event carries a `type` discriminator\n * (`text-delta`, `tool-input-available`, `tool-output-available`,\n * `tool-input-error`, `tool-output-error`, `error`, `abort`, …) — see the\n * `UIMessageChunk` union in `ai/dist/index.d.ts`.\n *\n * This module decodes those chunks into a small action vocabulary that\n * the React layer then applies to its state. Keeping decode pure means\n * the v5-boundary behavior is fully testable without spinning up a\n * component tree.\n */\n\n/** Raw v5 stream chunk, as parsed off the wire. `type` may be any string. */\nexport type AiStreamChunk = Record<string, unknown> & { type?: unknown }\n\n/**\n * Strip one SSE line's framing. Returns the parsed JSON payload, or `null`\n * for blank lines, comment lines (`:` prefix), non-`data:` SSE fields, the\n * `[DONE]` terminator, or any line whose payload doesn't parse as JSON.\n *\n * Multi-line `data:` events (per the SSE spec, joined by `\\n` before\n * dispatch) are NOT supported — v5's emitter never produces them. If you\n * hit a wire intermediary that re-splits long payloads (e.g. a proxy that\n * caps line length), upgrade this to accumulate consecutive `data:` lines\n * until a blank line.\n */\nexport function parseSseLine(line: string): AiStreamChunk | null {\n if (!line) return null\n if (line.startsWith(':')) return null // SSE comment\n if (!line.startsWith('data:')) return null // we only consume `data:` events\n // SSE allows exactly one space after the colon to be elided. Trim a\n // trailing \\r so CRLF-framed responses still hit the [DONE] short-circuit.\n const raw = line.slice(5).replace(/^ /, '').replace(/\\r$/, '')\n if (raw === '[DONE]') return null\n try {\n const parsed: unknown = JSON.parse(raw)\n if (!parsed || typeof parsed !== 'object') return null\n return parsed as AiStreamChunk\n } catch {\n return null\n }\n}\n\n/**\n * Action vocabulary the React layer applies. Every `decodeAiStreamChunk`\n * output is one of these — `null` means the chunk is intentionally ignored\n * (lifecycle markers, reasoning we don't surface yet, etc.).\n *\n * Wire field renames (v5): chunks carry `input` / `output` directly. We\n * map them to `args` / `result` here so persisted UI shapes stay v4-stable.\n */\nexport type AiStreamAction =\n | { type: 'append-text'; delta: string }\n | { type: 'upsert-tool-call'; toolCallId: string; toolName: string; input: unknown }\n | { type: 'finalize-tool-call'; toolCallId: string; result: unknown }\n /**\n * Schema validation rejected the input before the tool ran; no preceding\n * `upsert-tool-call` was emitted, so the React layer must create the\n * invocation and finalize it as failed in one step.\n */\n | { type: 'fail-tool-input'; toolCallId: string; toolName: string; input: unknown; errorText: string }\n /** Tool execution failed; a previous `upsert-tool-call` exists to finalize. */\n | { type: 'fail-tool-output'; toolCallId: string; errorText: string }\n | { type: 'stream-error'; errorText: string }\n /** Server-side abort with no error chunk to follow. */\n | { type: 'abort' }\n\n/** Decode one v5 UIMessage stream chunk into an action, or `null` to ignore. */\nexport function decodeAiStreamChunk(chunk: AiStreamChunk): AiStreamAction | null {\n if (typeof chunk.type !== 'string') return null\n\n switch (chunk.type) {\n case 'text-delta': {\n const delta = typeof chunk.delta === 'string' ? chunk.delta : ''\n if (!delta) return null\n return { type: 'append-text', delta }\n }\n\n case 'tool-input-available': {\n if (typeof chunk.toolCallId !== 'string' || typeof chunk.toolName !== 'string') return null\n return {\n type: 'upsert-tool-call',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: chunk.input,\n }\n }\n\n case 'tool-output-available': {\n if (typeof chunk.toolCallId !== 'string') return null\n // The wire emits `output: part.output` directly (no `toJSONValue`\n // wrapping at this layer). When `part.output` is `undefined`,\n // `JSON.stringify` drops the key entirely, so `'output' in chunk`\n // reads false on the receiving side. Treat absence as an explicit\n // `null` result — finalizing the invocation is what stops the\n // spinner; ignoring the chunk would hang the UI forever for any\n // tool whose `execute` returns undefined.\n const result = 'output' in chunk ? chunk.output : null\n return { type: 'finalize-tool-call', toolCallId: chunk.toolCallId, result }\n }\n\n case 'tool-input-error': {\n if (typeof chunk.toolCallId !== 'string' || typeof chunk.toolName !== 'string') return null\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Tool input rejected'\n return {\n type: 'fail-tool-input',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: chunk.input,\n errorText,\n }\n }\n\n case 'tool-output-error': {\n if (typeof chunk.toolCallId !== 'string') return null\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Tool execution failed'\n return { type: 'fail-tool-output', toolCallId: chunk.toolCallId, errorText }\n }\n\n case 'error': {\n const errorText = typeof chunk.errorText === 'string' ? chunk.errorText : 'Stream error'\n return { type: 'stream-error', errorText }\n }\n\n case 'abort':\n return { type: 'abort' }\n\n // Forward-compat: silently ignore lifecycle markers (start/finish,\n // start-step/finish-step), text-start/-end, tool-input-start/-delta,\n // reasoning-*, source-*, message-metadata.\n default:\n return null\n }\n}\n","// Per-app subscription state hook. Reads through the starter's same-origin\n// /_deepspace proxy, which signs with the app identity token.\n\nimport { useCallback, useEffect, useState } from 'react'\nimport { getAuthToken } from '../auth/token'\nimport { isEntitled, type PlanInfo, type SubscriptionStatus } from '../../shared/subscription'\n\n// Re-export for SDK consumers — these are public types the hook is generic over.\nexport type { SubscriptionStatus, PlanInfo }\n\nexport interface SubscriptionState {\n tier: string\n status: SubscriptionStatus\n /** Billing interval of the active subscription, or null for free / no sub. */\n interval: 'month' | 'year' | null\n currentPeriodEnd: number | null\n cancelAtPeriodEnd: boolean\n trialEndsAt: number | null\n plans: PlanInfo[]\n}\n\nexport interface SubscribeOpts {\n interval?: 'month' | 'year'\n returnUrl?: string\n cancelUrl?: string\n}\n\nexport interface SubscribeResult {\n url: string | null\n immediate: boolean\n requiresPayment?: boolean\n hostedInvoiceUrl?: string | null\n}\n\ninterface UseSubscriptionReturn {\n tier: string\n status: SubscriptionStatus\n /**\n * True iff status is `active` or `trialing`. `hasTier` and `isAtLeast`\n * already encode this — read `entitled` only when you need the raw boolean\n * without picking a tier.\n */\n entitled: boolean\n /** Current billing interval, or null when on free / no subscription. */\n interval: 'month' | 'year' | null\n currentPeriodEnd: number | null\n cancelAtPeriodEnd: boolean\n trialEndsAt: number | null\n isLoading: boolean\n error: string | null\n /**\n * Returns true only when `tier === slug` AND the subscription is currently\n * entitled (status ∈ {active, trialing}). A `past_due` / `canceled` /\n * `unpaid` subscription that still has a stored paid tier returns false.\n * The free tier is always entitled.\n */\n hasTier: (slug: string) => boolean\n /**\n * Returns true when the tier's rank meets-or-exceeds `slug` AND the\n * subscription is currently entitled. Same entitlement gate as `hasTier`.\n */\n isAtLeast: (slug: string) => boolean\n /** Plan catalog from /me — pass into `<PricingTable plans={...}>` directly. */\n plans: PlanInfo[]\n subscribe: (planSlug: string, opts?: SubscribeOpts) => Promise<SubscribeResult>\n openPortal: (returnUrl?: string) => Promise<{ url: string }>\n refresh: () => Promise<void>\n}\n\nasync function authedJson<T>(path: string, init?: RequestInit): Promise<T> {\n const token = await getAuthToken()\n const res = await fetch(path, {\n ...init,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...init?.headers,\n },\n })\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>\n if (!res.ok) {\n throw new Error((data.error as string) ?? `Request failed (${res.status})`)\n }\n return data as T\n}\n\nexport function useSubscription(): UseSubscriptionReturn {\n const [state, setState] = useState<SubscriptionState>({\n tier: 'free',\n status: 'none',\n interval: null,\n currentPeriodEnd: null,\n cancelAtPeriodEnd: false,\n trialEndsAt: null,\n plans: [],\n })\n const [isLoading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n const refresh = useCallback(async () => {\n setLoading(true)\n try {\n const r = await authedJson<SubscriptionState>('/_deepspace/subscriptions/me')\n setState({\n tier: r.tier,\n status: r.status,\n interval: r.interval ?? null,\n currentPeriodEnd: r.currentPeriodEnd,\n cancelAtPeriodEnd: r.cancelAtPeriodEnd,\n trialEndsAt: r.trialEndsAt,\n plans: r.plans ?? [],\n })\n setError(null)\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to load subscription')\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n const entitled = isEntitled(state.tier, state.status)\n const hasTier = useCallback(\n (slug: string) => state.tier === slug && isEntitled(state.tier, state.status),\n [state.tier, state.status],\n )\n const isAtLeast = useCallback(\n (slug: string) => {\n if (!isEntitled(state.tier, state.status)) return false\n const targetRank = state.plans.find((p) => p.slug === slug)?.rank\n const currentRank = state.plans.find((p) => p.slug === state.tier)?.rank\n if (targetRank == null || currentRank == null) return false\n return currentRank >= targetRank\n },\n [state.plans, state.tier, state.status],\n )\n\n const subscribe = useCallback(\n async (planSlug: string, opts?: SubscribeOpts): Promise<SubscribeResult> => {\n const result = await authedJson<SubscribeResult>('/_deepspace/subscriptions/checkout', {\n method: 'POST',\n body: JSON.stringify({\n planSlug,\n interval: opts?.interval ?? 'month',\n returnUrl: opts?.returnUrl ?? window.location.href,\n cancelUrl: opts?.cancelUrl ?? window.location.href,\n requestNonce: crypto.randomUUID(),\n }),\n })\n if (result.immediate) await refresh()\n // Auto-redirect when the server tells us to navigate. `result.url` is\n // populated in every redirect-bound case: Stripe Checkout session URL\n // (new sub), returnUrl (immediate in-place tier/interval change), and\n // hostedInvoiceUrl (SCA-pending proration). Matches useCheckout's\n // chargeOnce behavior so docs that show `await sub.subscribe('pro')`\n // and expect a redirect actually work without extra plumbing.\n if (typeof window !== 'undefined' && result.url) {\n window.location.href = result.url\n }\n return result\n },\n [refresh],\n )\n\n const openPortal = useCallback(\n async (returnUrl?: string) => {\n return authedJson<{ url: string }>('/_deepspace/subscriptions/portal', {\n method: 'POST',\n body: JSON.stringify({ returnUrl: returnUrl ?? window.location.href }),\n })\n },\n [],\n )\n\n return {\n tier: state.tier,\n status: state.status,\n entitled,\n interval: state.interval,\n currentPeriodEnd: state.currentPeriodEnd,\n cancelAtPeriodEnd: state.cancelAtPeriodEnd,\n trialEndsAt: state.trialEndsAt,\n isLoading,\n error,\n hasTier,\n isAtLeast,\n plans: state.plans,\n subscribe,\n openPortal,\n refresh,\n }\n}\n","/**\n * Subscription primitives shared between client (useSubscription hook) and\n * server (requireSubscription helper). Pulled into a shared module so the\n * entitlement gate has a single source of truth — if it ever diverges between\n * client and server, gated features silently disagree about who's allowed in,\n * which is a security bug, not a UX bug.\n */\n\nexport type SubscriptionStatus =\n | 'none'\n | 'trialing'\n | 'active'\n | 'past_due'\n | 'canceled'\n | 'incomplete'\n | 'incomplete_expired'\n | 'unpaid'\n | 'paused'\n\n/** Per-interval price advertised by a plan. */\nexport interface PlanPrice {\n interval: 'month' | 'year'\n priceCents: number\n currency?: string\n}\n\n/**\n * Plan shape returned by `/api/subscriptions/me` and consumed directly by\n * `<PricingTable plans={sub.plans}>`. Fields beyond slug/rank are optional so\n * a free tier (no prices, no trial) doesn't need to fabricate them.\n */\nexport interface PlanInfo {\n slug: string\n rank: number\n name: string\n trialDays?: number | null\n prices: PlanPrice[]\n}\n\n// Statuses that grant access to paid features. Other statuses (past_due,\n// unpaid, incomplete, paused, canceled) keep the user's recorded planSlug so\n// the UI can surface \"your Pro plan is past-due\" — but they MUST NOT unlock.\n//\n// Typed as `ReadonlySet<string>` (not `Set<SubscriptionStatus>`) so callers\n// passing a server-supplied string don't need a runtime cast; unknown statuses\n// fall through as \"not entitled\", which is the safe default.\nexport const ENTITLED_STATUSES: ReadonlySet<string> = new Set([\n 'active',\n 'trialing',\n])\n\n/**\n * True iff the subscription currently grants access to paid features.\n *\n * - Free tier always counts as entitled — no payment required.\n * - Otherwise the status must be in `ENTITLED_STATUSES`.\n *\n * `status` is typed as `string` deliberately: server responses can carry\n * statuses we haven't enumerated yet (e.g. if Stripe adds a new one), and\n * those should fall through as not-entitled rather than crashing the check.\n */\nexport function isEntitled(tier: string, status: string): boolean {\n if (tier === 'free') return true\n return ENTITLED_STATUSES.has(status)\n}\n","// Minimal pre-fab pricing UI. Stateless: pass in `plans` from\n// `useSubscription().plans` and an `onSelect` callback that calls\n// `useSubscription().subscribe()`. Apps that want their own design can ignore\n// this and roll their own; this is just the \"works out of the box\" path for\n// starter apps.\n\nimport type { PlanInfo, PlanPrice } from '../../shared/subscription'\n\n// Re-export shared types so callers can do\n// `import { PricingTablePlan } from 'deepspace'` without reaching into shared.\nexport type PricingTablePrice = PlanPrice\nexport type PricingTablePlan = PlanInfo\n\nexport function PricingTable(props: {\n plans: PricingTablePlan[]\n interval?: 'month' | 'year'\n currentTier?: string\n onSelect: (planSlug: string, interval: 'month' | 'year') => void | Promise<void>\n}) {\n const interval = props.interval ?? 'month'\n return (\n <div className=\"grid gap-4 md:grid-cols-3\">\n {props.plans.map((plan) => {\n const price = plan.prices.find((p) => p.interval === interval)\n const selected = props.currentTier === plan.slug\n // A plan is truly free only if it has no priced interval at all.\n // If `price` is missing but the plan has prices on OTHER intervals,\n // this interval is unavailable — clicking checkout would fail with\n // `unknown_price`, so we render \"Unavailable\" and disable the button\n // instead of mislabeling it as free.\n const isTrueFree = plan.prices.length === 0\n const otherIntervals = plan.prices\n .map((p) => p.interval)\n .filter((i) => i !== interval)\n const intervalUnavailable = !price && !isTrueFree\n const onlyInterval = otherIntervals.length === 1 ? otherIntervals[0] : null\n const unavailableLabel = onlyInterval\n ? onlyInterval === 'month'\n ? 'Monthly only'\n : 'Yearly only'\n : 'Unavailable'\n const priceLabel = price\n ? `$${(price.priceCents / 100).toFixed(0)}`\n : isTrueFree\n ? 'Free'\n : unavailableLabel\n const disabled = selected || intervalUnavailable\n return (\n <section key={plan.slug} className=\"rounded-lg border border-border p-5\">\n <div className=\"space-y-1\">\n <h3 className=\"text-lg font-semibold\">{plan.name}</h3>\n <p className=\"text-3xl font-semibold\">\n {priceLabel}\n <span className=\"text-sm font-normal text-muted-foreground\">\n {price ? `/${interval}` : ''}\n </span>\n </p>\n {plan.trialDays ? (\n <p className=\"text-xs text-muted-foreground\">{plan.trialDays}-day free trial</p>\n ) : null}\n </div>\n <button\n type=\"button\"\n disabled={disabled}\n onClick={() => void props.onSelect(plan.slug, interval)}\n className=\"mt-5 w-full rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {selected\n ? 'Current plan'\n : intervalUnavailable\n ? unavailableLabel\n : 'Select plan'}\n </button>\n </section>\n )\n })}\n </div>\n )\n}\n","// One-time charge hook. Two modes:\n//\n// 1. Server-declared product (`chargeOnce({ productId })`): the platform\n// resolves amount/name from your declared product catalog. The browser\n// can't pick `productId` + `amount` together — only the declared\n// amount is charged. This is the only entitlement-safe mode:\n// `useCheckout({productId}).owned` answers truthfully.\n//\n// 2. Ad-hoc (`chargeOnce({ amount, name })`): tips, donations, dynamic\n// amounts. The resulting invoice has no `productId` so `ownsProduct()`\n// cannot satisfy gating against it. Use for collection, not unlock.\n//\n// To declare products, POST to `/api/charges/products/sync` from a deploy\n// step or admin tool with `{appName, products: [{productId, name,\n// amountCents}]}`. Products dropped from a later sync are deactivated.\n//\n// The hook fetches the customer's purchase history on mount, caches it in\n// state, and exposes `owned` + `ownsProduct(id)` for gating features behind\n// a one-time purchase the same way `useSubscription().tier` gates behind a\n// recurring plan.\n\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { getAuthToken } from '../auth/token'\n\ninterface ChargeRedirectOpts {\n /** Defaults to window.location.href. */\n returnUrl?: string\n /** Defaults to window.location.href. */\n cancelUrl?: string\n}\n\n/**\n * Product-mode charge: amount, name, and currency are resolved server-side\n * from the developer's declared product catalog (`src/products.ts`). The\n * browser cannot influence the price — this is the only entitlement-safe\n * shape because `useCheckout({productId}).owned` can be trusted afterwards.\n */\nexport interface ProductChargeOpts extends ChargeRedirectOpts {\n productId: string\n}\n\n/**\n * Ad-hoc charge: tips, donations, \"name your price\". Caller supplies the\n * amount and display name; the resulting invoice has `productId=null`, so\n * `ownsProduct()` will never report ownership against it. Use for revenue\n * collection, not for feature gating.\n */\nexport interface AdHocChargeOpts extends ChargeRedirectOpts {\n /** Amount in cents. Minimum 100 (Stripe fees eat smaller amounts). */\n amount: number\n /** Product name shown in Checkout and on the customer's receipt. */\n name: string\n /** Optional description rendered under the product name. */\n description?: string\n /** Must be omitted in ad-hoc mode — the never type makes the union disjoint. */\n productId?: never\n}\n\n/**\n * `chargeOnce` accepts either a `productId` (server-resolves price/name) or\n * an `amount`+`name` pair (ad-hoc). The two are mutually exclusive at the\n * type level so the safe path doesn't require dummy amount/name fields.\n */\nexport type ChargeOnceOpts = ProductChargeOpts | AdHocChargeOpts\n\nexport interface ChargeOnceResult {\n url: string\n}\n\nexport interface Purchase {\n /** Internal invoice row id. Stable across refetches. */\n id: string\n /** Developer-supplied product id, or null for pre-entitlement rows. */\n productId: string | null\n /** Display name captured at checkout time. */\n name: string\n /** Amount paid in cents (post-tax — uses Stripe's `amount_total`). */\n amount: number\n currency: string\n /** ISO timestamp of the payment. */\n paidAt: string\n}\n\nexport interface UseCheckoutOpts {\n /**\n * Product id to derive `owned` against. Without this, `owned` is always\n * false — the hook still surfaces `purchases` and `ownsProduct` for\n * callers that need to ask about more than one product.\n */\n productId?: string\n}\n\ninterface UseCheckoutReturn {\n // Action surface\n chargeOnce: (opts: ChargeOnceOpts) => Promise<ChargeOnceResult>\n isLoading: boolean\n error: string | null\n\n // Read surface\n purchases: Purchase[]\n /** True iff `opts.productId` was provided and a non-fully-refunded row matches. */\n owned: boolean\n /** Pure function over the in-memory `purchases` array. No network. */\n ownsProduct: (productId: string) => boolean\n /** Re-fetch the purchase list. Useful right after a successful checkout. */\n refresh: () => Promise<void>\n}\n\nasync function authedJson<T>(path: string, init?: RequestInit): Promise<T> {\n const token = await getAuthToken()\n const res = await fetch(path, {\n ...init,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...init?.headers,\n },\n })\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>\n if (!res.ok) {\n throw new Error((data.error as string) ?? `Request failed (${res.status})`)\n }\n return data as T\n}\n\nexport function useCheckout(opts?: UseCheckoutOpts): UseCheckoutReturn {\n const [purchases, setPurchases] = useState<Purchase[]>([])\n const [isLoading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n\n // No productId param on the fetch — the hook caches the full list and the\n // per-product question is answered in-memory. Cheaper than refetching on\n // every productId change and lets one component check ownership of N\n // products without N requests.\n const refresh = useCallback(async () => {\n setLoading(true)\n try {\n const r = await authedJson<{ purchases: Purchase[] }>(\n '/_deepspace/charges/me',\n )\n setPurchases(r.purchases ?? [])\n setError(null)\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to load purchases')\n } finally {\n setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n refresh()\n }, [refresh])\n\n const chargeOnce = useCallback(\n async (chargeOpts: ChargeOnceOpts): Promise<ChargeOnceResult> => {\n // Note: isLoading intentionally not toggled here — it tracks the\n // fetch lifecycle (initial + refresh), not the chargeOnce redirect.\n // Mirrors the v1 semantics callers already depend on.\n setError(null)\n\n // Build the request body by mode. In product mode we deliberately\n // omit amount/name from the wire — the server resolves them from the\n // declared catalog and would ignore client values anyway, but sending\n // them keeps the dangerous \"browser picks the price\" shape on the\n // wire. In ad-hoc mode we send what the caller supplied.\n const common = {\n returnUrl: chargeOpts.returnUrl ?? window.location.href,\n cancelUrl: chargeOpts.cancelUrl ?? window.location.href,\n requestNonce: crypto.randomUUID(),\n }\n const body =\n chargeOpts.productId !== undefined\n ? { ...common, productId: chargeOpts.productId }\n : {\n ...common,\n amount: chargeOpts.amount,\n name: chargeOpts.name,\n ...(chargeOpts.description ? { description: chargeOpts.description } : {}),\n }\n\n try {\n const result = await authedJson<{ url: string }>(\n '/_deepspace/charges/create',\n {\n method: 'POST',\n body: JSON.stringify(body),\n },\n )\n if (typeof window !== 'undefined' && result.url) {\n window.location.href = result.url\n }\n return result\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Failed to start checkout'\n setError(msg)\n throw e\n }\n },\n [],\n )\n\n const ownsProduct = useCallback(\n (productId: string) => purchases.some((p) => p.productId === productId),\n [purchases],\n )\n\n // `owned` is the convenience binding for the single-product case. Vacuously\n // false when no productId was passed to the hook — the caller didn't ask a\n // question, so the answer is \"no entitlement\".\n const owned = useMemo(\n () => !!opts?.productId && purchases.some((p) => p.productId === opts.productId),\n [opts?.productId, purchases],\n )\n\n return {\n chargeOnce,\n isLoading,\n error,\n purchases,\n owned,\n ownsProduct,\n refresh,\n }\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'relative rounded-2xl border border-border bg-card text-card-foreground shadow-card',\n className\n )}\n {...props}\n />\n))\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1.5 p-4 sm:p-6', className)}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-4 pt-0 sm:p-6 sm:pt-0', className)} {...props} />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-4 pt-0 sm:p-6 sm:pt-0', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n","import * as React from 'react'\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\n\nimport { cn } from './utils'\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = 'horizontal', decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'shrink-0 bg-border',\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement>\n>(({ className, ...props }, ref) => (\n <div className=\"relative w-full overflow-auto\">\n <table\n ref={ref}\n className={cn('w-full caption-bottom text-sm', className)}\n {...props}\n />\n </div>\n))\nTable.displayName = 'Table'\n\nconst TableHeader = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />\n))\nTableHeader.displayName = 'TableHeader'\n\nconst TableBody = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tbody\n ref={ref}\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n))\nTableBody.displayName = 'TableBody'\n\nconst TableFooter = React.forwardRef<\n HTMLTableSectionElement,\n React.HTMLAttributes<HTMLTableSectionElement>\n>(({ className, ...props }, ref) => (\n <tfoot\n ref={ref}\n className={cn(\n 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',\n className\n )}\n {...props}\n />\n))\nTableFooter.displayName = 'TableFooter'\n\nconst TableRow = React.forwardRef<\n HTMLTableRowElement,\n React.HTMLAttributes<HTMLTableRowElement>\n>(({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\n 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',\n className\n )}\n {...props}\n />\n))\nTableRow.displayName = 'TableRow'\n\nconst TableHead = React.forwardRef<\n HTMLTableCellElement,\n React.ThHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n 'h-10 px-2 sm:px-3 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n className\n )}\n {...props}\n />\n))\nTableHead.displayName = 'TableHead'\n\nconst TableCell = React.forwardRef<\n HTMLTableCellElement,\n React.TdHTMLAttributes<HTMLTableCellElement>\n>(({ className, ...props }, ref) => (\n <td\n ref={ref}\n className={cn(\n 'p-2 sm:p-3 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\n className\n )}\n {...props}\n />\n))\nTableCell.displayName = 'TableCell'\n\nconst TableCaption = React.forwardRef<\n HTMLTableCaptionElement,\n React.HTMLAttributes<HTMLTableCaptionElement>\n>(({ className, ...props }, ref) => (\n <caption\n ref={ref}\n className={cn('mt-4 text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nTableCaption.displayName = 'TableCaption'\n\nexport {\n Table,\n TableHeader,\n TableBody,\n TableFooter,\n TableHead,\n TableRow,\n TableCell,\n TableCaption,\n}\n","import * as React from 'react'\nimport * as TabsPrimitive from '@radix-ui/react-tabs'\n\nimport { cn } from './utils'\n\nconst Tabs = TabsPrimitive.Root\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.List\n ref={ref}\n className={cn(\n 'inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground overflow-x-auto max-w-full',\n className\n )}\n {...props}\n />\n))\nTabsList.displayName = TabsPrimitive.List.displayName\n\nconst TabsTrigger = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Trigger\n ref={ref}\n className={cn(\n 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow',\n className\n )}\n {...props}\n />\n))\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName\n\nconst TabsContent = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n className={cn(\n 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n))\nTabsContent.displayName = TabsPrimitive.Content.displayName\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent }\n","import * as React from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default:\n 'bg-primary text-primary-foreground shadow hover:bg-primary/90',\n destructive:\n 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',\n outline:\n 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',\n secondary:\n 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3 text-xs',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean\n loading?: boolean\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, loading = false, disabled, children, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={disabled || loading}\n {...props}\n >\n {loading && (\n <span className=\"w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin\" />\n )}\n {children}\n </Comp>\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n 'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n }\n)\nInput.displayName = 'Input'\n\nexport { Input }\n","import * as React from 'react'\n\nimport { cn } from './utils'\n\nconst Textarea = React.forwardRef<\n HTMLTextAreaElement,\n React.ComponentProps<'textarea'>\n>(({ className, ...props }, ref) => {\n return (\n <textarea\n className={cn(\n 'flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',\n className\n )}\n ref={ref}\n {...props}\n />\n )\n})\nTextarea.displayName = 'Textarea'\n\nexport { Textarea }\n","import * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"h-4 w-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronUp className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn(\n 'flex cursor-default items-center justify-center py-1',\n className\n )}\n {...props}\n >\n <ChevronDown className=\"h-4 w-4\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n className={cn(\n 'relative z-50 max-h-96 min-w-[8rem] max-w-[calc(100vw-2rem)] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className\n )}\n position={position}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-sm font-semibold', className)}\n {...props}\n />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center rounded-sm py-2 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n}\n","import * as React from 'react'\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox'\nimport { Check } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n 'grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn('grid place-content-center text-current')}\n >\n <Check className=\"h-4 w-4\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n","import * as React from 'react'\nimport * as SwitchPrimitives from '@radix-ui/react-switch'\n\nimport { cn } from './utils'\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n 'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',\n className\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n 'pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'\n )}\n />\n </SwitchPrimitives.Root>\n))\nSwitch.displayName = SwitchPrimitives.Root.displayName\n\nexport { Switch }\n","import * as React from 'react'\nimport * as LabelPrimitive from '@radix-ui/react-label'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst labelVariants = cva(\n 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'\n)\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst badgeVariants = cva(\n 'inline-flex items-center rounded-full border font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',\n {\n variants: {\n variant: {\n default:\n 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',\n secondary:\n 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',\n destructive:\n 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',\n outline: 'text-foreground',\n success:\n 'border-transparent bg-success text-success-foreground shadow hover:bg-success/80',\n warning:\n 'border-transparent bg-warning text-warning-foreground shadow hover:bg-warning/80',\n info:\n 'border-transparent bg-info text-info-foreground shadow hover:bg-info/80',\n },\n size: {\n default: 'px-2.5 py-0.5 text-xs',\n sm: 'px-2 py-px text-[10px]',\n lg: 'px-3 py-1 text-sm',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n }\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, size, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant, size }), className)} {...props} />\n )\n}\n\nexport { Badge, badgeVariants }\n","import * as React from 'react'\nimport * as AvatarPrimitive from '@radix-ui/react-avatar'\n\nimport { cn } from './utils'\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(\n 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',\n className\n )}\n {...props}\n />\n))\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn('aspect-square h-full w-full', className)}\n {...props}\n />\n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n 'flex h-full w-full items-center justify-center rounded-full bg-muted',\n className\n )}\n {...props}\n />\n))\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","import * as React from 'react'\nimport * as ProgressPrimitive from '@radix-ui/react-progress'\n\nimport { cn } from './utils'\n\nconst Progress = React.forwardRef<\n React.ElementRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-primary/20',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 bg-primary transition-all\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n))\nProgress.displayName = ProgressPrimitive.Root.displayName\n\nexport { Progress }\n","import React, { type ReactNode, type JSX } from 'react'\n\nimport { cn } from './utils'\n\n// ============================================================================\n// Skeleton - Base skeleton component (shadcn-compatible)\n// ============================================================================\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-primary/10', className)}\n {...props}\n />\n )\n}\n\n// ============================================================================\n// SkeletonText - Text line skeleton\n// ============================================================================\n\ninterface SkeletonTextProps {\n lines?: number\n lastLineWidth?: string\n className?: string\n}\n\nfunction SkeletonText({\n lines = 3,\n lastLineWidth = '60%',\n className = '',\n}: SkeletonTextProps): JSX.Element {\n return (\n <div className={cn('space-y-2', className)}>\n {Array.from({ length: lines }).map((_, i) => (\n <Skeleton\n key={i}\n className=\"h-4\"\n style={{ width: i === lines - 1 ? lastLineWidth : '100%' }}\n />\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonCard - Card skeleton\n// ============================================================================\n\ninterface SkeletonCardProps {\n hasImage?: boolean\n className?: string\n}\n\nfunction SkeletonCard({ hasImage = false, className = '' }: SkeletonCardProps): JSX.Element {\n return (\n <div className={cn('border border-border rounded-lg overflow-hidden', className)}>\n {hasImage && <Skeleton className=\"w-full h-32 rounded-none\" />}\n <div className=\"p-4 space-y-3\">\n <Skeleton className=\"h-5 w-3/4\" />\n <SkeletonText lines={2} />\n <Skeleton className=\"h-3 w-1/3\" />\n </div>\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonList - List skeleton\n// ============================================================================\n\ninterface SkeletonListProps {\n items?: number\n className?: string\n}\n\nfunction SkeletonList({ items = 5, className = '' }: SkeletonListProps): JSX.Element {\n return (\n <div className={cn('space-y-3', className)}>\n {Array.from({ length: items }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 p-3 border border-border rounded-lg\">\n <Skeleton className=\"w-10 h-10 rounded-full\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-4 w-1/3\" />\n <Skeleton className=\"h-3 w-1/2\" />\n </div>\n <Skeleton className=\"w-16 h-6\" />\n </div>\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonTable - Table skeleton\n// ============================================================================\n\ninterface SkeletonTableProps {\n rows?: number\n columns?: number\n className?: string\n}\n\nfunction SkeletonTable({\n rows = 5,\n columns = 4,\n className = '',\n}: SkeletonTableProps): JSX.Element {\n return (\n <div className={cn('border border-border rounded-lg overflow-hidden', className)}>\n {/* Header */}\n <div className=\"flex gap-4 p-4 bg-muted/50 border-b border-border\">\n {Array.from({ length: columns }).map((_, i) => (\n <Skeleton key={i} className=\"h-4 flex-1\" />\n ))}\n </div>\n {/* Rows */}\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <div key={rowIndex} className=\"flex gap-4 p-4 border-b border-border last:border-0\">\n {Array.from({ length: columns }).map((_, colIndex) => (\n <Skeleton\n key={colIndex}\n className=\"h-4 flex-1\"\n style={{ width: colIndex === 0 ? '40%' : undefined }}\n />\n ))}\n </div>\n ))}\n </div>\n )\n}\n\n// ============================================================================\n// SkeletonAvatar - Avatar skeleton\n// ============================================================================\n\ninterface SkeletonAvatarProps {\n size?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction SkeletonAvatar({ size = 'md', className = '' }: SkeletonAvatarProps): JSX.Element {\n const sizes = {\n sm: 'w-8 h-8',\n md: 'w-10 h-10',\n lg: 'w-12 h-12',\n }\n\n return <Skeleton className={cn(sizes[size], 'rounded-full', className)} />\n}\n\n// ============================================================================\n// LoadingSpinner - Simple spinner\n// ============================================================================\n\ninterface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction LoadingSpinner({ size = 'md', className = '' }: LoadingSpinnerProps): JSX.Element {\n const sizes = {\n sm: 'w-4 h-4',\n md: 'w-6 h-6',\n lg: 'w-8 h-8',\n }\n\n return (\n <div\n className={cn(sizes[size], 'border-2 border-muted border-t-primary rounded-full animate-spin', className)}\n />\n )\n}\n\n// ============================================================================\n// LoadingOverlay - Full-page or container loading\n// ============================================================================\n\ninterface LoadingOverlayProps {\n children?: ReactNode\n message?: string\n className?: string\n}\n\nfunction LoadingOverlay({\n children,\n message,\n className = '',\n}: LoadingOverlayProps): JSX.Element {\n return (\n <div className={cn('flex flex-col items-center justify-center py-16', className)}>\n <LoadingSpinner size=\"lg\" />\n {message && <p className=\"mt-4 text-muted-foreground\">{message}</p>}\n {children}\n </div>\n )\n}\n\nexport {\n Skeleton,\n SkeletonText,\n SkeletonCard,\n SkeletonList,\n SkeletonTable,\n SkeletonAvatar,\n LoadingSpinner,\n LoadingOverlay,\n}\n","import React, { ReactNode, JSX } from 'react'\nimport { MoreHorizontal, Trash2 } from 'lucide-react'\nimport { cn } from './utils'\n\n// ============================================================================\n// CardGrid - Responsive grid container\n// ============================================================================\n\ninterface CardGridProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n columns?: 1 | 2 | 3 | 4\n}\n\nexport function CardGrid({ children, columns = 3, className = '', ...rest }: CardGridProps): JSX.Element {\n const gridCols = {\n 1: 'grid-cols-1',\n 2: 'grid-cols-1 sm:grid-cols-2',\n 3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',\n 4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',\n }\n\n return (\n <div className={cn('grid gap-3 sm:gap-4', gridCols[columns], className)} {...rest}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard - Base card component (named GridCard to avoid conflict with shadcn Card)\n// ============================================================================\n\ninterface GridCardProps extends React.HTMLAttributes<HTMLDivElement> {\n children: ReactNode\n onClick?: () => void\n hoverable?: boolean\n}\n\nexport function GridCard({ children, onClick, className = '', hoverable = true, ...rest }: GridCardProps): JSX.Element {\n return (\n <div\n onClick={onClick}\n className={cn(\n 'group relative bg-card rounded-xl border border-border overflow-hidden transition-all duration-200',\n hoverable && 'hover:border-border hover:shadow-card-hover hover:-translate-y-0.5',\n onClick && 'cursor-pointer',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Image - Optional image header\n// ============================================================================\n\ninterface GridCardImageProps {\n src: string\n alt?: string\n height?: 'sm' | 'md' | 'lg'\n className?: string\n}\n\nfunction GridCardImage({ src, alt = '', height = 'md', className = '' }: GridCardImageProps): JSX.Element {\n const heights = {\n sm: 'h-24',\n md: 'h-36',\n lg: 'h-48',\n }\n\n return (\n <div className={cn(heights[height], 'overflow-hidden bg-muted', className)}>\n <img\n src={src}\n alt={alt}\n referrerPolicy=\"no-referrer\"\n className=\"w-full h-full object-cover transition-transform duration-300 group-hover:scale-105\"\n />\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Header - Title area with optional actions\n// ============================================================================\n\ninterface GridCardHeaderProps {\n children: ReactNode\n actions?: ReactNode\n className?: string\n}\n\nfunction GridCardHeader({ children, actions, className = '' }: GridCardHeaderProps): JSX.Element {\n return (\n <div className={cn('flex items-start justify-between gap-2 p-4 pb-2', className)}>\n <div className=\"flex-1 min-w-0\">{children}</div>\n {actions && (\n <div className=\"sm:opacity-0 sm:group-hover:opacity-100 transition-opacity shrink-0\">\n {actions}\n </div>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Title\n// ============================================================================\n\ninterface GridCardTitleProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardTitle({ children, className = '' }: GridCardTitleProps): JSX.Element {\n return (\n <h3 className={cn('font-semibold text-foreground truncate', className)}>\n {children}\n </h3>\n )\n}\n\n// ============================================================================\n// GridCard.Content - Main content area\n// ============================================================================\n\ninterface GridCardContentProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardContent({ children, className = '' }: GridCardContentProps): JSX.Element {\n return (\n <div className={cn('px-4 pb-4', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Description - Muted text with line clamp\n// ============================================================================\n\ninterface GridCardDescriptionProps {\n children: ReactNode\n lines?: 1 | 2 | 3 | 4\n className?: string\n}\n\nfunction GridCardDescription({ children, lines = 2, className = '' }: GridCardDescriptionProps): JSX.Element {\n const lineClamp = {\n 1: 'line-clamp-1',\n 2: 'line-clamp-2',\n 3: 'line-clamp-3',\n 4: 'line-clamp-4',\n }\n\n return (\n <p className={cn('text-sm text-muted-foreground leading-relaxed', lineClamp[lines], className)}>\n {children}\n </p>\n )\n}\n\n// ============================================================================\n// GridCard.Footer - Bottom area for meta info\n// ============================================================================\n\ninterface GridCardFooterProps {\n children: ReactNode\n className?: string\n}\n\nfunction GridCardFooter({ children, className = '' }: GridCardFooterProps): JSX.Element {\n return (\n <div className={cn('px-4 pb-4 pt-2 text-xs text-muted-foreground', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// GridCard.Badge - Status badge\n// ============================================================================\n\ninterface GridCardBadgeProps {\n children: ReactNode\n variant?: 'default' | 'success' | 'warning' | 'danger'\n className?: string\n}\n\nfunction GridCardBadge({ children, variant = 'default', className = '' }: GridCardBadgeProps): JSX.Element {\n const variants = {\n default: 'bg-muted text-muted-foreground border-border',\n success: 'bg-success/20 text-success border-success/40',\n warning: 'bg-warning/20 text-warning border-warning/40',\n danger: 'bg-destructive/20 text-destructive border-destructive/40',\n }\n\n return (\n <span className={cn('inline-flex px-2 py-0.5 text-xs font-medium rounded border', variants[variant], className)}>\n {children}\n </span>\n )\n}\n\n// ============================================================================\n// GridCard.Actions - Common action buttons\n// ============================================================================\n\ninterface GridCardActionsProps {\n onDelete?: () => void\n onMore?: () => void\n}\n\nfunction GridCardActions({ onDelete, onMore }: GridCardActionsProps): JSX.Element {\n const handleClick = (e: React.MouseEvent, handler?: () => void): void => {\n e.stopPropagation()\n handler?.()\n }\n\n return (\n <div className=\"flex items-center gap-1\">\n {onMore && (\n <button\n onClick={(e) => handleClick(e, onMore)}\n className=\"p-2 rounded-lg bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n >\n <MoreHorizontal className=\"w-4 h-4\" />\n </button>\n )}\n {onDelete && (\n <button\n onClick={(e) => handleClick(e, onDelete)}\n className=\"p-2 rounded-lg bg-muted/50 hover:bg-destructive/20 text-muted-foreground hover:text-destructive transition-colors\"\n >\n <Trash2 className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// Attach sub-components\n// ============================================================================\n\nGridCard.Image = GridCardImage\nGridCard.Header = GridCardHeader\nGridCard.Title = GridCardTitle\nGridCard.Content = GridCardContent\nGridCard.Description = GridCardDescription\nGridCard.Footer = GridCardFooter\nGridCard.Badge = GridCardBadge\nGridCard.Actions = GridCardActions\n\nexport default GridCard\n","import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from './utils'\n\nconst alertVariants = cva(\n 'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',\n {\n variants: {\n variant: {\n default: 'bg-background text-foreground',\n destructive:\n 'border-destructive/50 text-destructive [&>svg]:text-destructive',\n success:\n 'border-success/50 text-success [&>svg]:text-success',\n warning:\n 'border-warning/50 text-warning [&>svg]:text-warning',\n info:\n 'border-info/50 text-info [&>svg]:text-info',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n)\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n))\nAlert.displayName = 'Alert'\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn('mb-1 font-medium leading-none tracking-tight', className)}\n {...props}\n />\n))\nAlertTitle.displayName = 'AlertTitle'\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('text-sm [&_p]:leading-relaxed', className)}\n {...props}\n />\n))\nAlertDescription.displayName = 'AlertDescription'\n\nexport { Alert, AlertTitle, AlertDescription }\n","/**\n * Toast Notification System\n *\n * Self-contained toast provider with success/error/warning/info variants.\n * Uses the theme's semantic color tokens (success, warning, info, destructive).\n *\n * @example\n * // Wrap your app once:\n * <ToastProvider position=\"bottom-right\">\n * <App />\n * </ToastProvider>\n *\n * // In any child component:\n * const { success, error, warning, info } = useToast()\n * success('Saved!', 'Your changes have been saved.')\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode,\n} from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype ToastType = 'success' | 'error' | 'warning' | 'info'\n\ninterface Toast {\n id: string\n type: ToastType\n title: string\n description?: string\n duration?: number\n}\n\ninterface ToastContextValue {\n toasts: Toast[]\n toast: (options: Omit<Toast, 'id'>) => void\n success: (title: string, description?: string) => void\n error: (title: string, description?: string) => void\n warning: (title: string, description?: string) => void\n info: (title: string, description?: string) => void\n dismiss: (id: string) => void\n dismissAll: () => void\n}\n\n// ============================================================================\n// Icons (inline SVGs — no external dependency)\n// ============================================================================\n\nfunction CheckCircleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\" />\n <polyline points=\"22 4 12 14.01 9 11.01\" />\n </svg>\n )\n}\n\nfunction AlertCircleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n )\n}\n\nfunction AlertTriangleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" />\n <line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"13\" />\n <line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\" />\n </svg>\n )\n}\n\nfunction InfoIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"16\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"8\" x2=\"12.01\" y2=\"8\" />\n </svg>\n )\n}\n\nfunction CloseIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n )\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\nconst ToastContext = createContext<ToastContextValue | null>(null)\n\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext)\n if (!ctx) throw new Error('useToast must be used within ToastProvider')\n return ctx\n}\n\n// ============================================================================\n// ToastProvider\n// ============================================================================\n\ninterface ToastProviderProps {\n children: ReactNode\n position?:\n | 'top-right'\n | 'top-left'\n | 'bottom-right'\n | 'bottom-left'\n | 'top-center'\n | 'bottom-center'\n maxToasts?: number\n}\n\nexport function ToastProvider({\n children,\n position = 'bottom-right',\n maxToasts = 5,\n}: ToastProviderProps): React.ReactElement {\n const [toasts, setToasts] = useState<Toast[]>([])\n\n const dismiss = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id))\n }, [])\n\n const dismissAll = useCallback(() => {\n setToasts([])\n }, [])\n\n const addToast = useCallback(\n (options: Omit<Toast, 'id'>) => {\n const id = Math.random().toString(36).slice(2)\n const duration = options.duration ?? 5000\n\n setToasts((prev) => {\n const next = [...prev, { ...options, id }]\n return next.slice(-maxToasts)\n })\n\n if (duration > 0) {\n setTimeout(() => dismiss(id), duration)\n }\n },\n [dismiss, maxToasts],\n )\n\n const toast = useCallback(\n (options: Omit<Toast, 'id'>) => addToast(options),\n [addToast],\n )\n const success = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'success', title, description }),\n [addToast],\n )\n const error = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'error', title, description }),\n [addToast],\n )\n const warning = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'warning', title, description }),\n [addToast],\n )\n const info = useCallback(\n (title: string, description?: string) =>\n addToast({ type: 'info', title, description }),\n [addToast],\n )\n\n const positionClasses: Record<string, string> = {\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n 'top-center': 'top-4 left-1/2 -translate-x-1/2',\n 'bottom-center': 'bottom-4 left-1/2 -translate-x-1/2',\n }\n\n return (\n <ToastContext.Provider\n value={{ toasts, toast, success, error, warning, info, dismiss, dismissAll }}\n >\n {children}\n\n {/* Toast container */}\n <div\n className={`fixed z-[100] flex flex-col gap-2 ${positionClasses[position]}`}\n >\n {toasts.map((t) => (\n <ToastItem key={t.id} toast={t} onDismiss={() => dismiss(t.id)} />\n ))}\n </div>\n </ToastContext.Provider>\n )\n}\n\n// ============================================================================\n// ToastItem\n// ============================================================================\n\n/**\n * Per-type visual config. Body uses the neutral popover surface — the type\n * is conveyed by a thin colored left-edge accent and the icon glyph alone,\n * not by tinting the title text or stamping a chunky colored block behind\n * the icon. Cleaner read; doesn't compete with the page underneath.\n */\nconst TOAST_CONFIG = {\n success: { Icon: CheckCircleIcon, accent: 'bg-success', icon: 'text-success' },\n error: { Icon: AlertCircleIcon, accent: 'bg-destructive', icon: 'text-destructive' },\n warning: { Icon: AlertTriangleIcon, accent: 'bg-warning', icon: 'text-warning' },\n info: { Icon: InfoIcon, accent: 'bg-info', icon: 'text-info' },\n} as const\n\ninterface ToastItemProps {\n toast: Toast\n onDismiss: () => void\n}\n\nfunction ToastItem({ toast, onDismiss }: ToastItemProps): React.ReactElement {\n const { Icon, accent, icon } = TOAST_CONFIG[toast.type]\n const [exiting, setExiting] = useState(false)\n\n // Animate out before removing.\n useEffect(() => {\n if (exiting) {\n const timer = setTimeout(onDismiss, 150)\n return () => clearTimeout(timer)\n }\n }, [exiting, onDismiss])\n\n return (\n <div\n className={`\n relative flex items-start gap-2.5 min-w-[260px] max-w-[360px]\n overflow-hidden rounded-lg border border-border bg-popover\n text-popover-foreground pl-3.5 pr-2 py-2.5 shadow-lg\n ${exiting\n ? 'animate-out fade-out-0 slide-out-to-right-2 duration-150'\n : 'animate-in fade-in-0 slide-in-from-right-2 duration-200'\n }\n `}\n role=\"alert\"\n >\n {/* Colored left-edge accent — the only chrome that reflects the type. */}\n <span className={`absolute inset-y-0 left-0 w-[3px] ${accent}`} aria-hidden />\n <Icon className={`mt-0.5 h-4 w-4 shrink-0 ${icon}`} />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-[13px] font-medium leading-tight\">{toast.title}</p>\n {toast.description && (\n <p className=\"mt-0.5 text-xs leading-snug text-muted-foreground\">\n {toast.description}\n </p>\n )}\n </div>\n <button\n onClick={() => setExiting(true)}\n className=\"-mr-0.5 shrink-0 rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n aria-label=\"Dismiss\"\n >\n <CloseIcon className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n}\n","import React, { ReactNode, JSX } from 'react'\nimport { FileText, Search, Inbox, Plus, FolderOpen, Users, AlertCircle } from 'lucide-react'\nimport { cn } from './utils'\n\n// ============================================================================\n// EmptyState - Customizable empty state component\n// ============================================================================\n\ninterface EmptyStateProps extends React.HTMLAttributes<HTMLDivElement> {\n icon?: ReactNode\n title: string\n description?: string\n action?: {\n label: string\n onClick: () => void\n }\n secondaryAction?: {\n label: string\n onClick: () => void\n }\n}\n\nexport function EmptyState({\n icon,\n title,\n description,\n action,\n secondaryAction,\n className = '',\n ...rest\n}: EmptyStateProps): JSX.Element {\n return (\n <div className={cn('flex flex-col items-center justify-center py-16 px-4 text-center', className)} {...rest}>\n {icon && (\n <div className=\"w-16 h-16 rounded-2xl bg-muted/50 border border-border flex items-center justify-center mb-5\">\n <span className=\"text-muted-foreground\">{icon}</span>\n </div>\n )}\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">{title}</h3>\n {description && (\n <p className=\"text-muted-foreground text-sm max-w-sm mb-6\">{description}</p>\n )}\n {(action || secondaryAction) && (\n <div className=\"flex items-center gap-3\">\n {action && (\n <button\n onClick={action.onClick}\n className=\"inline-flex items-center gap-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg font-medium text-sm hover:bg-primary/90 shadow-lg shadow-primary/25 transition-all\"\n >\n <Plus className=\"w-4 h-4\" />\n {action.label}\n </button>\n )}\n {secondaryAction && (\n <button\n onClick={secondaryAction.onClick}\n className=\"px-4 py-2 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {secondaryAction.label}\n </button>\n )}\n </div>\n )}\n </div>\n )\n}\n\n// ============================================================================\n// Pre-built empty state variants\n// ============================================================================\n\ninterface EmptyStateVariantProps {\n action?: {\n label: string\n onClick: () => void\n }\n className?: string\n}\n\nexport function EmptyItems({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<Inbox className=\"w-8 h-8\" />}\n title=\"No items yet\"\n description=\"Get started by creating your first item.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\ninterface EmptySearchProps extends EmptyStateVariantProps {\n query?: string\n onClear?: () => void\n}\n\nexport function EmptySearch({ query, onClear, className }: EmptySearchProps): JSX.Element {\n return (\n <EmptyState\n icon={<Search className=\"w-8 h-8\" />}\n title=\"No results found\"\n description={query ? `No results for \"${query}\". Try a different search term.` : 'Try adjusting your search or filters.'}\n secondaryAction={onClear ? { label: 'Clear search', onClick: onClear } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyDocuments({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<FileText className=\"w-8 h-8\" />}\n title=\"No documents\"\n description=\"Create a document to start writing.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyProjects({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<FolderOpen className=\"w-8 h-8\" />}\n title=\"No projects\"\n description=\"Create a project to organize your work.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\nexport function EmptyTeam({ action, className }: EmptyStateVariantProps): JSX.Element {\n return (\n <EmptyState\n icon={<Users className=\"w-8 h-8\" />}\n title=\"No team members\"\n description=\"Invite people to collaborate with you.\"\n action={action ? { label: action.label, onClick: action.onClick } : undefined}\n className={className}\n />\n )\n}\n\ninterface EmptyErrorProps extends EmptyStateVariantProps {\n error?: string\n onRetry?: () => void\n}\n\nexport function EmptyError({ error, onRetry, className }: EmptyErrorProps): JSX.Element {\n return (\n <EmptyState\n icon={<AlertCircle className=\"w-8 h-8 text-destructive\" />}\n title=\"Something went wrong\"\n description={error || 'An error occurred. Please try again.'}\n action={onRetry ? { label: 'Try again', onClick: onRetry } : undefined}\n className={className}\n />\n )\n}\n\nexport default EmptyState\n","import * as React from 'react'\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n className\n )}\n {...props}\n />\n))\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-[calc(100vw-2rem)] sm:max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background/95 backdrop-blur-2xl p-4 sm:p-6 shadow-card-hover duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-2xl',\n className\n )}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 rounded-sm p-1 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n))\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col space-y-1.5 text-center sm:text-left',\n className\n )}\n {...props}\n />\n)\nDialogHeader.displayName = 'DialogHeader'\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n className\n )}\n {...props}\n />\n)\nDialogFooter.displayName = 'DialogFooter'\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className\n )}\n {...props}\n />\n))\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n))\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","import * as React from 'react'\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-react'\n\nimport { cn } from './utils'\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n inset && 'pl-8',\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto\" />\n </DropdownMenuPrimitive.SubTrigger>\n))\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n))\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[8rem] max-w-[calc(100vw-1rem)] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n))\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-sm py-2 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n))\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n 'px-2 py-1.5 text-sm font-semibold',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n))\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn('ml-auto text-xs tracking-widest opacity-60', className)}\n {...props}\n />\n )\n}\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut'\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n}\n","import * as React from 'react'\nimport * as TooltipPrimitive from '@radix-ui/react-tooltip'\n\nimport { cn } from './utils'\n\nconst TooltipProvider = TooltipPrimitive.Provider\n\nconst Tooltip = TooltipPrimitive.Root\n\nconst TooltipTrigger = TooltipPrimitive.Trigger\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </TooltipPrimitive.Portal>\n))\nTooltipContent.displayName = TooltipPrimitive.Content.displayName\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n","/**\n * Modal / ConfirmModal — backward-compatible wrappers around Dialog primitives.\n *\n * New code should use Dialog directly. These wrappers exist so existing\n * widget code (`<Modal open={...}>`) keeps working without changes.\n */\n\nimport React, { ReactNode, JSX } from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogHeader as DHeader,\n DialogTitle as DTitle,\n DialogDescription as DDescription,\n DialogFooter as DFooter,\n} from './Dialog'\nimport { Button } from './Button'\nimport { cn } from './utils'\n\n// ============================================================================\n// Modal - Accessible modal dialog (wraps Radix Dialog)\n// ============================================================================\n\ninterface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n open: boolean\n onClose: () => void\n children: ReactNode\n size?: 'sm' | 'md' | 'lg' | 'xl'\n}\n\nexport function Modal({\n open,\n onClose,\n children,\n size = 'md',\n className,\n}: ModalProps): JSX.Element {\n const sizes = {\n sm: 'max-w-[calc(100vw-2rem)] sm:max-w-sm',\n md: 'max-w-[calc(100vw-2rem)] sm:max-w-lg',\n lg: 'max-w-[calc(100vw-2rem)] sm:max-w-2xl',\n xl: 'max-w-[calc(100vw-2rem)] sm:max-w-4xl',\n }\n\n return (\n <Dialog open={open} onOpenChange={(v) => { if (!v) onClose() }}>\n <DialogContent aria-describedby={undefined} className={cn(sizes[size], 'flex flex-col max-h-[85vh]', className)}>\n {children}\n </DialogContent>\n </Dialog>\n )\n}\n\n// ============================================================================\n// Modal.Header\n// ============================================================================\n\ninterface ModalHeaderProps {\n children: ReactNode\n onClose?: () => void\n className?: string\n}\n\nfunction ModalHeader({ children, className = '' }: ModalHeaderProps): JSX.Element {\n return (\n <DHeader className={className}>\n {children}\n </DHeader>\n )\n}\n\n// ============================================================================\n// Modal.Title\n// ============================================================================\n\ninterface ModalTitleProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalTitle({ children, className = '' }: ModalTitleProps): JSX.Element {\n return (\n <DTitle className={className}>\n {children}\n </DTitle>\n )\n}\n\n// ============================================================================\n// Modal.Description\n// ============================================================================\n\ninterface ModalDescriptionProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalDescription({ children, className = '' }: ModalDescriptionProps): JSX.Element {\n return (\n <DDescription className={className}>\n {children}\n </DDescription>\n )\n}\n\n// ============================================================================\n// Modal.Body - Scrollable content area\n// ============================================================================\n\ninterface ModalBodyProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalBody({ children, className = '' }: ModalBodyProps): JSX.Element {\n return (\n <div className={cn('flex-1 overflow-y-auto py-4', className)}>\n {children}\n </div>\n )\n}\n\n// ============================================================================\n// Modal.Footer - Action buttons area\n// ============================================================================\n\ninterface ModalFooterProps {\n children: ReactNode\n className?: string\n}\n\nfunction ModalFooter({ children, className = '' }: ModalFooterProps): JSX.Element {\n return (\n <DFooter className={className}>\n {children}\n </DFooter>\n )\n}\n\n// ============================================================================\n// ConfirmModal - Pre-built confirmation dialog\n// ============================================================================\n\ninterface ConfirmModalProps {\n open: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n description?: string\n confirmText?: string\n cancelText?: string\n variant?: 'destructive' | 'default'\n loading?: boolean\n}\n\nexport function ConfirmModal({\n open,\n onClose,\n onConfirm,\n title,\n description,\n confirmText = 'Confirm',\n cancelText = 'Cancel',\n variant = 'destructive',\n loading = false,\n}: ConfirmModalProps): JSX.Element {\n return (\n <Modal open={open} onClose={onClose} size=\"sm\">\n <Modal.Header>\n <Modal.Title>{title}</Modal.Title>\n {description && <Modal.Description>{description}</Modal.Description>}\n </Modal.Header>\n <Modal.Footer>\n <Button variant=\"ghost\" onClick={onClose} disabled={loading}>\n {cancelText}\n </Button>\n <Button variant={variant} onClick={onConfirm} loading={loading}>\n {confirmText}\n </Button>\n </Modal.Footer>\n </Modal>\n )\n}\n\n// ============================================================================\n// Attach sub-components\n// ============================================================================\n\nModal.Header = ModalHeader\nModal.Title = ModalTitle\nModal.Description = ModalDescription\nModal.Body = ModalBody\nModal.Footer = ModalFooter\n\nexport default Modal\n","import * as React from 'react'\nimport { Search, X } from 'lucide-react'\nimport { cn } from './utils'\nimport { Input } from './Input'\n\ninterface SearchInputProps extends Omit<React.ComponentProps<'input'>, 'type'> {\n onClear?: () => void\n}\n\nconst SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(\n ({ className, onClear, value, ...props }, ref) => {\n return (\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground\" />\n <Input\n ref={ref}\n type=\"search\"\n className={cn('pl-9 pr-9', className)}\n value={value}\n {...props}\n />\n {value && onClear && (\n <button\n type=\"button\"\n onClick={onClear}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground hover:text-foreground transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n )\n }\n)\nSearchInput.displayName = 'SearchInput'\n\nexport { SearchInput }\n"],"mappings":"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","names":["Fragment","jsx","jsxs","useEffect","useRef","Fragment","jsx","useRef","useEffect","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","createContext","useContext","useEffect","useState","useCallback","useRef","useMemo","useRef","jsx","Fragment","jsx","createContext","useContext","useState","useRef","useCallback","useEffect","useMemo","useEffect","useState","useCallback","useRef","useMemo","Fragment","jsx","jsxs","recordMatchesWhere","useRef","useState","useCallback","useEffect","useMemo","useMemo","useMemo","useEffect","useCallback","useRef","useMemo","useContext","useContext","useMemo","useRef","useEffect","useCallback","useCallback","useContext","useMemo","useContext","useCallback","useMemo","useEffect","useMemo","useEffect","useMemo","useState","useEffect","useCallback","useRef","Y","useState","useRef","useEffect","msgDocKey","payload","useCallback","useMemo","useCallback","useMemo","useCallback","useEffect","useCallback","useState","useState","useEffect","useCallback","u","useState","useEffect","useCallback","useRef","useMemo","Y","useState","useRef","useMemo","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useState","useEffect","useCallback","useRef","useState","useRef","useEffect","useCallback","useCallback","useState","useMemo","useState","useMemo","useCallback","useCallback","useMemo","useMemo","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useCallback","useMemo","useCallback","useMemo","useCallback","useMemo","useRef","useRef","useMemo","useCallback","useCallback","useMemo","useMemo","useCallback","useCallback","useCallback","useEffect","r","g","b","Fragment","jsx","useEffect","useState","useEffect","createContext","useContext","useState","useEffect","useRef","useCallback","jsx","createContext","useContext","useEffect","useState","useRef","useCallback","useState","useEffect","useRef","useRef","useState","useEffect","DEFAULT_TIMEOUT_MS","useCallback","useEffect","useState","useState","useCallback","useEffect","jsx","jsxs","useCallback","useEffect","useMemo","useState","authedJson","useState","useCallback","useEffect","useMemo","React","jsx","React","jsx","React","jsx","React","jsx","React","jsx","jsxs","React","jsx","React","jsx","React","jsx","jsxs","React","Check","jsx","Check","React","jsx","React","cva","jsx","cva","Label","cva","jsx","cva","React","jsx","React","jsx","jsx","jsxs","_","jsx","jsxs","React","cva","jsx","cva","createContext","useContext","useState","useCallback","useEffect","jsx","jsxs","Icon","jsx","jsxs","React","jsx","jsxs","React","Check","jsx","jsxs","Check","React","jsx","jsx","jsxs","React","Search","X","jsx","jsxs","Search","X"]}