{"version":3,"sources":["../src/react.ts","../src/core/tab-claim.ts","../src/core/connection-supervisor.ts","../src/react/host-slot.ts","../src/react/provider.tsx","../src/core/ai.ts","../src/core/errors.ts","../src/core/leave.ts","../src/core/tokens.ts","../src/core/api.ts","../src/core/channels.ts","../src/core/reasons.ts","../src/core/phase.ts","../src/core/types.ts","../src/core/calls.ts","../src/core/devices.ts","../src/core/names.ts","../src/core/recording.ts","../src/core/live-policy.ts","../src/core/attendance.ts","../src/core/repository.ts","../src/core/app-panel.ts","../src/core/collab.ts","../src/core/transcript.ts","../src/core/store.ts","../src/core/meetings.ts","../src/core/session-identity.ts","../src/core/capabilities.ts","../src/core/media-supervisor.ts","../src/core/room-events.ts","../src/core/note-taker.ts","../src/core/room-driver.ts","../src/core/network-health.ts","../src/core/room.ts","../src/core/effects.ts","../src/core/in-room.ts","../src/core/livekit-driver.ts","../src/react/root.tsx","../src/core/observation.ts","../src/react/hooks.ts","../src/core/record.ts","../src/core/record-cache.ts","../src/core/captions-state.ts","../src/core/layout.ts","../src/react/skin-root.tsx","../src/skins/meet/components.tsx","../src/react/facade.ts","../src/core/after.ts","../src/core/format.ts","../src/react/app-panel.tsx","../src/core/collab-state.ts","../src/react/collab-hooks.ts","../src/core/reactions.ts","../src/core/speaking-detector.ts","../src/skins/meet/collab.tsx","../src/skins/meet/icons.tsx","../src/react/record.tsx","../src/react/calls-ui.tsx","../src/core/invitations.ts","../src/core/management.ts"],"sourcesContent":["\"use client\";\n\n/**\n * `@ai-matrx/meet/react` — the headless React binding (CORE-DESIGN §5.1).\n *\n * A host mounts ONE `<MeetProvider>`, drops `<IncomingCallHost />` high in the\n * tree, and renders `<MeetingSkinRoot />` on its meeting route. The in-call UI\n * is a skin (`@ai-matrx/meet/skins/meet`); this entry holds the provider, the\n * hooks, the observation root, the skin root and the skin-external surfaces.\n */\n\nexport {\n  MeetProvider,\n  useCanRecord,\n  useDeviceSnapshot,\n  useIsHost,\n  useRole,\n  useLocalUserId,\n  useMeetHost,\n  useMeetSnapshot,\n  useRequiredMeetHost,\n} from \"./react/provider\";\nexport type { MeetDiagnostic, MeetHost, MeetProviderProps } from \"./react/provider\";\n\n// THE OBSERVATION ROOT (S0): one `[data-meet-root]` per tab, for the scenario harness.\nexport { MeetRoot, useCoreObservation, useCoreRootProps } from \"./react/root\";\nexport type { CoreRootOptions } from \"./react/root\";\n\nexport {\n  useLeave,\n  useCalls,\n  useCanModerate,\n  useConsentNotice,\n  useElapsed,\n  useEndMeeting,\n  useGuestRecordAccess,\n  useHostControls,\n  useListenOnlyNotice,\n  useLobby,\n  useLocalMedia,\n  useMeetAi,\n  useCaptions,\n  useMeeting,\n  useMeetingId,\n  useMeetingRecord,\n  meetingRecordCache,\n  useMeetings,\n  useReactions,\n  useRecording,\n  useRoom,\n  useStage,\n  useTrack,\n  // Meet wave 2\n  MEET_SHORTCUTS,\n  useAudioLevel,\n  useHandQueue,\n  useMediaEffects,\n  useMeetShortcuts,\n  useModerationNotice,\n} from \"./react/hooks\";\nexport type {\n  TranscriptLine,\n  UseCallsResult,\n  UseEndMeetingResult,\n  UseGuestRecordAccessResult,\n  UseHostControlsResult,\n  UseMeetingRecordResult,\n  UseMeetingsResult,\n  UseLobbyResult,\n  UseMeetAiResult,\n  UseRecordingResult,\n  UseRoomResult,\n  UseMediaEffectsResult,\n} from \"./react/hooks\";\n\n// THE MEETING PAGE (S1): the one entry. Chooses the viewer's skin (only\n// `meet` until S9) and owns everything that is not a look.\nexport { MeetingSkinRoot } from \"./react/skin-root\";\nexport type { MeetingSkinRootProps } from \"./react/skin-root\";\n\n// SKIN-EXTERNAL SURFACES (CORE-DESIGN §5.3): outside every skin's boundary.\nexport { MeetingRecordView, RecordingPlayer } from \"./react/record\";\n// MRF-1: the host's control for what guests may read of a meeting — the\n// record view and the People panel mount it; a consumer's own meeting-settings\n// screen renders the same one rather than a second.\nexport { GuestRecordAccessControl } from \"./skins/meet/components\";\nexport { IncomingCallCard, IncomingCallHost } from \"./react/calls-ui\";\n\n// The headless surface a skin reads (also what `useMeetCore()` composes).\nexport { useMeetCore } from \"./react/facade\";\nexport type { MeetCore } from \"./react/facade\";\n\n// Collab and caption hooks — thin selectors over the core (S1).\nexport {\n  useActivityAttention,\n  useAvailableActivities,\n  useCaptionTranslation,\n  useCollab,\n  useCollabPanelRequest,\n} from \"./react/collab-hooks\";\nexport type { UseCollabResult } from \"./react/collab-hooks\";\n\n// HR-360 wave 2 (MD-15): the host app registers its panels; the room opens the meeting's one.\nexport { MeetAppPanels, useMeetAppPanel, useMeetAppPanelRegistry, useSharedFocus } from \"./react/app-panel\";\nexport type {\n  MeetAppPanelEntry,\n  MeetAppPanelProps,\n  MeetAppPanelRegistry,\n  ResolvedMeetAppPanel,\n  SharedFocus,\n} from \"./react/app-panel\";\n\n// The core is re-exported so a React consumer needs ONE import specifier.\nexport * from \"./index\";\n","/**\n * THE TAB CLAIM (S7, CORE-DESIGN §2.1 / §3.5) — one id per browser tab, through the platform port.\n *\n * The LiveKit identity is `<person key>~<tab id>`. The tab id lives in SESSION storage, so a\n * refresh keeps it (LiveKit evicts the old page's ghost under the same identity, nobody sees a\n * second copy) — but a browser's \"Duplicate tab\" COPIES session storage, and a copied id would\n * make the new tab evict the original. So every page CLAIMS its id at load:\n *\n *  1. Web Locks: `mx.meet.tab:<id>` held for the page's life. Taken → this page owns the id.\n *  2. Held by someone else → ask on the tab bus (BroadcastChannel) whether a live page answers\n *     for that id. A reloading page has already released its lock (or is gone and cannot\n *     answer), so silence means the id is ours; an answer means this is a duplicate → mint a\n *     fresh id and claim that.\n *\n * The same bus carries PRESENCE: a tab in a call answers \"who is in room R?\" so a second tab's\n * pre-join can offer \"Switch here / Join here too\" before anybody presses Join (cross-device, the\n * server asks instead — the token response's `second_device_choice`).\n *\n * The core never touches a browser global except through `webTabPlatform()`; tests pass fakes.\n */\n\n/** What the claim needs from the platform (web: Web Locks + BroadcastChannel + sessionStorage). */\nexport interface TabPlatform {\n  readonly storage: {\n    get(key: string): string | null;\n    set(key: string, value: string): void;\n  } | null;\n  /** Try to hold `name` for the page's life; resolves true when held, false when another holds it. */\n  tryLock(name: string): Promise<boolean>;\n  /** Same-device message bus, or null when the browser has none. */\n  bus: TabBus | null;\n  randomId(): string;\n}\n\nexport interface TabBus {\n  post(message: TabMessage): void;\n  subscribe(listener: (message: TabMessage) => void): () => void;\n}\n\nexport type TabMessage =\n  | { readonly kind: \"tab-alive?\"; readonly tabId: string; readonly from: string }\n  | { readonly kind: \"tab-alive\"; readonly tabId: string }\n  | { readonly kind: \"who-is-in?\"; readonly room: string; readonly person: string; readonly from: string }\n  | {\n      readonly kind: \"in-room\";\n      readonly room: string;\n      readonly person: string;\n      readonly tabId: string;\n      readonly to: string;\n      /** The meeting's `second_device` rule the live tab was told (absent from an older page). */\n      readonly rule?: string | null;\n    };\n\nexport const TAB_ID_KEY = \"mx.meet.tab\";\n/** How long a duplicated tab waits for the original to answer. */\nexport const TAB_ANSWER_MS = 250;\n\nexport interface TabClaim {\n  /** This page's claimed tab id (resolves once the claim settles). */\n  readonly tabId: Promise<string>;\n  /** Announce that this tab is in `room` as `person` (until `left`); answers presence questions. */\n  inRoom(room: string, person: string, rule?: string | null): void;\n  left(): void;\n  /** Is `person` in `room` on ANOTHER tab of this browser? Answers within `TAB_ANSWER_MS`. */\n  presentElsewhere(room: string, person: string): Promise<boolean>;\n  /**\n   * The same question, with the meeting's `second_device` rule the live tab holds — so the second\n   * tab offers the PROFILE's choice (Meet: Switch here / Join here too; Teams: Transfer here / Add\n   * this device) before anybody presses Join. Null when no other tab has the person live.\n   */\n  presenceElsewhere?(room: string, person: string): Promise<{ readonly rule: string | null } | null>;\n  dispose(): void;\n}\n\nfunction validTabId(value: string | null): value is string {\n  return value !== null && /^[A-Za-z0-9_-]{4,64}$/.test(value);\n}\n\nfunction wait(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function createTabClaim(platform: TabPlatform = webTabPlatform()): TabClaim {\n  let mine: string | null = null;\n  let current: { room: string; person: string; rule: string | null } | null = null;\n  const self = platform.randomId();\n  const unsubscribe =\n    platform.bus?.subscribe((message) => {\n      if (message.kind === \"tab-alive?\" && mine !== null && message.tabId === mine && message.from !== self) {\n        platform.bus?.post({ kind: \"tab-alive\", tabId: mine });\n      } else if (\n        message.kind === \"who-is-in?\" &&\n        current !== null &&\n        mine !== null &&\n        message.from !== self &&\n        message.room === current.room &&\n        message.person === current.person\n      ) {\n        platform.bus?.post({\n          kind: \"in-room\",\n          room: current.room,\n          person: current.person,\n          tabId: mine,\n          to: message.from,\n          rule: current.rule,\n        });\n      }\n    }) ?? (() => {});\n\n  async function someoneAnswersFor(tabId: string): Promise<boolean> {\n    const bus = platform.bus;\n    if (bus === null) return false;\n    let answered = false;\n    const stop = bus.subscribe((message) => {\n      if (message.kind === \"tab-alive\" && message.tabId === tabId) answered = true;\n    });\n    bus.post({ kind: \"tab-alive?\", tabId, from: self });\n    await wait(TAB_ANSWER_MS);\n    stop();\n    return answered;\n  }\n\n  async function claim(): Promise<string> {\n    const stored = platform.storage?.get(TAB_ID_KEY) ?? null;\n    let candidate = validTabId(stored) ? stored : platform.randomId();\n    for (let attempt = 0; attempt < 4; attempt++) {\n      const held = await platform.tryLock(`${TAB_ID_KEY}:${candidate}`);\n      if (held) break;\n      // Held: a duplicated tab (the original answers) or a reload racing its own unload (silence).\n      if (!(await someoneAnswersFor(candidate))) break;\n      candidate = platform.randomId();\n    }\n    mine = candidate;\n    platform.storage?.set(TAB_ID_KEY, candidate);\n    return candidate;\n  }\n\n  const tabId = claim();\n\n  async function presence(room: string, person: string): Promise<{ rule: string | null } | null> {\n    const bus = platform.bus;\n    if (bus === null) return null;\n    let seen: { rule: string | null } | null = null;\n    const stop = bus.subscribe((message) => {\n      if (message.kind === \"in-room\" && message.to === self && message.room === room && message.person === person) {\n        seen = { rule: seen?.rule ?? message.rule ?? null };\n      }\n    });\n    bus.post({ kind: \"who-is-in?\", room, person, from: self });\n    await wait(TAB_ANSWER_MS);\n    stop();\n    return seen;\n  }\n\n  return {\n    tabId,\n    inRoom(room, person, rule) {\n      current = { room, person, rule: rule ?? null };\n    },\n    left() {\n      current = null;\n    },\n    async presentElsewhere(room, person) {\n      return (await presence(room, person)) !== null;\n    },\n    presenceElsewhere: (room, person) => presence(room, person),\n    dispose() {\n      unsubscribe();\n    },\n  };\n}\n\nfunction randomTabId(): string {\n  const crypto = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n  const raw = crypto?.randomUUID?.() ?? `${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;\n  return raw.replace(/[^A-Za-z0-9]/g, \"\").slice(0, 16);\n}\n\n/** The web platform: sessionStorage, Web Locks (held until the page unloads), BroadcastChannel. */\nexport function webTabPlatform(): TabPlatform {\n  const g = globalThis as {\n    sessionStorage?: Storage;\n    navigator?: { locks?: { request: (name: string, options: { ifAvailable: boolean }, cb: (lock: unknown) => Promise<void>) => Promise<unknown> } };\n    BroadcastChannel?: new (name: string) => {\n      postMessage(message: unknown): void;\n      addEventListener(type: \"message\", listener: (event: { data: unknown }) => void): void;\n      removeEventListener(type: \"message\", listener: (event: { data: unknown }) => void): void;\n    };\n  };\n  const session = g.sessionStorage;\n  const storage =\n    session === undefined\n      ? null\n      : {\n          get(key: string) {\n            try {\n              return session.getItem(key);\n            } catch {\n              return null;\n            }\n          },\n          set(key: string, value: string) {\n            try {\n              session.setItem(key, value);\n            } catch {\n              // Private mode: the id lives for this page only.\n            }\n          },\n        };\n  const channel = g.BroadcastChannel !== undefined ? new g.BroadcastChannel(\"mx.meet.tabs\") : null;\n  const bus: TabBus | null =\n    channel === null\n      ? null\n      : {\n          post(message) {\n            channel.postMessage(message);\n          },\n          subscribe(listener) {\n            const handler = (event: { data: unknown }) => {\n              const data = event.data as TabMessage | null;\n              if (data !== null && typeof data === \"object\" && typeof (data as { kind?: unknown }).kind === \"string\") listener(data);\n            };\n            channel.addEventListener(\"message\", handler);\n            return () => channel.removeEventListener(\"message\", handler);\n          },\n        };\n  return {\n    storage,\n    bus,\n    randomId: randomTabId,\n    tryLock(name) {\n      const locks = g.navigator?.locks;\n      if (locks === undefined) return Promise.resolve(false);\n      return new Promise<boolean>((resolve) => {\n        locks\n          .request(name, { ifAvailable: true }, (lock) => {\n            if (lock === null) {\n              resolve(false);\n              return Promise.resolve();\n            }\n            resolve(true);\n            // Held for the page's life: released by the browser when the page unloads.\n            return new Promise<void>(() => {});\n          })\n          .catch(() => resolve(false));\n      });\n    },\n  };\n}\n","/**\n * CS — THE CONNECTION SUPERVISOR (CORE-DESIGN §3.3, step S6b).\n *\n * The one owner of \"is this tab still connected, and if not, why, and what happens next\". It\n * never touches a browser global itself — the network signal and the reachability probe arrive\n * as ports (`NetworkPort`, `probe`), with web implementations below for the provider to hand in —\n * and it never moves the phase except through `store.dispatch` (via the engine's `autoRejoin`).\n *\n * What it decides:\n *\n * 1. **The `connection` region** (§3.2): `stable · signal_reconnecting · reconnecting · offline ·\n *    server_unreachable`. `offline` = the device has no network (`navigator.onLine` false);\n *    `server_unreachable` = online, but our API or the media server does not answer the probe.\n *    The two get different screens because they have different fixes.\n * 2. **The banner debounce** (`reconnect_banner_delay_ms`): the region is honest at once (the\n *    contract attribute), the banner appears only if the blip outlasts the delay (`net-blip`).\n * 3. **Auto-rejoin after the SDK gives up** (`auto_rejoin`, `auto_rejoin_max_attempts`): from\n *    `disconnected`, when the network is back AND the probe answers, rejoin with a fresh mint into\n *    the same identity — the server restores role / hand / admission from the person row. Attempts\n *    are only spent while reachable; a long offline spell costs none. Manual Rejoin always works.\n * 4. **The reload-after-offline marker**: while in the call (or dropped from it) the tab keeps a\n *    per-tab marker, so a page that Chrome replaced with its own offline page and then reloaded\n *    comes back INTO the call instead of to the pre-join (`resume`). A deliberate exit clears it.\n * 5. **The jittered reconnect policy** handed to LiveKit (`createReconnectPolicy`): jitter from\n *    attempt 0 (the SDK's default has none on its first two attempts — 650 people reconnecting\n *    on the same millisecond is the thundering-herd issue), with the give-up limits as options.\n *\n * Others' drops (`net-others-see-drop`) are the pure ghost helpers at the bottom: an unannounced\n * departure keeps a `reconnecting` tile for `reconnect_grace_seconds`.\n */\n\nimport type { DriverConnectionState, DriverParticipant } from \"./room-driver\";\nimport type { JoinRequest } from \"./room\";\nimport type { ConnectionRegion, MeetStore } from \"./store\";\nimport type { MeetPhase } from \"./phase\";\n\n/* ------------------------------------------------------------------ policy (knobs) */\n\n/** The server-delivered connection knobs (CORE-DESIGN §4.2/§4.3), resolved per meeting. */\nexport interface ConnectionPolicy {\n  /** `reconnect_banner_delay_ms`: how long a drop must last before the banner shows. */\n  readonly bannerDelayMs: number;\n  /** `auto_rejoin`: rejoin by itself after the SDK gives up. */\n  readonly autoRejoin: boolean;\n  /** `auto_rejoin_max_attempts`: rejoin attempts (while reachable) before only Rejoin is left. */\n  readonly autoRejoinMaxAttempts: number;\n  /** `reconnect_grace_seconds`: how long others keep a dropped person's `reconnecting` tile. */\n  readonly reconnectGraceSeconds: number;\n  /**\n   * `video_auto_off_after_poor_seconds`: a poor path that lasts this long pauses the person's\n   * camera so their audio survives (`net-video-auto-off`); 0 = never.\n   */\n  readonly videoAutoOffAfterPoorSeconds: number;\n  /**\n   * `captions_start_timeout_seconds`: how long \"Starting captions\" may last before the person is\n   * told, honestly, that captions are unavailable (and offered Try again).\n   */\n  readonly captionsStartTimeoutSeconds: number;\n}\n\n/** The knob defaults (§4.3) — what an older server that sends nothing gets. */\nexport const DEFAULT_CONNECTION_POLICY: ConnectionPolicy = {\n  bannerDelayMs: 5000,\n  autoRejoin: true,\n  autoRejoinMaxAttempts: 5,\n  reconnectGraceSeconds: 30,\n  videoAutoOffAfterPoorSeconds: 20,\n  captionsStartTimeoutSeconds: 20,\n};\n\nfunction clampInt(value: unknown, min: number, max: number, fallback: number): number {\n  if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n  return Math.min(max, Math.max(min, Math.round(value)));\n}\n\n/** The token's `connection_policy` object → the typed policy; anything missing is the default. */\nexport function connectionPolicyFrom(raw: unknown): ConnectionPolicy {\n  if (typeof raw !== \"object\" || raw === null) return DEFAULT_CONNECTION_POLICY;\n  const row = raw as Record<string, unknown>;\n  const d = DEFAULT_CONNECTION_POLICY;\n  return {\n    bannerDelayMs: clampInt(row[\"reconnect_banner_delay_ms\"], 0, 10_000, d.bannerDelayMs),\n    autoRejoin: typeof row[\"auto_rejoin\"] === \"boolean\" ? row[\"auto_rejoin\"] : d.autoRejoin,\n    autoRejoinMaxAttempts: clampInt(row[\"auto_rejoin_max_attempts\"], 0, 20, d.autoRejoinMaxAttempts),\n    reconnectGraceSeconds: clampInt(row[\"reconnect_grace_seconds\"], 0, 600, d.reconnectGraceSeconds),\n    videoAutoOffAfterPoorSeconds: clampInt(row[\"video_auto_off_after_poor_seconds\"], 0, 600, d.videoAutoOffAfterPoorSeconds),\n    captionsStartTimeoutSeconds: clampInt(row[\"captions_start_timeout_seconds\"], 1, 600, d.captionsStartTimeoutSeconds),\n  };\n}\n\n/* ------------------------------------------------------------------ LiveKit policy */\n\n/** LiveKit's `ReconnectPolicy` shape, restated so this module never imports the SDK. */\nexport interface ReconnectPolicyLike {\n  nextRetryDelayInMs(context: { readonly retryCount: number; readonly elapsedMs: number }): number | null;\n}\n\nexport interface ReconnectPolicyOptions {\n  /** Base delay per attempt (ms); the last one repeats. Default: LiveKit's own schedule. */\n  readonly delaysMs?: readonly number[];\n  /** Stop after this long since the drop (ms). Default 45 000 — about the SDK's own ~44 s. */\n  readonly giveUpMs?: number;\n  /** Stop after this many attempts. Default 12. */\n  readonly maxAttempts?: number;\n  readonly random?: () => number;\n}\n\n/** livekit-client 2.22 `DEFAULT_RETRY_DELAYS_IN_MS` (verified in the SDK source, 2026-10-08). */\nexport const LIVEKIT_BASE_DELAYS_MS: readonly number[] = [0, 300, 1200, 2700, 4800, 7000];\n\n/**\n * THE JITTERED RECONNECT POLICY. Every attempt — attempt 0 included — gets a random spread of at\n * least 500 ms (half the base delay, capped at 2 s), so a room whose SFU blinks does not hear\n * every client come back on the same millisecond.\n */\nexport function createReconnectPolicy(options: ReconnectPolicyOptions = {}): ReconnectPolicyLike {\n  const delays = options.delaysMs !== undefined && options.delaysMs.length > 0 ? options.delaysMs : LIVEKIT_BASE_DELAYS_MS;\n  const giveUpMs = options.giveUpMs ?? 45_000;\n  const maxAttempts = options.maxAttempts ?? 12;\n  const random = options.random ?? Math.random;\n  return {\n    nextRetryDelayInMs({ retryCount, elapsedMs }) {\n      if (retryCount >= maxAttempts || elapsedMs >= giveUpMs) return null;\n      const base = delays[Math.min(retryCount, delays.length - 1)] ?? 0;\n      const spread = Math.min(2000, Math.max(500, base / 2));\n      return Math.round(base + random() * spread);\n    },\n  };\n}\n\n/* ------------------------------------------------------------------ ports */\n\n/** Whether the device has a network, and when that changes (the platform port's `network`). */\nexport interface NetworkPort {\n  online(): boolean;\n  subscribe(listener: (online: boolean) => void): () => void;\n}\n\n/** `navigator.onLine` + `online`/`offline` events; outside a browser it is always online. */\nexport function createWebNetworkPort(): NetworkPort {\n  const scope = globalThis as unknown as {\n    navigator?: { onLine?: boolean };\n    addEventListener?: (type: string, fn: () => void) => void;\n    removeEventListener?: (type: string, fn: () => void) => void;\n  };\n  return {\n    online: () => scope.navigator?.onLine !== false,\n    subscribe(listener) {\n      if (typeof scope.addEventListener !== \"function\") return () => undefined;\n      const on = (): void => listener(true);\n      const off = (): void => listener(false);\n      scope.addEventListener(\"online\", on);\n      scope.addEventListener(\"offline\", off);\n      return () => {\n        scope.removeEventListener?.(\"online\", on);\n        scope.removeEventListener?.(\"offline\", off);\n      };\n    },\n  };\n}\n\n/**\n * THE REACHABILITY PROBE: does each URL answer at all? An opaque (`no-cors`) GET resolves for any\n * HTTP answer and rejects only when the network path is down — exactly the question, with no\n * CORS dependency. All URLs must answer; a timeout is a \"no\".\n */\nexport function createReachabilityProbe(urls: () => readonly string[], timeoutMs = 4000): () => Promise<boolean> {\n  return async () => {\n    const targets = urls().filter((url) => url.length > 0);\n    if (targets.length === 0 || typeof fetch !== \"function\") return true;\n    const one = async (url: string): Promise<boolean> => {\n      const controller = typeof AbortController === \"function\" ? new AbortController() : null;\n      const timer = setTimeout(() => controller?.abort(), timeoutMs);\n      try {\n        await fetch(url, {\n          method: \"GET\",\n          mode: \"no-cors\",\n          cache: \"no-store\",\n          credentials: \"omit\",\n          ...(controller !== null ? { signal: controller.signal } : {}),\n        });\n        return true;\n      } catch {\n        return false;\n      } finally {\n        clearTimeout(timer);\n      }\n    };\n    const answers = await Promise.all(targets.map(one));\n    return answers.every(Boolean);\n  };\n}\n\n/** `wss://x.livekit.cloud` → `https://x.livekit.cloud` (what the probe can GET). */\nexport function httpUrlOf(serverUrl: string): string {\n  return serverUrl.replace(/^ws(s?):\\/\\//i, \"http$1://\");\n}\n\n/* ------------------------------------------------------------------ resume marker */\n\n/** Per-tab storage for the reload-after-offline marker (session storage on the web). */\nexport interface ResumeStorage {\n  load(roomName: string): ResumeMarker | null;\n  save(roomName: string, marker: ResumeMarker): void;\n  clear(roomName: string): void;\n}\n\nexport interface ResumeMarker {\n  readonly request: JoinRequest;\n  /** Epoch ms of the last time this tab was in (or dropped from) the call. */\n  readonly at: number;\n}\n\n/** How long after the last in-call moment a reload still goes straight back in. */\nexport const RESUME_WINDOW_MS = 15 * 60_000;\n\nconst RESUME_KEY = \"mx-meet:resume:\";\n\nexport function createWebResumeStorage(): ResumeStorage | undefined {\n  const storage = (globalThis as unknown as { sessionStorage?: Storage }).sessionStorage;\n  if (storage === undefined) return undefined;\n  return {\n    load(roomName) {\n      try {\n        const raw = storage.getItem(RESUME_KEY + roomName);\n        if (raw === null) return null;\n        const parsed = JSON.parse(raw) as ResumeMarker;\n        return typeof parsed?.at === \"number\" && typeof parsed.request?.roomName === \"string\" ? parsed : null;\n      } catch {\n        return null;\n      }\n    },\n    save(roomName, marker) {\n      try {\n        storage.setItem(RESUME_KEY + roomName, JSON.stringify(marker));\n      } catch {\n        // Storage full or blocked: a reload lands on the pre-join, as before. Not fatal.\n      }\n    },\n    clear(roomName) {\n      try {\n        storage.removeItem(RESUME_KEY + roomName);\n      } catch {\n        // Already gone.\n      }\n    },\n  };\n}\n\n/** Phases a deliberate or server-decided exit lands on: the marker is cleared, no resume. */\nconst CLEARS_RESUME = (phase: MeetPhase): boolean =>\n  phase === \"left\" ||\n  phase === \"removed\" ||\n  phase === \"superseded\" ||\n  phase === \"inactive\" ||\n  phase === \"ended\" ||\n  phase === \"record\" ||\n  phase === \"prejoin\" ||\n  phase === \"denied\" ||\n  phase === \"knock_expired\" ||\n  phase.startsWith(\"refused:\");\n\n/**\n * `wr-refresh-while-waiting`: a reload while waiting goes straight back to waiting (the same\n * person key, the same knock — the server keeps its place), never to the name or device steps.\n */\nconst WAITING_RESUMES = (phase: MeetPhase): boolean => phase.startsWith(\"waiting:\");\n\n/* ------------------------------------------------------------------ the supervisor */\n\nexport interface ConnectionSupervisorOptions {\n  readonly store: MeetStore;\n  readonly network: NetworkPort;\n  /** Do our API and the media server answer? */\n  readonly probe: () => Promise<boolean>;\n  readonly policy: () => ConnectionPolicy;\n  /** Rejoin from `disconnected` with a fresh mint (the engine's `autoRejoin`). */\n  readonly autoRejoin: () => Promise<void>;\n  /** The request to resume with (current media state folded in), or null. */\n  readonly currentRequest: () => JoinRequest | null;\n  readonly resume?: ResumeStorage | undefined;\n  readonly now?: () => number;\n  readonly random?: () => number;\n  /** How often to re-probe while not stable (ms). Default 3000. */\n  readonly probeEveryMs?: number;\n  readonly report?: (level: \"info\" | \"warn\", message: string) => void;\n}\n\nexport interface ConnectionSupervisor {\n  /** LiveKit's connection state, as the driver reports it. */\n  driverState(state: DriverConnectionState): void;\n  /** The region to show beside `disconnected` when the server's state read failed. */\n  exitConnection(): Exclude<ConnectionRegion, \"stable\" | \"reconnecting\" | \"signal_reconnecting\">;\n  /** The resume marker for `roomName` if it is fresh, else null (and a stale one is cleared). */\n  resumable(roomName: string): ResumeMarker | null;\n  dispose(): void;\n}\n\n/** Backoff before auto-rejoin attempt `n` (0-based): 1 s, 2 s, 4 s … capped at 15 s, jittered ±50%. */\nexport function autoRejoinDelayMs(attempt: number, random: () => number = Math.random): number {\n  const base = Math.min(15_000, 1000 * 2 ** Math.max(0, attempt));\n  return Math.round(base * (0.5 + random()));\n}\n\nexport function createConnectionSupervisor(options: ConnectionSupervisorOptions): ConnectionSupervisor {\n  const { store, network } = options;\n  const now = options.now ?? (() => Date.now());\n  const random = options.random ?? Math.random;\n  const probeEveryMs = options.probeEveryMs ?? 3000;\n\n  /** What LiveKit last said, independent of the network: null = connected / not in a room. */\n  let driverRegion: \"reconnecting\" | \"signal_reconnecting\" | null = null;\n  let probeTimer: ReturnType<typeof setTimeout> | null = null;\n  let probing = false;\n  let bannerTimer: ReturnType<typeof setTimeout> | null = null;\n  let rejoinTimer: ReturnType<typeof setTimeout> | null = null;\n  let rejoinAttempts = 0;\n  let lastPhase: MeetPhase = store.snapshot().phase;\n  let lastSavedAt = 0;\n  let disposed = false;\n\n  const inCall = (): boolean => store.snapshot().phase === \"in_call\";\n  const dropped = (): boolean => store.snapshot().phase === \"disconnected\";\n\n  function setRegion(next: ConnectionRegion): void {\n    if (store.snapshot().connection !== next) store.patch({ connection: next });\n  }\n\n  /** The region the facts say, given the last probe answer (true/false) or none (null). */\n  function regionFor(reachable: boolean | null): ConnectionRegion {\n    if (!network.online()) return \"offline\";\n    if (reachable === false) return \"server_unreachable\";\n    if (dropped()) return reachable === true ? \"stable\" : store.snapshot().connection;\n    return driverRegion ?? \"stable\";\n  }\n\n  function needsWatch(): boolean {\n    const snap = store.snapshot();\n    if (dropped()) return true;\n    return inCall() && (driverRegion !== null || snap.connection !== \"stable\");\n  }\n\n  function stopProbe(): void {\n    if (probeTimer !== null) clearTimeout(probeTimer);\n    probeTimer = null;\n  }\n\n  function scheduleProbe(delayMs: number): void {\n    if (disposed || probeTimer !== null) return;\n    probeTimer = setTimeout(() => {\n      probeTimer = null;\n      void runProbe();\n    }, delayMs);\n  }\n\n  async function runProbe(): Promise<void> {\n    if (disposed || probing) return;\n    if (!needsWatch()) return;\n    if (!network.online()) {\n      setRegion(\"offline\");\n      scheduleProbe(probeEveryMs);\n      return;\n    }\n    probing = true;\n    let reachable = false;\n    try {\n      reachable = await options.probe();\n    } catch {\n      reachable = false;\n    } finally {\n      probing = false;\n    }\n    if (disposed) return;\n    if (inCall() || dropped()) setRegion(regionFor(reachable));\n    if (dropped() && reachable) maybeRejoin();\n    if (needsWatch()) scheduleProbe(Math.round(probeEveryMs * (0.75 + random() * 0.5)));\n  }\n\n  function syncBanner(): void {\n    const snap = store.snapshot();\n    const unstable = snap.phase === \"in_call\" && snap.connection !== \"stable\";\n    if (!unstable) {\n      if (bannerTimer !== null) clearTimeout(bannerTimer);\n      bannerTimer = null;\n      if (snap.connectionBanner) store.patch({ connectionBanner: false });\n      return;\n    }\n    if (snap.connectionBanner || bannerTimer !== null) return;\n    const delay = options.policy().bannerDelayMs;\n    if (delay <= 0) {\n      store.patch({ connectionBanner: true });\n      return;\n    }\n    bannerTimer = setTimeout(() => {\n      bannerTimer = null;\n      const latest = store.snapshot();\n      if (latest.phase === \"in_call\" && latest.connection !== \"stable\" && !latest.connectionBanner) {\n        store.patch({ connectionBanner: true });\n      }\n    }, delay);\n  }\n\n  function stopRejoin(): void {\n    if (rejoinTimer !== null) clearTimeout(rejoinTimer);\n    rejoinTimer = null;\n  }\n\n  /** From `disconnected`, once reachable: one backoff-delayed attempt (if the policy allows). */\n  function maybeRejoin(): void {\n    if (disposed || rejoinTimer !== null || !dropped()) return;\n    const policy = options.policy();\n    if (!policy.autoRejoin) return;\n    if (rejoinAttempts >= policy.autoRejoinMaxAttempts) return;\n    if (!network.online()) return;\n    const attempt = rejoinAttempts;\n    rejoinTimer = setTimeout(() => {\n      rejoinTimer = null;\n      if (disposed || !dropped() || !network.online()) return;\n      rejoinAttempts = attempt + 1;\n      options.report?.(\"info\", `meet: rejoining by itself (attempt ${rejoinAttempts} of ${policy.autoRejoinMaxAttempts})`);\n      void options.autoRejoin().catch(() => undefined);\n    }, autoRejoinDelayMs(attempt, random));\n  }\n\n  function saveMarker(force: boolean): void {\n    const resume = options.resume;\n    const snap = store.snapshot();\n    if (resume === undefined || snap.roomName === null) return;\n    const at = now();\n    if (!force && at - lastSavedAt < 10_000) return;\n    const request = options.currentRequest();\n    if (request === null) return;\n    lastSavedAt = at;\n    resume.save(snap.roomName, { request, at });\n  }\n\n  const unsubscribeStore = store.subscribe(() => {\n    if (disposed) return;\n    const snap = store.snapshot();\n    const phase = snap.phase;\n    const changed = phase !== lastPhase;\n    lastPhase = phase;\n    if (changed) {\n      if (phase === \"in_call\") {\n        rejoinAttempts = 0;\n        stopRejoin();\n        saveMarker(true);\n      } else if (WAITING_RESUMES(phase)) {\n        stopRejoin();\n        driverRegion = null;\n        saveMarker(true);\n      } else if (phase === \"disconnected\") {\n        driverRegion = null;\n        saveMarker(true);\n        // Reachable right now? Probe at once; the probe starts the rejoin.\n        stopProbe();\n        scheduleProbe(0);\n      } else {\n        stopRejoin();\n        if (phase !== \"joining\") driverRegion = null;\n        if (CLEARS_RESUME(phase) && snap.roomName !== null) options.resume?.clear(snap.roomName);\n      }\n    } else if (phase === \"in_call\" || phase === \"disconnected\") {\n      saveMarker(false);\n    }\n    syncBanner();\n  });\n\n  const unsubscribeNetwork = network.subscribe((online) => {\n    if (disposed) return;\n    if (!online) {\n      if (inCall() || dropped()) setRegion(\"offline\");\n      stopRejoin();\n      stopProbe();\n      if (needsWatch()) scheduleProbe(probeEveryMs);\n      return;\n    }\n    // Back online: is it really (our servers answer)? The probe decides the region and the rejoin.\n    stopProbe();\n    if (needsWatch()) scheduleProbe(0);\n  });\n\n  return {\n    driverState(state) {\n      if (disposed) return;\n      if (state === \"connected\") {\n        driverRegion = null;\n        if (inCall() || store.snapshot().phase === \"joining\") setRegion(network.online() ? \"stable\" : \"offline\");\n        if (!needsWatch()) stopProbe();\n        return;\n      }\n      if (state === \"reconnecting\" || state === \"signal_reconnecting\") {\n        driverRegion = state;\n        if (inCall()) {\n          // Honest at once: no network is `offline` before any probe; otherwise LiveKit's word,\n          // until the probe says whether our servers answer.\n          setRegion(network.online() ? state : \"offline\");\n          stopProbe();\n          scheduleProbe(0);\n        }\n      }\n    },\n    exitConnection() {\n      return network.online() ? \"server_unreachable\" : \"offline\";\n    },\n    resumable(roomName) {\n      const resume = options.resume;\n      if (resume === undefined) return null;\n      const marker = resume.load(roomName);\n      if (marker === null) return null;\n      if (now() - marker.at > RESUME_WINDOW_MS) {\n        resume.clear(roomName);\n        return null;\n      }\n      return marker;\n    },\n    dispose() {\n      disposed = true;\n      stopProbe();\n      stopRejoin();\n      if (bannerTimer !== null) clearTimeout(bannerTimer);\n      bannerTimer = null;\n      unsubscribeStore();\n      unsubscribeNetwork();\n    },\n  };\n}\n\n/* ------------------------------------------------------------------ others' drops (ghosts) */\n\n/**\n * LiveKit departure reasons that mean \"they meant to go, or were sent\": no ghost. Anything else —\n * no reason, a signal close, a timeout, a media failure — is a drop, and the tile stays as\n * `reconnecting` for `reconnect_grace_seconds` so others see the truth instead of a vanished tile.\n */\nconst DELIBERATE_DEPARTURES: ReadonlySet<string> = new Set([\n  \"CLIENT_INITIATED\",\n  \"PARTICIPANT_REMOVED\",\n  \"ROOM_DELETED\",\n  \"ROOM_CLOSED\",\n  \"DUPLICATE_IDENTITY\",\n  \"USER_REJECTED\",\n  \"USER_UNAVAILABLE\",\n  \"SIP_TRUNK_FAILURE\",\n]);\n\nexport function isUnannouncedDeparture(reason: string | null): boolean {\n  return reason === null || !DELIBERATE_DEPARTURES.has(reason);\n}\n\nexport interface Ghost {\n  readonly participant: DriverParticipant;\n  readonly until: number;\n}\n\n/**\n * The roster with the live ghosts merged in. A ghost whose identity is back in the live roster is\n * dropped (the person returned — one tile, never a copy); an expired one is dropped.\n */\nexport function mergeGhosts(\n  live: readonly DriverParticipant[],\n  ghosts: ReadonlyMap<string, Ghost>,\n  at: number,\n): { readonly roster: readonly (DriverParticipant & { readonly reconnecting?: boolean })[]; readonly kept: Map<string, Ghost> } {\n  const present = new Set(live.map((p) => p.identity));\n  const kept = new Map<string, Ghost>();\n  const extra: (DriverParticipant & { readonly reconnecting: boolean })[] = [];\n  for (const [identity, ghost] of ghosts) {\n    if (present.has(identity) || ghost.until <= at) continue;\n    kept.set(identity, ghost);\n    extra.push({\n      ...ghost.participant,\n      micEnabled: false,\n      cameraEnabled: false,\n      screenSharing: false,\n      reconnecting: true,\n    });\n  }\n  return { roster: [...live, ...extra], kept };\n}\n","\"use client\";\n\n/**\n * `@ai-matrx/meet/host-slot` — the Meet host CONTEXT and nothing else (a few hundred bytes).\n *\n * A host app that must keep `<MeetProvider>`'s whole engine out of its first load (the app shell\n * mounts Meet on every signed-in route, but nothing renders until a call arrives) renders this\n * context's Provider itself, immediately, with an inert `null` — and a lazily loaded core mounts\n * `<MeetProvider>` as a null-rendering sibling that publishes its live `MeetHost` up through\n * `onHost`. Children never remount; every `useMeetHost()` reader sees `null` (inert) until the\n * engine is ready, which is the state it already handles for a signed-out visitor.\n *\n * ONE CONTEXT across entries: the object lives in the globalThis slot (see provider.tsx S1), so\n * this entry, `/react` and `/skins/meet` all resolve the same one.\n */\n\nimport { createContext } from \"react\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport type { MeetHost } from \"./provider\";\n\nexport type { MeetHost } from \"./provider\";\n\nexport const MeetHostContext = globalSlot(\"ai-matrx.meet.react.context\", () => createContext<MeetHost | null>(null));\n","\"use client\";\n\n/**\n * `<MeetProvider>` — the one place an app wires calls and meetings (R7).\n *\n * THE ONE-HOUR INTEGRATION CONTRACT is this component's job: a host passes a\n * Supabase client, who they are, their org, and aidream's base URL. Everything\n * else — the repository, the realtime manager and its three channels, the token\n * client, the room engine, the call center, the meeting session, the recording\n * controller, the device manager, the AI surface — is constructed and owned\n * here.\n *\n * What a host may inject is IDENTITY and app chrome: session source, a\n * navigator, a notification sink. It may NOT inject an agent id — as of 0.3.0\n * there is no prop for one, because which agent answers is a Mandate binding\n * the SERVER resolves (D2). What a host must NEVER have to inject is\n * behavior — if you find yourself catching a package error, retrying a package\n * call, or branching on a package quirk in host code, that logic belongs in\n * here (C22).\n *\n * 🚨 THE PROVIDER'S LIFETIME IS `client` + the SESSION'S user (or `guestName`)\n * + `organizationId` + `baseUrl`, AND NOTHING ELSE. Hosts pass fresh function\n * literals for `onDiagnostic` and `accessToken` on every render; keying the\n * runtime on those identities would tear down and rebuild every channel — and\n * drop the call in progress — on every parent re-render.\n *\n * 🚨 THERE IS NO `userId` PROP, AND THERE NEVER WILL BE AGAIN (DD-240, 0.6.0).\n * The acting user is read from `client`'s own session — the same client that\n * mints the JWT on every request — so the id in a `p_user_id` argument and the\n * id in the token cannot disagree. Through 0.5.x this was a prop, every host\n * filled it from a copy in its own state, and a rotated auth cookie left that\n * copy naming an account the tab could no longer prove it was:\n * `meet_pending_call_invites` refused it at 403 with \"the acting user … is not\n * the authenticated user\", 8.8 h and 32.9 h into two tabs' lives. The whole\n * story is in `../core/session-identity.ts`.\n *\n * 🚨 A GUEST IS A FIRST-CLASS IDENTITY (D6), not a degraded user. Pass\n * `guestName` and the provider builds a runtime with no calling surface and no\n * host powers, which is exactly what a link-follower needs — and, because a\n * guest has no account at all, the guest lane never reads the session. Nothing\n * downstream branches on \"is this a real user\".\n */\n\nimport { createTabClaim, type TabClaim } from \"../core/tab-claim\";\nimport {\n  createReachabilityProbe,\n  createWebNetworkPort,\n  createWebResumeStorage,\n  httpUrlOf,\n} from \"../core/connection-supervisor\";\nimport { MeetHostContext } from \"./host-slot\";\nimport {\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  useSyncExternalStore,\n  type ReactNode,\n} from \"react\";\nimport {\n  RealtimeProvider,\n  useIsRealtimeProviderMounted,\n  useRealtimeManager,\n} from \"@ai-matrx/data/realtime/react\";\nimport type { MessagingSupabaseClient } from \"@ai-matrx/messaging\";\nimport { createMeetAi, type MeetAi } from \"../core/ai\";\nimport { createMeetApi, type MeetApi } from \"../core/api\";\nimport { createCallCenter, type CallCenter } from \"../core/calls\";\nimport {\n  createDeviceManager,\n  createWebDeviceStorage,\n  type DeviceManager,\n  type DeviceSnapshot,\n  type MediaDevicesLike,\n} from \"../core/devices\";\nimport { createMeetingSession, type MeetingSession } from \"../core/meetings\";\nimport { createRecordingController, type RecordingController } from \"../core/recording\";\nimport { createMeetRepository, type MeetRepository } from \"../core/repository\";\nimport {\n  createMeetSessionIdentity as createSessionIdentity,\n  SERVER_SESSION_IDENTITY,\n  type SessionIdentitySnapshot,\n} from \"../core/session-identity\";\nimport { createRoomEngine, type RoomEngine } from \"../core/room\";\nimport { isWaitingPhase } from \"../core/phase\";\nimport { createWebEffectsStorage } from \"../core/effects\";\nimport { createInRoomClient, type InRoomClient } from \"../core/in-room\";\nimport { createLiveKitDriver } from \"../core/livekit-driver\";\nimport type { RoomDriverFactory } from \"../core/room-driver\";\nimport {\n  createMeetStore,\n  effectiveRole,\n  type MeetSnapshot,\n  type MeetStore,\n} from \"../core/store\";\nimport {\n  createTokenClient,\n  createWebRoomTokenStorage,\n  type AccessTokenSource,\n  type TokenClient,\n} from \"../core/tokens\";\nimport {\n  asOrganizationId,\n  isHostRole,\n  type CallInvite,\n  type MeetIdentity,\n  type ParticipantRole,\n  type UserId,\n} from \"../core/types\";\n\nexport interface MeetDiagnostic {\n  readonly level: \"info\" | \"warn\" | \"error\";\n  readonly message: string;\n  readonly remedy?: string | undefined;\n}\n\nexport interface MeetHost {\n  readonly store: MeetStore;\n  readonly engine: RoomEngine;\n  readonly calls: CallCenter | null;\n  readonly meetings: MeetingSession;\n  /**\n   * Meet wave 2: host moderation and the SAVED chat, both decided and written by\n   * the server (`core/in-room.ts`). A guest's calls carry their room pass.\n   */\n  readonly inRoom: InRoomClient;\n  readonly recording: RecordingController;\n  readonly devices: DeviceManager;\n  readonly repository: MeetRepository;\n  readonly tokens: TokenClient;\n  /**\n   * 🚨 NEVER NULL as of 0.3.0. Through 0.2.1 this was `null` unless the host\n   * injected a transport AND four agent ids, so the meeting assistant silently\n   * did not exist for any app that had not filled in a config line. The\n   * capability is the SERVER's now: if a Mandate has no Holder bound, the\n   * server refuses with a sentence naming the Mandate admin, and that sentence\n   * is what the panel shows. Absence is a fact the server states, never a prop\n   * a host forgot.\n   */\n  readonly ai: MeetAi;\n  /**\n   * 🚨 THE ONE WAY ANYTHING IN THIS PACKAGE TALKS TO AIDREAM (MRI-A16). Every\n   * request it builds carries `x-organization-id`; a request built any other\n   * way is refused by the org-admission middleware with 400\n   * `organization_required`, and `core/api.test.ts` fails the build if a second\n   * way appears. Playing a recording — `GET /files/{id}/download` — goes\n   * through here too, which is the defect this replaced.\n   */\n  readonly api: MeetApi;\n  readonly identity: MeetIdentity;\n  readonly baseUrl: string;\n  /**\n   * The host's session source, as handed to `<MeetProvider>`. Exposed for the\n   * host's own diagnostics; package code reaches aidream through `api`.\n   */\n  readonly accessToken: AccessTokenSource;\n  readonly report: (event: MeetDiagnostic) => void;\n}\n\n// 🚨 ONE CONTEXT ACROSS ENTRIES (S1). `/react` and `/skins/meet` are separate\n// bundles (`splitting: false`), so each carries its own copy of this module. A\n// module-level `createContext` would give the skin's parts a DIFFERENT context\n// than the `<MeetProvider>` above them, and every part would read \"no host\".\n// The context lives in the globalThis slot, like every process-global (rule 4).\nconst MeetContext = MeetHostContext;\n\nexport interface MeetProviderProps {\n  /**\n   * Any Supabase client. `null` while the host is still resolving one.\n   *\n   * 🚨 DELIBERATELY THE SHALLOW SHAPE (0.2.1) — pass the\n   * `SupabaseClient<Database>` you already have, with no cast. The rich\n   * internal contract sent tsc into `TS2589` for any host with generated\n   * Supabase types; see `core/repository.ts`'s header for the whole story.\n   */\n  client: MessagingSupabaseClient | null | undefined;\n  /** aidream's base URL. LiveKit credentials live THERE, never here. */\n  baseUrl: string;\n  /**\n   * A guest's typed name — and the ONE way to declare the guest lane (D6).\n   * With it, this mount is a link-follower's room: no session is read, no\n   * calling surface is built, and nothing user-scoped is ever issued. Without\n   * it, the acting user is whoever `client`'s session says it is.\n   *\n   * 🚨 There is NO `userId` prop. See this file's header and\n   * `../core/session-identity.ts`.\n   */\n  guestName?: string | null | undefined;\n  organizationId: string | null | undefined;\n  displayName?: string | undefined;\n  avatarUrl?: string | null | undefined;\n  /** The bearer token source for aidream calls. */\n  accessToken: AccessTokenSource;\n  /** Swap the media driver. Defaults to LiveKit — there is no reason to. */\n  driverFactory?: RoomDriverFactory | undefined;\n  /** A call is ringing this device — for a sound, a toast, or a badge. */\n  onIncomingCall?: ((invite: CallInvite) => void) | undefined;\n  onDiagnostic?: ((event: MeetDiagnostic) => void) | undefined;\n  ringTimeoutMs?: number | undefined;\n  children: ReactNode;\n}\n\nfunction defaultDiagnostics(event: MeetDiagnostic): void {\n  const line = `[@ai-matrx/meet] ${event.message}${\n    event.remedy !== undefined ? `\\n  → ${event.remedy}` : \"\"\n  }`;\n  if (event.level === \"error\") console.error(line);\n  else if (event.level === \"warn\") console.warn(line);\n  else console.info(line);\n}\n\nlet claimedTab: TabClaim | null = null;\n/** S7: ONE tab claim per page (`core/tab-claim.ts`), shared by every provider on it. */\nfunction pageTabClaim(): TabClaim | undefined {\n  if (typeof window === \"undefined\") return undefined;\n  claimedTab ??= createTabClaim();\n  return claimedTab;\n}\n\n/** A stable per-device id, so a reconnect keeps ONE LiveKit identity. */\nfunction deviceId(): string {\n  const storage = (globalThis as { localStorage?: Storage }).localStorage;\n  const key = \"mx.meet.device\";\n  try {\n    const existing = storage?.getItem(key);\n    if (existing !== null && existing !== undefined && existing.length > 0) return existing;\n    const created = Math.random().toString(36).slice(2, 14);\n    storage?.setItem(key, created);\n    return created;\n  } catch {\n    return Math.random().toString(36).slice(2, 14);\n  }\n}\n\n/**\n * THE ONE SESSION READ. Subscribed per client, torn down with it, and honest\n * about the `resolving` window in between — see `../core/session-identity.ts`\n * for the class this closes.\n *\n * `client === null` (the guest lane, or a host still resolving one) never opens\n * a subscription at all: a link-follower has no account to read.\n */\nfunction useSessionIdentity(\n  client: MessagingSupabaseClient | null | undefined,\n  report: (event: MeetDiagnostic) => void,\n): SessionIdentitySnapshot {\n  const [snapshot, setSnapshot] = useState<SessionIdentitySnapshot>(SERVER_SESSION_IDENTITY);\n\n  useEffect(() => {\n    if (client == null) {\n      setSnapshot(SERVER_SESSION_IDENTITY);\n      return undefined;\n    }\n    const identity = createSessionIdentity({ client, onDiagnostic: report });\n    setSnapshot(identity.snapshot());\n    const unsubscribe = identity.subscribe(() => setSnapshot(identity.snapshot()));\n    return () => {\n      unsubscribe();\n      identity.dispose();\n    };\n  }, [client, report]);\n\n  return snapshot;\n}\n\n/** A guest lane is declared by a NON-EMPTY typed name, and by nothing else. */\nfunction guestLaneName(guestName: string | null | undefined): string | null {\n  return typeof guestName === \"string\" && guestName.trim().length > 0 ? guestName : null;\n}\n\nexport function MeetProvider(props: MeetProviderProps): ReactNode {\n  const { client } = props;\n\n  // Live ref so a host's fresh function literal per render never becomes part\n  // of anything's lifetime, while callbacks still see the CURRENT one.\n  const diagnosticRef = useRef(props.onDiagnostic);\n  diagnosticRef.current = props.onDiagnostic;\n  const report = useCallback((event: MeetDiagnostic): void => {\n    (diagnosticRef.current ?? defaultDiagnostics)(event);\n  }, []);\n\n  // 🚨 NOTHING FAILS SILENTLY. A host still passing the 0.5.x `userId` prop —\n  // a stale bundle, a JS consumer tsc never checked — is told, once, that it is\n  // ignored and why. Silently dropping it would look exactly like the bug.\n  const legacyUserIdReported = useRef(false);\n  const legacyUserId = (props as { userId?: unknown }).userId;\n  useEffect(() => {\n    if (legacyUserId === undefined || legacyUserId === null) return;\n    if (legacyUserIdReported.current) return;\n    legacyUserIdReported.current = true;\n    report({\n      level: \"error\",\n      message:\n        \"<MeetProvider userId> is ignored: since 0.6.0 Meet reads the acting user from the \" +\n        \"Supabase client's own session.\",\n      remedy:\n        \"Delete the userId prop. Passing a copy of the user id is what let a tab whose auth \" +\n        \"cookie had rotated issue reads as an account it could no longer prove it was — the \" +\n        \"database refused them at 403 (DD-240).\",\n    });\n  }, [legacyUserId, report]);\n\n  const guestName = guestLaneName(props.guestName);\n  // The guest lane reads no session; the member lane reads nothing else.\n  const session = useSessionIdentity(guestName === null ? client : null, report);\n  const actingUserId = guestName === null ? session.userId : null;\n\n  // 🚨 RIDE THE HOST'S REALTIME MANAGER WHEN THERE IS ONE (0.6.5).\n  //\n  // Through 0.6.4 this ALWAYS mounted a provider of its own, with `client={null}`\n  // until an organization was selected. That shadowed the host's manager for\n  // everything below Meet: a sibling that rides a mounted host provider (as\n  // `@ai-matrx/messaging` does) read a NULL manager forever when no org was\n  // selected — `/messages` spun and a thread showed \"0 members\" — and with an\n  // org selected it got a SECOND manager (two sockets, two write ledgers).\n  // The probe is provider PRESENCE (`@ai-matrx/data/realtime` 0.3.0), never\n  // `useRealtimeManager() !== null`, which is also null while a mounted host\n  // provider waits for its client.\n  //\n  // And the realtime connection never waits on the organization: a socket is\n  // the PERSON's (access belongs to the person, 2026-09-23). Whether Meet's own\n  // runtime needs an org is MeetRuntime's question, not the transport's.\n  const hostProvidesRealtime = useIsRealtimeProviderMounted();\n  const runtime = (\n    <MeetRuntime\n      {...props}\n      report={report}\n      actingUserId={actingUserId}\n      guestLaneName={guestName}\n      sessionResolved={guestName !== null || session.state === \"resolved\"}\n    />\n  );\n  if (hostProvidesRealtime) return runtime;\n  return (\n    <RealtimeProvider\n      client={client != null ? (client as never) : null}\n      actorId={actingUserId ?? undefined}\n    >\n      {runtime}\n    </RealtimeProvider>\n  );\n}\n\ninterface MeetRuntimeProps extends MeetProviderProps {\n  readonly report: (event: MeetDiagnostic) => void;\n  /** Who the SESSION says is acting. Never a prop from outside the package. */\n  readonly actingUserId: UserId | null;\n  readonly guestLaneName: string | null;\n  readonly sessionResolved: boolean;\n}\n\nfunction MeetRuntime(props: MeetRuntimeProps): ReactNode {\n  const { client, actingUserId, guestLaneName: guestName, organizationId, baseUrl, children } =\n    props;\n  const report = props.report;\n  const manager = useRealtimeManager();\n\n  // Live refs so callbacks always see the CURRENT render's functions without\n  // those functions' identities being part of the runtime's lifetime.\n  const incomingRef = useRef(props.onIncomingCall);\n  incomingRef.current = props.onIncomingCall;\n  const accessTokenRef = useRef(props.accessToken);\n  accessTokenRef.current = props.accessToken;\n  const driverRef = useRef(props.driverFactory);\n  driverRef.current = props.driverFactory;\n\n  const displayName =\n    props.displayName ?? (typeof guestName === \"string\" ? guestName : \"Guest\");\n\n  // 🚨 INERT UNTIL THE SESSION HAS ANSWERED. A runtime built during the\n  // `resolving` window would issue its first `pendingInvites` read on behalf of\n  // a guess; the whole point of DD-240 is that there is no guess.\n  const ready =\n    client != null &&\n    manager !== null &&\n    typeof organizationId === \"string\" &&\n    organizationId.length > 0 &&\n    props.sessionResolved &&\n    (guestName !== null || actingUserId !== null);\n\n  const host = useMemo<MeetHost | null>(() => {\n    if (!ready || manager === null || client == null) return null;\n\n    const identity: MeetIdentity = {\n      // THE SESSION'S ANSWER, never a prop (DD-240).\n      userId: actingUserId,\n      organizationId: asOrganizationId(organizationId as string),\n      displayName,\n      avatarUrl: props.avatarUrl ?? null,\n      deviceId: deviceId(),\n    };\n\n    const effectsStorage = createWebEffectsStorage();\n    // Seeded BEFORE the room: the pre-join screen shows (and previews) the\n    // remembered choice, and the engine applies the same one on connect.\n    const store = createMeetStore({ effects: effectsStorage.load() });\n    const devicesHolder: { current: DeviceManager | null } = { current: null };\n    const api = createMeetApi({\n      baseUrl,\n      organizationId: identity.organizationId,\n      accessToken: (...args) => accessTokenRef.current(...args),\n    });\n    const repository = createMeetRepository({ client });\n    // MRF-1: a GUEST's pass is kept on this device so the durable link still\n    // opens the record after the meeting — `/token` will not mint another one\n    // for a finished meeting, correctly, and a guest has no session to prove\n    // they were here with. `createTokenClient` stores only guest passes.\n    const tokens = createTokenClient({\n      api,\n      storage: createWebRoomTokenStorage((message, remedy) =>\n        report({ level: \"warn\", message, remedy }),\n      ),\n    });\n    const engine = createRoomEngine({\n      store,\n      tokens,\n      identity,\n      // S7: this page's tab id (one per page, claimed at load) — the LiveKit identity's tab half.\n      tabClaim: pageTabClaim(),\n      resolveMeeting: (slug) => repository.meetingBySlug(slug),\n      driverFactory: (handlers) =>\n        (driverRef.current ?? createLiveKitDriver)(handlers),\n      onDiagnostic: report,\n      effectsStorage,\n      resolveDevice: (kind) => devicesHolder.current?.resolve(kind) ?? null,\n      // §3.4: on every LiveKit disconnect, ask the server what happened to this connection.\n      readExit: (connection, pass) => meetings.readExit(connection, pass),\n      // S6b: the connection supervisor's ports — the device's network, whether OUR servers (the\n      // API and the media server) answer, and the per-tab reload-after-offline marker.\n      connection: {\n        network: createWebNetworkPort(),\n        resume: createWebResumeStorage(),\n        probe: (serverUrl) =>\n          createReachabilityProbe(() => [baseUrl, ...(serverUrl !== null ? [httpUrlOf(serverUrl)] : [])])(),\n      },\n    });\n    const meetings = createMeetingSession({\n      manager,\n      repository,\n      store,\n      identity,\n      api,\n      onDiagnostic: report,\n      // ADMISSION IS A JOIN, NOT A RE-RENDER. The lobby token grants neither\n      // publish nor subscribe, so the host saying yes has to mint a new one. The\n      // \"yes\" is read from the server (the state read), never a broadcast (S4).\n      onAdmitted: () => {\n        void engine.rejoin().catch(() => undefined);\n      },\n      rejoin: () => engine.rejoin(),\n      // THE MEETING PASS this device holds — what the state read and `/leave` carry.\n      resolvePass: () => {\n        const roomName = store.snapshot().meeting?.roomName;\n        const active = engine.token();\n        if (active?.meetingPass) return active.meetingPass;\n        return roomName === undefined ? null : (tokens.remembered(roomName)?.meetingPass ?? null);\n      },\n    });\n    // THE AI IS PART OF THE RUNTIME, not an optional attachment. Nothing here\n    // names an agent: every capability is a server-owned Mandate (D2).\n    const resolveRoomToken = (): string | null => {\n      const roomName = store.snapshot().meeting?.roomName;\n      if (roomName === undefined) return null;\n      const active = engine.token();\n      // THE MEETING PASS, never the LiveKit token (CORE-DESIGN §2.5): `x-meet-pass`.\n      if (active?.roomName === roomName && active.meetingPass) return active.meetingPass;\n      return tokens.remembered(roomName)?.meetingPass ?? null;\n    };\n    const ai = createMeetAi({ api, store, resolveRoomToken });\n    const inRoom = createInRoomClient({ api, store, resolveRoomToken });\n    // THE SAVED CHAT IS READ ON EVERY JOIN (Meet wave 2) — that is what makes a\n    // late joiner see what was already said. Once per connected room; a refusal\n    // is a diagnostic with a remedy, and live messages keep arriving regardless.\n    // S4: THE WAIT READS SERVER TRUTH while (and only while) this tab is in the waiting room.\n    store.subscribe(() => {\n      const snapshot = store.snapshot();\n      if (isWaitingPhase(snapshot.phase) && snapshot.waiting !== null &&\n          (snapshot.waiting.admission === \"knocking\" || snapshot.waiting.admission === \"waiting_host\")) {\n        meetings.startWaiting();\n      } else if (!isWaitingPhase(snapshot.phase)) {\n        meetings.stopWaiting();\n      }\n    });\n    let chatReadFor: string | null = null;\n    store.subscribe(() => {\n      const snapshot = store.snapshot();\n      if (snapshot.phase !== \"in_call\" || snapshot.meeting === null) {\n        if (snapshot.phase === \"left\" || snapshot.phase === \"prejoin\" || snapshot.phase === \"resolving\") chatReadFor = null;\n        return;\n      }\n      if (chatReadFor === snapshot.meeting.id) return;\n      chatReadFor = snapshot.meeting.id;\n      // Meet wave 5: polls, questions, the whiteboard and an open breakout plan — read\n      // on the same once-per-join moment, so a late joiner sees them all. A refusal is\n      // written to `collab.error` by the client and reported here.\n      void inRoom.loadCollab().catch((error: unknown) => {\n        const normalized = error as { message?: string; remedy?: string };\n        report({\n          level: \"warn\",\n          message: normalized.message ?? \"meet: polls, questions and the whiteboard could not be read\",\n          ...(normalized.remedy !== undefined ? { remedy: normalized.remedy } : {}),\n        });\n      });\n      void inRoom.loadChat().catch((error: unknown) => {\n        const normalized = error as { message?: string; remedy?: string };\n        // NEVER \"Reading…\" FOREVER: the panel says history is unavailable, and why.\n        store.patch({\n          chatLoaded: true,\n          chatHistoryError:\n            normalized.remedy ?? \"Messages sent before you joined could not be read. New messages still arrive.\",\n        });\n        report({\n          level: \"warn\",\n          message: normalized.message ?? \"meet: the saved chat could not be read\",\n          ...(normalized.remedy !== undefined ? { remedy: normalized.remedy } : {}),\n        });\n      });\n    });\n    const recording = createRecordingController({\n      api,\n      store,\n      acknowledgeConsent: async (meetingId) => {\n        await repository.recordConsent({\n          meetingId,\n          identity: store.snapshot().localIdentity ?? identity.deviceId,\n          acknowledgedAt: new Date().toISOString(),\n        });\n      },\n    });\n    const devices = createDeviceManager({\n      media: (globalThis as unknown as { navigator?: { mediaDevices?: MediaDevicesLike } })\n        .navigator?.mediaDevices ?? {\n        // An SSR render or a browser without media devices gets an INERT\n        // manager that reports the truth, rather than a crash on import.\n        enumerateDevices: async () => [],\n        getUserMedia: async () => ({ getTracks: () => [] }),\n      },\n      storage: createWebDeviceStorage(),\n    });\n    devicesHolder.current = devices;\n    // A GUEST HAS NO CALLING SURFACE. Not \"a disabled one\" — none at all, so\n    // there is nothing to render as a dead button (D6, no dead ends).\n    const calls =\n      identity.userId === null\n        ? null\n        : createCallCenter({\n            manager,\n            repository,\n            store,\n            identity,\n            onIncoming: (invite) => incomingRef.current?.(invite),\n            // §3.6: my call was answered — the caller joins the call's room on the same machine.\n            onAnswered: (invite) => {\n              void engine.join({ roomName: invite.roomName, mode: invite.mode }).catch(() => undefined);\n            },\n            onDiagnostic: report,\n            ...(props.ringTimeoutMs !== undefined ? { ringTimeoutMs: props.ringTimeoutMs } : {}),\n          });\n\n    return {\n      store,\n      engine,\n      calls,\n      meetings,\n      inRoom,\n      recording,\n      devices,\n      repository,\n      tokens,\n      ai,\n      api,\n      identity,\n      baseUrl,\n      accessToken: (...args) => accessTokenRef.current(...args),\n      report,\n    };\n    // 🚨 IDENTITY ONLY. See the header: adding callbacks or option objects here\n    // rebuilds every channel — and drops the call in progress — on every render.\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [\n    ready,\n    manager,\n    client,\n    actingUserId,\n    guestName,\n    organizationId,\n    baseUrl,\n    displayName,\n    report,\n  ]);\n\n  useEffect(() => {\n    if (host?.calls == null) return undefined;\n    const center = host.calls;\n    void center.start().catch((error: unknown) => {\n      host.report({\n        level: \"error\",\n        message: `Meet could not start listening for calls: ${String(\n          (error as Error)?.message ?? error,\n        )}`,\n        remedy:\n          \"Calls will not ring on this device until this succeeds. Check the session and \" +\n          \"organization, then reload the surface.\",\n      });\n    });\n    return () => {\n      center.dispose();\n    };\n  }, [host]);\n\n  useEffect(() => {\n    if (host === null) return undefined;\n    return () => {\n      host.meetings.dispose();\n      host.devices.dispose();\n      void host.engine.dispose();\n    };\n  }, [host]);\n\n  return <MeetContext.Provider value={host}>{children}</MeetContext.Provider>;\n}\n\n/** The host, or `null` while auth/org are still resolving. */\nexport function useMeetHost(): MeetHost | null {\n  return useContext(MeetContext);\n}\n\nexport function useRequiredMeetHost(): MeetHost {\n  const host = useMeetHost();\n  if (host === null) {\n    throw new Error(\n      \"[@ai-matrx/meet] No meet host. Wrap this tree in <MeetProvider client={supabase} \" +\n        \"baseUrl={aidreamUrl} organizationId={orgId} accessToken={fn}> and render it only \" +\n        \"once auth has resolved.\",\n    );\n  }\n  return host;\n}\n\n/** The whole room snapshot, re-rendering only when it actually changes. */\nexport function useMeetSnapshot(): MeetSnapshot | null {\n  const host = useMeetHost();\n  const store = host?.store ?? null;\n  const empty = useRef<MeetSnapshot | null>(null);\n  return useSyncExternalStore(\n    (listener) => (store === null ? () => undefined : store.subscribe(listener)),\n    () => (store === null ? empty.current : store.snapshot()),\n    () => (store === null ? empty.current : store.snapshot()),\n  );\n}\n\nexport function useDeviceSnapshot(): DeviceSnapshot | null {\n  const host = useMeetHost();\n  const devices = host?.devices ?? null;\n  return useSyncExternalStore(\n    (listener) => (devices === null ? () => undefined : devices.subscribe(() => listener())),\n    () => devices?.snapshot() ?? null,\n    () => devices?.snapshot() ?? null,\n  );\n}\n\n/**\n * 🚨 THE LOCAL PARTICIPANT'S ROLE — THE SERVER'S WORD, FROM BOTH ITS CARRIERS\n * (MRI-A11, feedback `7418ef78`).\n *\n * Two sources, one decision made once in `services/meet/service.py`:\n *\n * 1. `snapshot.grants.role` — the `/meet/token` response, in the store from the\n *    instant the token lands, which is BEFORE any LiveKit roster exists.\n * 2. the local participant's roster entry, whose role comes from the\n *    `matrx.participant.role` LiveKit attribute the same mint published.\n *\n * The stronger of the two wins, and both are server-minted, so this can never\n * be client state: there is no branch here a browser could take on its own.\n * Reading only (2) is the shipped defect this replaces — a roster entry arrives\n * a beat later than the token and, before MRI-A11, carried no role at all.\n */\nexport function useRole(): ParticipantRole {\n  const snapshot = useMeetSnapshot();\n  // ONE definition, shared with the code that PERFORMS the host actions\n  // (`core/store.ts`). A second copy here is how the UI and the action drift.\n  return snapshot === null ? \"participant\" : effectiveRole(snapshot);\n}\n\n/** Does the local participant hold host powers? ONE predicate, one definition. */\nexport function useIsHost(): boolean {\n  return isHostRole(useRole());\n}\n\n/**\n * May the local participant start a recording? NOT `isHost` — the meeting's\n * recording policy is the server's, and an `always-on` meeting is recorded by\n * the server with no host control at all (MRI-A11).\n */\nexport function useCanRecord(): boolean {\n  const snapshot = useMeetSnapshot();\n  if (snapshot === null) return false;\n  const me = snapshot.participants.find(\n    (participant) => participant.identity === snapshot.localIdentity,\n  );\n  return snapshot.grants.canRecord || me?.canRecord === true;\n}\n\nexport function useLocalUserId(): UserId | null {\n  return useMeetHost()?.identity.userId ?? null;\n}\n","/**\n * AI-NATIVE, ON BY DEFAULT — and SERVER-OWNED as of 0.3.0 (R4, D2, D16).\n *\n * 🚨 **THE PACKAGE NO LONGER KNOWS WHO ANSWERS.** Through 0.2.1 a host injected\n * `MeetAgents` — four database row ids — and this module ran the agent itself,\n * shipping the transcript up as `variables`. Both halves of that are gone:\n *\n * 1. **No agent id crosses this boundary, and none is injected.** Reasoning runs\n *    behind Mandates whose Holder is resolved from the database at run time\n *    (`meet.live_notes`, `meet.live_intelligence`, `meet.wrap_up`), so an\n *    organization rebinds the job in the Mandate admin with no release of this\n *    package and no change in the host. A host that had to supply an id was a\n *    host that could supply the WRONG id, and a capability that silently\n *    disappeared when nobody had filled a config line.\n * 2. **No transcript crosses this boundary either.** `POST /v1/meet/intelligence/ask`\n *    takes `{meeting_id, question}` and NOTHING else; the answer is built\n *    server-side from durable rows. Captions are hints and this client holds\n *    only hints (D16) — sending them would be sending the model our guesses.\n *\n * What is left here is small and honest: ask a question and render the answer\n * as it streams, summon or dismiss the note-taker, end the meeting for\n * everyone, and report the server's refusal in the server's own words.\n *\n * 🚨 **THE USER-INPUT LAW still holds** and is now the server's to keep:\n * `question` is the one genuine human utterance in this module, and it is the\n * only free text this package sends anywhere near a model.\n */\n\nimport { readMatrxNdjsonStream } from \"@ai-matrx/api/stream\";\nimport type { MeetApi } from \"./api\";\nimport { MeetError, SERVER_FAILED_SENTENCE, isRawServerText } from \"./errors\";\nimport type { NoteTakerRefusal } from \"./note-taker\";\nimport type { MeetStore } from \"./store\";\nimport { MEET_ROUTES, MEETING_PASS_HEADER } from \"./tokens\";\nimport type { MeetingId, RoomName } from \"./types\";\n\nexport interface MeetAiOptions {\n  /** The ONE org-aware aidream client (MRI-A16). Owns base url and headers. */\n  api: MeetApi;\n  store: MeetStore;\n  /**\n   * Resolves the current meeting's room pass for a guest Q&A request. The\n   * provider owns this because it alone has both the active room and its\n   * persisted guest pass. `null` leaves the header absent for signed-in record\n   * Q&A, where the session remains the credential.\n   */\n  resolveRoomToken?: (() => string | null) | undefined;\n}\n\n/** What the answer was built from. The server measures it; we never guess it. */\nexport interface MeetAnswerCoverage {\n  readonly segmentsUsed: number;\n  readonly segmentsTotal: number;\n  readonly truncated: boolean;\n  readonly speakers: readonly string[];\n}\n\nexport interface MeetAiAnswer {\n  readonly text: string;\n  readonly coverage: MeetAnswerCoverage | null;\n}\n\nexport interface AskArgs {\n  readonly meetingId: MeetingId;\n  readonly question: string;\n  readonly signal?: AbortSignal | undefined;\n  /** Called with the answer so far, every time it grows. Rendering is live. */\n  readonly onText?: ((text: string) => void) | undefined;\n  /** The server's phase, verbatim, so a slow answer is never a bare spinner. */\n  readonly onPhase?: ((phase: string) => void) | undefined;\n}\n\nexport interface NoteTakerDispatch {\n  readonly dispatched: boolean;\n  /** The server's sentence. Never empty on a refusal. */\n  readonly detail: string;\n}\n\nexport interface MeetAi {\n  /** In-meeting Q&A. The ONE human utterance this package sends (D16). */\n  ask(args: AskArgs): Promise<MeetAiAnswer>;\n  /** Ask aidream to dispatch the note-taker INTO the room. Host-only. */\n  startNoteTaker(args: { meetingId: MeetingId; roomName: RoomName }): Promise<NoteTakerDispatch>;\n  /**\n   * Make sure the note-taker (the speech-to-text) is in the room because THIS viewer turned\n   * captions on. Open to everyone in the meeting, guests included. Never throws: a refusal\n   * is stored as `captionsRefusal` in the server's own words.\n   */\n  requestCaptions(args: { meetingId: MeetingId }): Promise<void>;\n  /** Dismiss it. Nothing automatic brings a dismissed note-taker back (D9). */\n  stopNoteTaker(args: { meetingId: MeetingId }): Promise<NoteTakerDispatch>;\n}\n\n/** The event vocabulary `/intelligence/ask` emits, pinned by the server's FEATURE.md. */\nexport const MEET_ANSWER_EVENTS = {\n  chunk: \"chunk\",\n  info: \"info\",\n  phase: \"phase\",\n  error: \"error\",\n  end: \"end\",\n} as const;\n\n/** The `info` event carrying what the answer was built from. */\nexport const MEET_ANSWER_CONTEXT_EVENT = \"meet_intelligence_context\";\n\n/**\n * The coverage numbers, wherever the canonical emitter put them.\n *\n * 🚨 THE LIVE WIRE NESTS THEM UNDER `metadata`. `InfoPayload` is\n * `{code, system_message, user_message, metadata}`, so the numbers arrive at\n * `data.metadata.segments_used` — not at `data.segments_used`, which is what\n * this function read until it was walked against the real route on 2026-09-08\n * and quietly reported no coverage at all. Every shape is read now, and the\n * fixture in `ai.test.ts` is a VERBATIM line off the production stream.\n */\nfunction readCoverage(data: unknown): MeetAnswerCoverage | null {\n  if (typeof data !== \"object\" || data === null) return null;\n  const row = data as Record<string, unknown>;\n  const candidates: Record<string, unknown>[] = [row];\n  for (const key of [\"metadata\", \"data\"]) {\n    const nested = row[key];\n    if (typeof nested === \"object\" && nested !== null && !Array.isArray(nested)) {\n      candidates.push(nested as Record<string, unknown>);\n    }\n  }\n  const source =\n    candidates.find(\n      (entry) =>\n        typeof entry[\"segments_used\"] === \"number\" ||\n        typeof entry[\"segments_total\"] === \"number\",\n    ) ?? null;\n  if (source === null) return null;\n  const used = source[\"segments_used\"];\n  const total = source[\"segments_total\"];\n  const speakers = source[\"speakers\"];\n  return {\n    segmentsUsed: typeof used === \"number\" ? used : 0,\n    segmentsTotal: typeof total === \"number\" ? total : 0,\n    truncated: source[\"transcript_truncated\"] === true,\n    speakers: Array.isArray(speakers)\n      ? speakers.filter((entry): entry is string => typeof entry === \"string\")\n      : [],\n  };\n}\n\nfunction readText(data: unknown): string {\n  if (typeof data === \"string\") return data;\n  if (typeof data !== \"object\" || data === null) return \"\";\n  const row = data as Record<string, unknown>;\n  // `phase` and `system_message` are on this list because the live emitter\n  // sends `{\"phase\":\"generating\"}` and `{\"system_message\":\"Reading the meeting\n  // transcript\"}`. Without them a phase rendered as \"[object Object]\" —\n  // found by walking the real route, not by any test written from the docs.\n  for (const key of [\"text\", \"content\", \"delta\", \"t\", \"phase\", \"system_message\"]) {\n    const value = row[key];\n    if (typeof value === \"string\") return value;\n  }\n  return \"\";\n}\n\nexport { SERVER_FAILED_SENTENCE, isRawServerText } from \"./errors\";\n\n/**\n * THE ONE REFUSAL → MeetError (0.7.8). A non-OK aidream response becomes an\n * error whose `message` is the server's sentence for a PERSON and whose\n * `remedy` is the server's remedy (or the caller's fallback) — never the\n * operation name, a status code alone, or an exception class. Every door that\n * calls aidream builds its refusal here, so no door can drift back.\n */\nexport async function refusalFromResponse(\n  response: Response,\n  operation: string,\n  fallbackRemedy: string,\n): Promise<MeetError> {\n  let body: unknown = null;\n  try {\n    body = await response.json();\n  } catch {\n    body = null;\n  }\n  const said = readRefusalBody(body);\n  const code =\n    response.status === 403 || response.status === 401\n      ? \"forbidden\"\n      : response.status === 404\n        ? \"not-found\"\n        : response.status === 409\n          ? \"conflict\"\n          : \"transport\";\n  const error = new MeetError(\n    code,\n    said?.reason ?? SERVER_FAILED_SENTENCE,\n    said !== null && said.remedy.length > 0 ? said.remedy : fallbackRemedy,\n  );\n  (error as { operation?: string; status?: number }).operation = operation;\n  (error as { operation?: string; status?: number }).status = response.status;\n  return error;\n}\n\ninterface ServerRefusal {\n  readonly reason: string;\n  readonly remedy: string;\n}\n\n/**\n * THE SERVER'S REFUSAL, READ RATHER THAN RE-WRITTEN.\n *\n * aidream answers a refused dispatch with a body carrying its own `reason` and\n * `remedy` — \"no worker is registered under matrx-note-taker\", and what to do\n * about it. FastAPI nests a raised `HTTPException` under `detail`, and a\n * validation failure produces a list. All three shapes are read here so the\n * screen shows the system's own words instead of \"something went wrong\".\n */\nexport function readRefusalBody(body: unknown): ServerRefusal | null {\n  if (typeof body === \"string\") {\n    return body.trim().length === 0 ? null : { reason: body.trim(), remedy: \"\" };\n  }\n  if (typeof body !== \"object\" || body === null) return null;\n  const row = body as Record<string, unknown>;\n  const detail = row[\"detail\"];\n  if (Array.isArray(detail)) {\n    // FastAPI's validation shape: `{msg, loc}`. The FIELD is in `loc` and the\n    // field is the whole point — \"Field required\" alone names nothing.\n    const messages = detail\n      .map((entry) => {\n        if (typeof entry !== \"object\" || entry === null) return String(entry);\n        const row = entry as Record<string, unknown>;\n        const message = String(row[\"msg\"] ?? \"\");\n        const where = Array.isArray(row[\"loc\"])\n          ? row[\"loc\"].filter((part): part is string => typeof part === \"string\").join(\".\")\n          : \"\";\n        return where.length > 0 ? `${message} (${where})` : message;\n      })\n      .filter((entry) => entry.length > 0);\n    return messages.length === 0 ? null : { reason: messages.join(\"; \"), remedy: \"\" };\n  }\n  if (typeof detail === \"object\" && detail !== null) return readRefusalBody(detail);\n  // 🚨 NEVER A CLASS NAME. aidream's crash body is `message: \"Internal server\n  // error: UnsupportedClientFeatureError\"` beside `user_message` for a person;\n  // through 0.7.7 this read `message` whatever it said, so a crash reached a\n  // host's toast as a Python class name (verifier, 2026-09-27). A raw message\n  // now falls through to `user_message`. A HUMAN `message` still wins: Meet's\n  // own sentences carry the specific reason and its \"Fix:\", which a generic\n  // `user_message` wrapper would bury.\n  const humanOrNull = (value: unknown): string | null =>\n    typeof value === \"string\" && value.trim().length > 0 && !isRawServerText(value)\n      ? value.trim()\n      : null;\n  const reason =\n    humanOrNull(row[\"reason\"]) ??\n    humanOrNull(row[\"message\"]) ??\n    humanOrNull(row[\"user_message\"]) ??\n    (typeof detail === \"string\" ? humanOrNull(detail) : null) ??\n    (typeof row[\"message\"] === \"string\" ||\n    typeof row[\"error\"] === \"string\" ||\n    typeof detail === \"string\"\n      ? SERVER_FAILED_SENTENCE\n      : null);\n  if (reason === null) return null;\n  const remedy = typeof row[\"remedy\"] === \"string\" ? row[\"remedy\"] : \"\";\n  if (remedy.length > 0) return { reason, remedy };\n  // THE SERVER WRITES ITS REMEDY INLINE. Meet's own errors read\n  // \"<what happened>. Fix: <what to do>.\" — splitting it here is what puts the\n  // fix on its own line in the panel instead of burying it mid-paragraph.\n  const fix = reason.indexOf(\"Fix:\");\n  if (fix > 0) {\n    return {\n      reason: reason.slice(0, fix).trim(),\n      remedy: reason.slice(fix + \"Fix:\".length).trim(),\n    };\n  }\n  return { reason, remedy };\n}\n\nexport function createMeetAi(options: MeetAiOptions): MeetAi {\n  /**\n   * Every request here goes through the ONE org-aware client (MRI-A16), which\n   * puts `x-organization-id` on it — the 0.1.3 lesson, now structural rather\n   * than remembered. A refused session is translated into THIS surface's own\n   * sentence, because \"sign in\" means something specific for the note-taker.\n   */\n  async function send(input: {\n    path: string;\n    body: Record<string, unknown>;\n    operation: string;\n    requireAuth: boolean;\n    headers?: Record<string, string> | undefined;\n    signal?: AbortSignal | undefined;\n  }): Promise<Response> {\n    try {\n      return await options.api.request({\n        path: input.path,\n        method: \"POST\",\n        requireAuth: input.requireAuth,\n        operation: input.operation,\n        body: input.body,\n        ...(input.headers !== undefined ? { headers: input.headers } : {}),\n        ...(input.signal !== undefined ? { signal: input.signal } : {}),\n      });\n    } catch (error) {\n      if ((error as { code?: string }).code === \"session-unavailable\") {\n        throw new MeetError(\n          \"forbidden\",\n          `${input.operation}: this action needs a signed-in host`,\n          \"A guest cannot summon or dismiss the note-taker, and the control is hidden for \" +\n            \"them. Sign in as the meeting's host to use it.\",\n        );\n      }\n      throw error;\n    }\n  }\n\n  async function refusalFor(response: Response, operation: string): Promise<NoteTakerRefusal> {\n    let body: unknown = null;\n    try {\n      body = await response.json();\n    } catch {\n      try {\n        body = await response.text();\n      } catch {\n        body = null;\n      }\n    }\n    const parsed = readRefusalBody(body);\n    // 🚨 A NAMED SERVER GAP, ANNOUNCED RATHER THAN PAPERED OVER. 0.3.0 stopped\n    // sending `agent_id` because which agent transcribes is the server's\n    // business (D2), but aidream's `NoteTakerStartRequest` still DECLARES that\n    // field, so a server that has not landed the MRI-A2 side answers FastAPI's\n    // validation error — which reads like a client bug to the person clicking.\n    // This translates it into what is actually true. It never invents an id.\n    if (response.status === 422 && (parsed?.reason ?? \"\").includes(\"agent_id\")) {\n      return {\n        status: 422,\n        reason:\n          \"This server still expects the caller to name the note-taker agent, and this \" +\n          \"version of @ai-matrx/meet deliberately does not.\",\n        remedy:\n          \"The note-taker's identity is a Mandate binding the server resolves (D2). Update \" +\n          \"aidream so `/v1/meet/agent/start` resolves the agent itself — register item \" +\n          \"MRI-A2/A6. Until then the note-taker cannot be summoned from this surface, and \" +\n          \"nothing about this meeting is being transcribed.\",\n      };\n    }\n    return {\n      status: response.status,\n      reason:\n        parsed?.reason ??\n        `${operation}: the server answered ${response.status} with no reason.`,\n      remedy:\n        parsed?.remedy !== undefined && parsed.remedy.length > 0\n          ? parsed.remedy\n          : \"The server refused and said nothing more. The meeting continues WITHOUT the \" +\n            \"note-taker and this surface says so — a silent failure here is a meeting \" +\n            \"everyone believes is being minuted.\",\n    };\n  }\n\n  async function dispatch(\n    route: string,\n    body: Record<string, unknown>,\n    operation: string,\n  ): Promise<NoteTakerDispatch> {\n    // The session check happens BEFORE the request, so a guest's refusal is a\n    // package sentence rather than a round trip the server would reject anyway.\n    const response = await send({ path: route, body, operation, requireAuth: true });\n    if (!response.ok) {\n      const refusal = await refusalFor(response, operation);\n      // THE REFUSAL IS STATE, not only an exception: every surface renders the\n      // server's sentence until the next attempt, rather than a control that\n      // looks like it did nothing.\n      options.store.patch({ noteTakerRefusal: refusal });\n      throw new MeetError(\n        response.status === 403 ? \"forbidden\" : \"transport\",\n        refusal.reason,\n        refusal.remedy,\n      );\n    }\n    options.store.patch({ noteTakerRefusal: null });\n    let payload: unknown = null;\n    try {\n      payload = await response.json();\n    } catch {\n      payload = null;\n    }\n    const row =\n      typeof payload === \"object\" && payload !== null\n        ? (payload as Record<string, unknown>)\n        : {};\n    return {\n      dispatched: row[\"dispatched\"] === true,\n      detail: typeof row[\"detail\"] === \"string\" ? row[\"detail\"] : \"\",\n    };\n  }\n\n  return {\n    async ask({ meetingId, question, signal, onText, onPhase }) {\n      const trimmed = question.trim();\n      if (trimmed.length === 0) {\n        throw new MeetError(\n          \"misconfigured\",\n          \"meet.ai.ask: an empty question\",\n          \"Type a question. Nothing is sent until there is one.\",\n        );\n      }\n      const roomToken = options.resolveRoomToken?.() ?? null;\n      const response = await send({\n        path: MEET_ROUTES.intelligenceAsk,\n        // THE WHOLE BODY. No transcript, no context, no agent id (D16).\n        body: { meeting_id: meetingId, question: trimmed },\n        operation: \"meet.ai.ask\",\n        // A GUEST MAY ASK. The server decides whether it can answer.\n        requireAuth: false,\n        ...(roomToken !== null ? { headers: { [MEETING_PASS_HEADER]: roomToken } } : {}),\n        ...(signal !== undefined ? { signal } : {}),\n      });\n      if (!response.ok) {\n        // Both refusals happen BEFORE the stream opens, by the server's design,\n        // so this is an honest status rather than a stream that dies mid-answer.\n        const refusal = await refusalFor(response, \"meet.ai.ask\");\n        throw new MeetError(\n          response.status === 403 || response.status === 401\n            ? \"forbidden\"\n            : response.status === 404\n              ? \"not-found\"\n              : \"transport\",\n          refusal.reason,\n          refusal.remedy,\n        );\n      }\n      const body = response.body;\n      if (body === null || body === undefined) {\n        throw new MeetError(\n          \"invalid-response\",\n          \"meet.ai.ask: the answer arrived with no stream to read\",\n          \"The route streams NDJSON. A response with no body means a proxy buffered or \" +\n            \"stripped it — check for a gateway that does not pass streaming responses.\",\n        );\n      }\n      let text = \"\";\n      let coverage: MeetAnswerCoverage | null = null;\n      let failure: ServerRefusal | null = null;\n      for await (const envelope of readMatrxNdjsonStream(\n        body,\n        signal !== undefined ? { signal } : {},\n      )) {\n        if (envelope.event === MEET_ANSWER_EVENTS.chunk) {\n          const piece = readText(envelope.data);\n          if (piece.length > 0) {\n            // THE ANSWER IS THE CONCATENATED CHUNKS — the server deliberately\n            // sends no second copy in a terminal payload, so this accumulation\n            // IS the answer, not an optimization.\n            text += piece;\n            onText?.(text);\n          }\n          continue;\n        }\n        if (envelope.event === MEET_ANSWER_EVENTS.info) {\n          const parsed = readCoverage(envelope.data);\n          if (parsed !== null) coverage = parsed;\n          continue;\n        }\n        if (envelope.event === MEET_ANSWER_EVENTS.phase) {\n          const phase = readText(envelope.data);\n          onPhase?.(phase.length > 0 ? phase : String(envelope.data));\n          continue;\n        }\n        if (envelope.event === MEET_ANSWER_EVENTS.error) {\n          failure = readRefusalBody(envelope.data);\n        }\n      }\n      if (failure !== null) {\n        throw new MeetError(\n          \"transport\",\n          failure.reason,\n          failure.remedy.length > 0\n            ? failure.remedy\n            : \"The answer stopped mid-stream and the server said why. Ask again once the \" +\n              \"named cause is cleared.\",\n        );\n      }\n      if (text.trim().length === 0) {\n        throw new MeetError(\n          \"invalid-response\",\n          \"meet.ai.ask: the stream ended with no answer in it\",\n          \"Nothing was returned to show. Check the meeting has a Holder bound to \" +\n            \"`meet.live_intelligence` at /mandates, then ask again.\",\n        );\n      }\n      return { text: text.trim(), coverage };\n    },\n\n    startNoteTaker: ({ meetingId, roomName }) =>\n      dispatch(\n        MEET_ROUTES.noteTakerStart,\n        {\n          // NO agent_id. Which agent transcribes is the server's business\n          // (D2) — this package could not name one if it wanted to.\n          meeting_id: meetingId,\n          room_name: roomName,\n          organization_id: options.api.organizationId,\n          // The host pressed Start; the server derives the note-taker's origin from this.\n          initiation: \"user\",\n        },\n        \"meet.ai.startNoteTaker\",\n      ),\n\n    requestCaptions: async ({ meetingId }) => {\n      const roomToken = options.resolveRoomToken?.() ?? null;\n      const operation = \"meet.ai.requestCaptions\";\n      try {\n        const response = await send({\n          path: MEET_ROUTES.noteTakerCaptions,\n          // A person turned captions on.\n          body: { meeting_id: meetingId, initiation: \"user\" },\n          operation,\n          requireAuth: roomToken === null,\n          ...(roomToken !== null ? { headers: { [MEETING_PASS_HEADER]: roomToken } } : {}),\n        });\n        if (!response.ok) {\n          options.store.patch({ captionsRefusal: await refusalFor(response, operation) });\n          return;\n        }\n        let payload: unknown = null;\n        try {\n          payload = await response.json();\n        } catch {\n          payload = null;\n        }\n        const row =\n          typeof payload === \"object\" && payload !== null ? (payload as Record<string, unknown>) : {};\n        const detail = typeof row[\"detail\"] === \"string\" ? row[\"detail\"] : \"\";\n        // `dispatched: false` is also \"already in the room\"; the hook decides from the\n        // note-taker's real state whether this sentence matters.\n        options.store.patch({\n          captionsRefusal: row[\"dispatched\"] === true ? null : { status: 200, reason: detail, remedy: \"\" },\n        });\n      } catch (error) {\n        options.store.patch({\n          captionsRefusal: {\n            status: 0,\n            reason: (error as Error).message,\n            remedy: (error as { remedy?: string }).remedy ?? \"\",\n          },\n        });\n      }\n    },\n\n    stopNoteTaker: ({ meetingId }) =>\n      dispatch(\n        MEET_ROUTES.noteTakerStop,\n        { meeting_id: meetingId },\n        \"meet.ai.stopNoteTaker\",\n      ),\n  };\n}\n","/**\n * ONE error classification for the whole package (C22).\n *\n * The banned alternative is a host catching a LiveKit or PostgREST error and\n * deciding for itself whether the camera is busy, the token expired, or the\n * meeting is locked — which is how the same five-branch `if` gets copy-pasted\n * into every consumer and drifts. Everything this package throws is a\n * `MeetError` with a stable `code` and a `remedy` SENTENCE. Nothing fails\n * silently, and nothing fails without saying what to do about it.\n *\n * The device codes exist because \"it doesn't work\" in a video product is almost\n * always one of four specific, differently-remediable things: permission\n * denied, no such device, device already in use by another app, or insecure\n * context (http, where `getUserMedia` does not exist at all). A single\n * \"media-error\" would make the UI say the wrong sentence three times out of\n * four.\n */\n\nimport { PG_CODES, hasSessionExpiredMarker, isAccessRefusalCode } from \"@ai-matrx/kit/db-codes\";\n\nexport type MeetErrorCode =\n  | \"session-unavailable\"\n  | \"forbidden\"\n  | \"not-found\"\n  | \"conflict\"\n  | \"token\"\n  | \"transport\"\n  | \"invalid-response\"\n  | \"misconfigured\"\n  | \"permission-denied\"\n  | \"device-not-found\"\n  | \"device-in-use\"\n  | \"insecure-context\"\n  | \"media-unsupported\"\n  | \"room-locked\"\n  | \"lobby-denied\"\n  | \"capacity\"\n  /** Meet wave 1: the meeting was cancelled — its link resolves, its room never opens. */\n  | \"cancelled\"\n  | \"unknown\";\n\nexport class MeetError extends Error {\n  readonly code: MeetErrorCode;\n  /** What to DO. Rendered to the user for the device codes. */\n  readonly remedy: string;\n  override readonly cause?: unknown;\n  /**\n   * The join gate's reason code (CORE-DESIGN §2.5) when the server named one: `not_found`,\n   * `cancelled`, `ended`, `locked`, `removed`, `lobby_rejects`, `not_invited`… The phase\n   * renders `refused:<reason>` (or `ended`) from it — never from the HTTP status.\n   */\n  readonly reason: string | null;\n  /**\n   * A refusal that lifts by itself says when: whole seconds from the moment the server answered\n   * (a denial's cooldown, `reknock_cooldown_seconds`). Null for every refusal that does not.\n   */\n  readonly retryAfterSeconds: number | null;\n\n  constructor(\n    code: MeetErrorCode,\n    message: string,\n    remedy: string,\n    cause?: unknown,\n    reason?: string | null,\n    retryAfterSeconds?: number | null,\n  ) {\n    super(message);\n    this.name = \"MeetError\";\n    this.code = code;\n    this.remedy = remedy;\n    this.reason = reason ?? null;\n    this.retryAfterSeconds = retryAfterSeconds ?? null;\n    if (cause !== undefined) this.cause = cause;\n  }\n\n  /** True when retrying after the host re-establishes a session is the fix. */\n  get isRetryable(): boolean {\n    return (\n      this.code === \"session-unavailable\" ||\n      this.code === \"transport\" ||\n      this.code === \"token\"\n    );\n  }\n\n  /** True when the user, not the code, must act — the UI shows `remedy`. */\n  get isUserActionable(): boolean {\n    return (\n      this.code === \"permission-denied\" ||\n      this.code === \"device-not-found\" ||\n      this.code === \"device-in-use\" ||\n      this.code === \"insecure-context\"\n    );\n  }\n}\n\n/** What a person reads when the server failed without a sentence of its own. */\nexport const SERVER_FAILED_SENTENCE =\n  \"The server hit an unexpected problem and nothing was changed.\";\n\n/**\n * A developer's text, not a person's: `Internal server error: SomeError`, a\n * bare `SomeError` class name, or a machine code like `internal_error`.\n */\nexport function isRawServerText(value: string): boolean {\n  const text = value.trim();\n  return (\n    /^internal server error\\b/i.test(text) ||\n    /^[A-Z][A-Za-z0-9]*(Error|Exception)$/.test(text) ||\n    /^[a-z][a-z0-9]*(_[a-z0-9]+)+$/.test(text)\n  );\n}\n\n/**\n * A database message a PERSON can read: our RPCs raise plain sentences (\"Only\n * the host can remove a guest.\"); Postgres's own errors (\"permission denied\n * for table …\", \"violates foreign key …\") and class names are not.\n */\nfunction humanDatabaseSentence(message: string): string | null {\n  const text = message.trim();\n  if (text.length === 0 || isRawServerText(text)) return null;\n  if (\n    /permission denied for|violates|relation \"|does not exist|syntax error|column \"|jwt|pgrst|duplicate key|null value in/i.test(\n      text,\n    )\n  )\n    return null;\n  return text;\n}\n\ninterface ErrorLike {\n  name?: string | undefined;\n  message?: string | undefined;\n  code?: string | undefined;\n}\n\n// P0002 is how `platform.refuse_not_found` answers through PostgREST (\"no meeting for that\n// link\"): the one honest not-found, and the reason the join gate's `not_found` screen needs.\nconst NOT_FOUND_CODES = new Set<string>([PG_CODES.pgrstNoRows, PG_CODES.pgrstUnknownRelation, PG_CODES.noDataFound]);\n// PT409: the row changed since the caller read it (meet_update_meeting's version\n// compare-and-swap). 55000: the object is in a state that refuses the change (a\n// canceled meeting). Both are conflicts a person resolves by reloading.\n// (Never 40001: PostgREST retries that code without limit — the 2026-10-21 outage.)\nconst CONFLICT_CODES = new Set<string>([PG_CODES.uniqueViolation, \"PT409\", PG_CODES.objectNotInPrerequisiteState]);\n\n/**\n * THE ONE PLACE a raw database/transport error becomes a typed one. Called at\n * every repository boundary; nothing else in the package inspects a raw error,\n * and no consumer should ever have to.\n */\nexport function normalizeMeetError(error: unknown, operation: string): MeetError {\n  if (error instanceof MeetError) return error;\n\n  const raw = (error ?? {}) as ErrorLike;\n  const message = typeof raw.message === \"string\" ? raw.message : String(error);\n  const code = typeof raw.code === \"string\" ? raw.code : undefined;\n\n  if (raw.name === \"SessionUnavailableError\" || hasSessionExpiredMarker(message)) {\n    return new MeetError(\n      \"session-unavailable\",\n      `${operation}: no Supabase session available (${message})`,\n      \"Normal during sign-in and token refresh. The package retries once after the host's \" +\n        \"session source resolves; log it as a warning, never as an error.\",\n      error,\n    );\n  }\n  if (code !== undefined && isAccessRefusalCode(code)) {\n    // A PERSON reads `message` and `remedy` (toasts, panels); the database's\n    // own words stay on `cause` for the developer. Through 0.7.8 this read\n    // \"meet.x: denied by the database (42501: …)\" and a remedy about RLS.\n    return new MeetError(\n      \"forbidden\",\n      humanDatabaseSentence(message) ?? \"You don't have access to do that in this meeting.\",\n      \"Ask the meeting's host to do it, or to give you access.\",\n      error,\n    );\n  }\n  if (code !== undefined && NOT_FOUND_CODES.has(code)) {\n    return new MeetError(\n      \"not-found\",\n      `${operation}: not found (${code}: ${message})`,\n      \"The row is gone, or RLS hides it. If this is PGRST205 the communication.meet_* tables \" +\n        \"are not deployed yet — see MEET_SCHEMA in repository.ts for the exact contract.\",\n      error,\n      \"not_found\",\n    );\n  }\n  if (code !== undefined && CONFLICT_CODES.has(code)) {\n    return new MeetError(\n      \"conflict\",\n      humanDatabaseSentence(message) ?? \"This meeting changed a moment ago, so nothing was saved.\",\n      \"Reload to see the latest, then try again.\",\n      error,\n    );\n  }\n  const hint = (error as { hint?: unknown } | null)?.hint;\n  return new MeetError(\n    \"transport\",\n    /failed to fetch|networkerror|load failed|network request failed/i.test(message)\n      ? \"The server could not be reached.\"\n      : (humanDatabaseSentence(message) ?? SERVER_FAILED_SENTENCE),\n    typeof hint === \"string\" && humanDatabaseSentence(hint) !== null\n      ? hint.trim()\n      : \"Nothing was changed — retry in a moment; if it keeps happening, reload the page.\",\n    error,\n  );\n}\n\n/**\n * THE DEVICE ERROR TRANSLATOR — the second-most-copied block in every video app.\n *\n * `getUserMedia` rejects with DOMException names, and every one of them means\n * something a user could fix if we told them. This is the whole reason the\n * device layer lives in the package (C22 test 3: less-than-perfect unless done\n * perfectly).\n */\nexport function normalizeDeviceError(error: unknown, operation: string): MeetError {\n  if (error instanceof MeetError) return error;\n  const raw = (error ?? {}) as ErrorLike;\n  const name = raw.name ?? \"\";\n  const message = typeof raw.message === \"string\" ? raw.message : String(error);\n\n  switch (name) {\n    case \"NotAllowedError\":\n    case \"SecurityError\":\n      return new MeetError(\n        \"permission-denied\",\n        `${operation}: camera/microphone permission denied`,\n        \"Allow camera and microphone access for this site, then rejoin. On macOS also check \" +\n          \"System Settings › Privacy & Security — a browser denied there shows the same error.\",\n        error,\n      );\n    case \"NotFoundError\":\n    case \"OverconstrainedError\":\n      return new MeetError(\n        \"device-not-found\",\n        `${operation}: no matching camera/microphone (${message})`,\n        \"The selected device is gone — usually an unplugged headset. Pick another device in \" +\n          \"the pre-join panel; the package falls back to the system default automatically.\",\n        error,\n      );\n    case \"NotReadableError\":\n    case \"AbortError\":\n      return new MeetError(\n        \"device-in-use\",\n        `${operation}: the device is already in use (${message})`,\n        \"Another application (or another tab) holds the camera. Close it and try again — the \" +\n          \"hardware, not the meeting, is what refused.\",\n        error,\n      );\n    case \"TypeError\":\n      return new MeetError(\n        \"insecure-context\",\n        `${operation}: media devices are unavailable in this context (${message})`,\n        \"getUserMedia only exists on https or localhost. Serve the app over https.\",\n        error,\n      );\n    default:\n      return new MeetError(\n        \"media-unsupported\",\n        `${operation}: ${message}`,\n        \"This browser refused the media request for a reason the package does not recognize. \" +\n          \"Report it with this message so the class gets a named remedy rather than a shrug.\",\n        error,\n      );\n  }\n}\n\n/**\n * SCREEN SHARE IS NOT A CAMERA. `getDisplayMedia` rejects with `NotAllowedError`\n * when the person simply closes the picker, and that is a CHOICE, not a\n * permission problem — so it must never wear the camera/microphone sentence\n * `normalizeDeviceError` gives that same error name.\n *\n * WHAT BROWSERS ACTUALLY REPORT (the reason there are three outcomes, not two):\n *  - Chrome / Edge: a closed picker is `NotAllowedError` \"Permission denied\"; an\n *    OS-level refusal (macOS Screen Recording not granted) is `NotAllowedError`\n *    \"Permission denied by system\"; a permissions-policy / enterprise block is\n *    `NotAllowedError` naming the policy or `display-capture`. The MESSAGE is the\n *    only difference, so it is what we read.\n *  - Firefox and Safari: a closed picker, a denied OS permission and a policy\n *    block are ALL `NotAllowedError` with the same generic message (\"The request\n *    is not allowed by the user agent or the platform…\"). They CANNOT be told\n *    apart. That is the `ambiguous` outcome: the first one stays silent (a person\n *    who closed the picker wants no scolding), and the SECOND one in a row shows\n *    the notice, so nobody is left clicking a dead button with no explanation.\n */\nexport type ScreenShareDenial = \"blocked\" | \"ambiguous\" | \"other\";\n\nconst SYSTEM_BLOCK = /by system|permissions?[- ]policy|display-capture|disallowed|not allowed by the system/i;\n\nexport function classifyScreenShareError(error: unknown): ScreenShareDenial {\n  const read = (value: unknown, key: \"name\" | \"message\"): string => {\n    const v = (value as ErrorLike | null | undefined)?.[key];\n    return typeof v === \"string\" ? v : \"\";\n  };\n  const cause = error instanceof MeetError ? error.cause : undefined;\n  const denied = [error, cause].some((value) => {\n    const name = read(value, \"name\");\n    return name === \"NotAllowedError\" || name === \"AbortError\" || name === \"SecurityError\";\n  });\n  if (denied) {\n    const text = [read(error, \"message\"), read(cause, \"message\")].join(\" \");\n    return SYSTEM_BLOCK.test(text) || [error, cause].some((v) => read(v, \"name\") === \"SecurityError\")\n      ? \"blocked\"\n      : \"ambiguous\";\n  }\n  // A MeetError we made ourselves for a plain denial (no browser error inside).\n  if (error instanceof MeetError && error.code === \"permission-denied\" && cause === undefined) {\n    return \"ambiguous\";\n  }\n  return \"other\";\n}\n\n/** True only for a denial that MAY be the person closing the picker. */\nexport function isScreenShareCancel(error: unknown): boolean {\n  return classifyScreenShareError(error) === \"ambiguous\";\n}\n\nexport const SCREEN_SHARE_BLOCKED_REMEDY =\n  \"Your browser or computer is blocking screen sharing. On a Mac, open System Settings > \" +\n  \"Privacy & Security > Screen Recording, turn it on for your browser, then restart the \" +\n  \"browser. On a work computer, ask your administrator. You are still in the call.\";\n\nexport function normalizeScreenShareError(error: unknown, operation: string): MeetError {\n  if (error instanceof MeetError) return error;\n  const raw = (error ?? {}) as ErrorLike;\n  const message = typeof raw.message === \"string\" ? raw.message : String(error);\n  const kind = classifyScreenShareError(error);\n  if (kind === \"blocked\") {\n    return new MeetError(\n      \"permission-denied\",\n      `${operation}: screen sharing is blocked (${message})`,\n      SCREEN_SHARE_BLOCKED_REMEDY,\n      error,\n    );\n  }\n  if (kind === \"ambiguous\") {\n    return new MeetError(\n      \"permission-denied\",\n      `${operation}: screen sharing was canceled or refused`,\n      \"Choose a screen, window or tab in the picker to share it. If no picker appeared, \" +\n        SCREEN_SHARE_BLOCKED_REMEDY,\n      error,\n    );\n  }\n  return new MeetError(\n    \"media-unsupported\",\n    `${operation}: screen sharing is not available (${message})`,\n    \"This browser or device could not share a screen. You are still in the call; try a \" +\n      \"desktop browser to present.\",\n    error,\n  );\n}\n\n/** A response whose SHAPE is wrong — the ingress boundary, not the wire. */\nexport function invalidMeetResponse(operation: string, detail: string): MeetError {\n  return new MeetError(\n    \"invalid-response\",\n    `${operation}: ${detail}`,\n    \"The server returned a shape this package does not accept. Rendering it would put a lie \" +\n      \"on the screen, so it is refused here. Fix the endpoint's return contract.\",\n  );\n}\n","/**\n * S8 — LEAVE INTENTS (CORE-DESIGN §2.7 `/v1/meet/leave`, §4.2 `host_leave_prompt` · `end_confirm`,\n * §11 `leave-or-end-choice`, `host-leave-assign`).\n *\n * What the host's Leave OFFERS is the meeting's behavior profile, resolved by the server and\n * carried on the token response (`leave_policy`). What each choice DOES is the server's: the\n * `/leave` door decides from the pass and the run row whether this person holds the run's host\n * powers. The skin owns only the words.\n */\n\nimport type { ParticipantRole } from \"./types\";\n\nexport type HostLeavePrompt = \"leave_or_end\" | \"must_assign_or_end\" | \"leave_only\";\n\nexport interface LeavePolicy {\n  readonly hostLeavePrompt: HostLeavePrompt;\n  /** Ask \"End for everyone?\" once more before ending (Teams). */\n  readonly endConfirm: boolean;\n}\n\n/** The Meet profile's values — used only when the server sent none (an ad-hoc call). */\nexport const DEFAULT_LEAVE_POLICY: LeavePolicy = { hostLeavePrompt: \"leave_or_end\", endConfirm: false };\n\nconst PROMPTS: readonly HostLeavePrompt[] = [\"leave_or_end\", \"must_assign_or_end\", \"leave_only\"];\n\nexport function leavePolicyFrom(raw: unknown): LeavePolicy {\n  if (typeof raw !== \"object\" || raw === null) return DEFAULT_LEAVE_POLICY;\n  const value = raw as Record<string, unknown>;\n  const prompt = value[\"host_leave_prompt\"];\n  const confirm = value[\"end_confirm\"];\n  return {\n    hostLeavePrompt: PROMPTS.includes(prompt as HostLeavePrompt)\n      ? (prompt as HostLeavePrompt)\n      : DEFAULT_LEAVE_POLICY.hostLeavePrompt,\n    endConfirm: typeof confirm === \"boolean\" ? confirm : DEFAULT_LEAVE_POLICY.endConfirm,\n  };\n}\n\n/** One thing the Leave control can do. */\nexport type LeaveChoice = \"leave\" | \"assign_and_leave\" | \"end_for_all\";\n\n/**\n * The choices Leave offers, in order. Not the host → just leave (no menu). The host:\n * `leave_or_end` (Meet) → leave · end for everyone; `must_assign_or_end` (Zoom) → assign a new\n * host (when someone else is here) · end for everyone, with a plain leave only when nobody is\n * left to hand it to; `leave_only` (Teams) → leave · end meeting.\n */\nexport function leaveChoices(args: {\n  readonly policy: LeavePolicy;\n  readonly role: ParticipantRole | null;\n  readonly othersPresent: boolean;\n}): readonly LeaveChoice[] {\n  if (args.role !== \"host\") return [\"leave\"];\n  switch (args.policy.hostLeavePrompt) {\n    case \"must_assign_or_end\":\n      return args.othersPresent ? [\"assign_and_leave\", \"end_for_all\"] : [\"leave\", \"end_for_all\"];\n    case \"leave_only\":\n    case \"leave_or_end\":\n      return [\"leave\", \"end_for_all\"];\n  }\n}\n","/**\n * THE TOKEN FLOW — the ONLY authorization path into a room (R1).\n *\n * 🚨 **THE CLIENT NEVER HOLDS A LIVEKIT SECRET.** Not in an env var, not in a\n * build-time constant, not \"just for local dev\". A LiveKit API secret in a\n * browser bundle mints a token for ANY room in the project, including one the\n * holder was never invited to — it is a full compromise of every meeting in the\n * organization. This package therefore has no code path that could accept one:\n * it asks aidream, and aidream mints.\n *\n * Four hard parts live here so no host reimplements them (C22):\n *\n * 1. **Single flight.** A React strict-mode double effect, a re-render, and a\n *    reconnect all ask at once; they share ONE request. Two tokens for one\n *    identity is not harmless — LiveKit disconnects the older session, which\n *    looks exactly like \"my call randomly drops when I open the tab\".\n * 2. **Expiry is honored BEFORE it bites.** A token is refreshed at 80% of its\n *    life, not when a reconnect fails at 100%. A meeting that outlives its\n *    token and cannot reconnect is the classic 2-hour-meeting bug.\n * 3. **Guests are first-class, not an exception.** A guest has no session and\n *    the request carries a display name instead; the SERVER decides what a\n *    guest may do. There is no client-side \"is this person allowed\" branch.\n * 4. **A missing session is a lifecycle moment.** Between sign-in and token\n *    arrival, the fetch retries ONCE after the host's session resolves and then\n *    reports `session-unavailable` as a warning — never a red error, never a\n *    retry storm.\n */\n\nimport { connectionPolicyFrom, type ConnectionPolicy } from \"./connection-supervisor\";\nimport { leavePolicyFrom, type LeavePolicy } from \"./leave\";\nimport type { MeetApi } from \"./api\";\nimport { invalidMeetResponse, MeetError } from \"./errors\";\nimport type { JoinRefusalReason } from \"./reasons\";\nimport type {\n  AdmissionState,\n  ObserversVisibleTo,\n  MeetIdentity,\n  ParticipantIdentity,\n  ParticipantRole,\n  ParticipantStanding,\n  RoomName,\n} from \"./types\";\n\nexport interface RoomToken {\n  readonly token: string;\n  readonly serverUrl: string;\n  readonly roomName: RoomName;\n  /** S7: the PERSON key (`user:<id>` · `guest:<device>`) — what every roster tile and row uses. */\n  readonly identity: ParticipantIdentity;\n  /** S7: this tab's LiveKit identity, `<person>~<tab>` (the person key from an older server). */\n  readonly connectionIdentity?: string | undefined;\n  /** S7: `companion` for a \"join here too\" connection (no audio publish, speaker off). */\n  readonly connectionKind?: \"main\" | \"companion\" | undefined;\n  /**\n   * S7: set when the person is ALREADY in the room on another tab or device and has not chosen\n   * yet — the meeting's `second_device` rule (`ask_switch_or_join` · `ask_transfer_or_add`). No\n   * LiveKit token was issued (`token` is empty); the pre-join offers the choice.\n   */\n  readonly secondDeviceChoice?: string | null | undefined;\n  /** S7: the meeting's `second_device` rule, always — told to a second tab of this browser. */\n  readonly secondDeviceRule?: string | null | undefined;\n  readonly displayName: string;\n  /** ISO. The package refreshes at 80% of the remaining life. */\n  readonly expiresAt: string;\n  /** What the SERVER granted. The client renders from this; it never decides. */\n  readonly canPublish: boolean;\n  readonly canSubscribe: boolean;\n  readonly canRecord: boolean;\n  readonly isHost: boolean;\n  /**\n   * 🚨 THE SERVER'S WORD ON WHO THIS JOINER IS (MRI-A11) — `host · cohost · presenter ·\n   * participant · viewer` (CORE-DESIGN §2.1). The same string is minted into the LiveKit\n   * token's participant metadata and its `matrx.participant.role` attribute.\n   */\n  readonly role: ParticipantRole;\n  /** Where this joiner stands with the meeting — beside the role, never inside it. */\n  readonly standing: ParticipantStanding | null;\n  /**\n   * 🚨 THE MEETING PASS (CORE-DESIGN §2.5) — the credential for every aidream meet route,\n   * sent as `x-meet-pass`. It is NOT the LiveKit token (`token`), which is for the media\n   * connection only. Null for an ad-hoc call room (no meeting) or an older server.\n   */\n  readonly meetingPass: string | null;\n  readonly meetingPassExpiresAt: string | null;\n  /** The run (`meet_sessions.id`) this join belongs to; null while waiting before any run. */\n  readonly sessionId: string | null;\n  /** True when the server put this joiner in the lobby (D6). */\n  readonly lobby: boolean;\n  /**\n   * S4: what the mint wrote on the person row — `admitted` · `knocking` · `waiting_host`.\n   * A waiting person then reads `GET /v1/meet/state` every `pollSeconds`.\n   */\n  readonly admissionState?: AdmissionState | undefined;\n  readonly pollSeconds?: number | undefined;\n  /**\n   * Meet wave 5: the breakout room this pass is for, or null for the main room. The\n   * pass is still keyed by the MEETING's room name — it is this person's pass for the\n   * meeting, and the server accepts a breakout pass wherever the meeting's is asked.\n   */\n  readonly breakoutRoomId?: string | null | undefined;\n  /** HR-360 wave 2 (MD-16): who sees the \"Observing\" line in People (knob). */\n  readonly observersVisibleTo?: ObserversVisibleTo | undefined;\n  /**\n   * S6b: the meeting's connection knobs (`reconnect_banner_delay_ms`, `auto_rejoin`,\n   * `auto_rejoin_max_attempts`, `reconnect_grace_seconds`), resolved by the server's policy\n   * ladder. Absent from an older server → the knob defaults.\n   */\n  readonly connectionPolicy?: ConnectionPolicy | undefined;\n  /** S8: what the host's Leave offers for this meeting (`host_leave_prompt`, `end_confirm`). */\n  readonly leavePolicy?: LeavePolicy | undefined;\n  /** host-reclaim (`host_reclaim = prompt`): the returning owner may take the host powers back. */\n  readonly canReclaim?: boolean | undefined;\n}\n\nexport type { AccessTokenSource } from \"./api\";\n\nexport interface TokenClientOptions {\n  /** The ONE org-aware aidream client (MRI-A16). Owns base url and headers. */\n  api: MeetApi;\n  /** Injected clock, so expiry logic is provable without waiting two hours. */\n  now?: (() => number) | undefined;\n  /**\n   * Where a GUEST's pass survives a page close (MRF-1). Absent means passes\n   * live only in memory, which is correct for a member (they have a session to\n   * mint a new one from) and is why this is optional rather than assumed.\n   */\n  storage?: RoomTokenStorage | undefined;\n}\n\n/**\n * 🚨 **WHY A GUEST'S PASS MUST OUTLIVE THE TAB (MRF-1).**\n *\n * A guest has no session, so their only credential for a meeting is the room\n * token this server minted for them. After the meeting ends, `/token` refuses\n * to mint another one — correctly: the room is gone and nobody may rejoin it.\n * So a guest who closes the tab and comes back to read the summary has, in a\n * purely in-memory client, *no way to prove they were ever there* — and the one\n * honest thing left to show them is a refusal.\n *\n * Persisting the pass is what makes the durable link durable for them. It is\n * per-device by nature (it is stored beside the device id that minted it) and\n * it expires on its own: `meet.room_token_ttl_seconds` is the organization's\n * setting for how long, and an expired pass produces the renew-the-link\n * sentence, never \"you were never here\".\n */\nexport interface RoomTokenStorage {\n  read(roomName: RoomName): string | null;\n  write(roomName: RoomName, serialized: string): void;\n  remove(roomName: RoomName): void;\n}\n\n/** `localStorage` when it exists; a no-op that SAYS so otherwise. */\nexport function createWebRoomTokenStorage(\n  onDiagnostic?: (message: string, remedy: string) => void,\n): RoomTokenStorage {\n  const store = (globalThis as { localStorage?: Storage }).localStorage;\n  const key = (roomName: RoomName): string => `mx.meet.pass.${roomName}`;\n  if (store === undefined) {\n    // NEVER SILENT. A guest in a browser with no storage will be refused the\n    // record after they close the tab, and that is worth a line rather than a\n    // mystery.\n    onDiagnostic?.(\n      \"This browser exposes no localStorage, so a guest's meeting pass cannot be kept.\",\n      \"A guest who closes the tab will have to open the meeting link again before the \" +\n        \"record opens. Signed-in members are unaffected.\",\n    );\n    return { read: () => null, write: () => undefined, remove: () => undefined };\n  }\n  return {\n    read(roomName) {\n      try {\n        return store.getItem(key(roomName));\n      } catch {\n        return null;\n      }\n    },\n    write(roomName, serialized) {\n      try {\n        store.setItem(key(roomName), serialized);\n      } catch {\n        /* a full or blocked store is a lost convenience, never a lost join */\n      }\n    },\n    remove(roomName) {\n      try {\n        store.removeItem(key(roomName));\n      } catch {\n        /* see write */\n      }\n    },\n  };\n}\n\n/**\n * The meeting pass a GUEST's browser kept for a room (MRF-1), or null — read from the same\n * storage `createWebRoomTokenStorage` writes. Used by \"keep your notes\" after sign-up.\n */\nexport function rememberedMeetingPass(\n  roomName: RoomName,\n  storage: RoomTokenStorage = createWebRoomTokenStorage(),\n): string | null {\n  const raw = storage.read(roomName);\n  if (raw === null) return null;\n  try {\n    const parsed = JSON.parse(raw) as Partial<RoomToken>;\n    if (parsed.standing !== \"guest\") return null;\n    return typeof parsed.meetingPass === \"string\" && parsed.meetingPass.length > 0\n      ? parsed.meetingPass\n      : null;\n  } catch {\n    return null;\n  }\n}\n\nexport interface TokenRequest {\n  readonly roomName: RoomName;\n  readonly identity: MeetIdentity;\n  /** Present for a meeting join; absent for an ad-hoc call room. */\n  readonly meetingId?: string | undefined;\n  /** The public meeting slug, when joining by link without knowing the id. */\n  readonly slug?: string | undefined;\n  /** Meet wave 5: a breakout room of this meeting; absent = the main room. */\n  readonly breakoutRoomId?: string | null | undefined;\n  /** HR-360 wave 2 (MD-16): ask to join as a silent observer. The server decides. */\n  readonly observe?: boolean | undefined;\n  /** S7: this tab's claimed id (`core/tab-claim.ts`) — the LiveKit identity is `<person>~<tab>`. */\n  readonly tabId?: string | undefined;\n  /** S7: the person's answer when they are already in this meeting on another tab or device. */\n  readonly secondDevice?: SecondDeviceAnswer | undefined;\n}\n\n/** S7: what a person already in the meeting elsewhere chose (CORE-DESIGN §2.1). */\nexport type SecondDeviceAnswer = \"switch_here\" | \"join_too\";\n\nexport interface TokenClient {\n  /** A currently-valid token, minting or refreshing only when it must. */\n  get(request: TokenRequest): Promise<RoomToken>;\n  /** Drop the cached token for a room (after a `denied`, or on leave). */\n  invalidate(roomName: RoomName): void;\n  /** True when the cached token is inside its refresh window. */\n  needsRefresh(roomName: RoomName): boolean;\n  /**\n   * The pass this DEVICE holds for a room, **including an expired one** (MRF-1).\n   *\n   * 🚨 The expired case is the whole reason this returns the token instead of\n   * `null`: \"your pass expired, open the link again\" and \"you were never in\n   * this meeting\" are different sentences, and only the caller that can see the\n   * expiry can say the right one. Never used to join — `get` mints for that.\n   */\n  remembered(roomName: RoomName): RoomToken | null;\n}\n\n/** The aidream routes this package calls. ONE place, so a rename is one edit. */\n/**\n * EVERY aidream ROUTE THIS PACKAGE CALLS, in one object.\n *\n * This is the contract in both directions: aidream carries a test\n * (`services/meet/tests/test_meet_service.py`) that reads THIS object out of\n * this source file and fails if the server stops serving one of these paths.\n * The package is the spec.\n *\n * `meetingEnd` is pinned here BEFORE the server serves it (MRI-A6 owns landing\n * it). That is deliberate and it is not a lie on screen: the control that calls\n * it renders, and a 404 from a server that has not landed A6 is reported as the\n * honest sentence \"Ending a meeting is not available on this server yet\" —\n * never a dead button, never a spinner, and never a silent no-op.\n */\nexport const MEET_ROUTES = {\n  token: \"/api/v1/meet/token\",\n  recordingStart: \"/api/v1/meet/recording/start\",\n  recordingStop: \"/api/v1/meet/recording/stop\",\n  noteTakerStart: \"/api/v1/meet/agent/start\",\n  noteTakerStop: \"/api/v1/meet/agent/stop\",\n  /** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */\n  noteTakerCaptions: \"/api/v1/meet/agent/captions\",\n  /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */\n  intelligenceAsk: \"/api/v1/meet/intelligence/ask\",\n  /** A host ends the meeting for everyone. Served by MRI-A6. */\n  meetingEnd: \"/api/v1/meet/end\",\n  /**\n   * THE POST-MEETING RECORD FOR A READER WITH NO DATABASE (MRF-1). A `GET`,\n   * authorized by the room token this device already holds, carried in the\n   * `x-meet-pass` header — never a query parameter, because a bearer\n   * credential in a URL lands in access logs, referrers and history.\n   */\n  record: \"/api/v1/meet/record\",\n  /** A host chooses what guests may read of ONE meeting (MRF-1). */\n  recordAccess: \"/api/v1/meet/record/access\",\n  /**\n   * KEEP YOUR NOTES (2026-10-01): a guest who just created an account presents\n   * their kept pass in `x-meet-pass` with their new session, and the\n   * meeting they attended becomes theirs to read. Idempotent; never a grant.\n   */\n  claim: \"/api/v1/meet/claim\",\n  /**\n   * Meet wave 1 (0.8): bring every invitee up to date after a write — sends the\n   * invitation / update / cancellation emails with their `.ics` and re-queues\n   * reminders. Idempotent. `{meeting_id}` is substituted by `meetingPath`.\n   */\n  meetingAnnounce: \"/api/v1/meet/meetings/{meeting_id}/announce\",\n  /** Put a one-off meeting on the caller's own Google Calendar (gated by the server). */\n  meetingGoogleCalendar: \"/api/v1/meet/meetings/{meeting_id}/google-calendar\",\n  /**\n   * Meet wave 3: the recap email after the meeting. `GET` = the draft (subject,\n   * body from the wrap-up, who it can go to); `POST` = send what the host\n   * reviewed (`dry_run` renders and queues nothing). Never sent automatically.\n   */\n  meetingFollowUp: \"/api/v1/meet/meetings/{meeting_id}/follow-up\",\n  /**\n   * Meet wave 2: EVERY in-meeting host power (mute, stop video, mute all, ask to\n   * unmute, spotlight, lower hands, co-host, hand over, rename, remove, report).\n   * Decided by the server from the meeting itself; a guest's pass rides\n   * `x-meet-pass`.\n   */\n  moderate: \"/api/v1/meet/moderate\",\n  /** Meet wave 2: the SAVED chat — `POST` sends to everyone, `GET ?meeting_id=` reads history. */\n  chat: \"/api/v1/meet/chat\",\n  /**\n   * Meet wave 5: polls, Q&A, the shared whiteboard and breakout rooms. `POST` acts\n   * (`{meeting_id, action, …}`), `GET ?meeting_id=` reads what this viewer may see.\n   */\n  collab: \"/api/v1/meet/collab\",\n  /** Meet wave 5: translate finished caption lines into this viewer's language. */\n  captionsTranslate: \"/api/v1/meet/captions/translate\",\n  /**\n   * S4 — THE STATE READ (CORE-DESIGN §2.6): `GET ?meeting_id=` with `x-meet-pass`. This\n   * person's admission (lazy expiry applied), whether anyone who can admit is here, the run's\n   * phase. Read every `waiting_poll_seconds` while waiting and on every `mx.state.changed`.\n   */\n  state: \"/api/v1/meet/state\",\n  /** S4: `withdraw` (stop waiting) or `leave` (close this tab); the pass may ride in the body. */\n  leave: \"/api/v1/meet/leave\",\n  /**\n   * S8: a host's browser just called an admission DOOR (`meet_admit` · `meet_deny` ·\n   * `meet_undeny` · `meet_admit_all`). Payload-free: the server republishes the room's\n   * replicated state (the People badge's waiting count) from the database truth.\n   */\n  admissionChanged: \"/api/v1/meet/admission/changed\",\n  /** S4: a pass holder (guests included) saw the recording notice, for this run. */\n  consent: \"/api/v1/meet/consent\",\n} as const;\n\n/** A `MEET_ROUTES` template with its `{meeting_id}` filled in, URL-encoded. */\nexport function meetingPath(template: string, meetingId: string): string {\n  return template.replace(\"{meeting_id}\", encodeURIComponent(meetingId));\n}\n\n/** The header the meeting pass rides on (CORE-DESIGN §2.5). Pinned on both sides. */\nexport const MEETING_PASS_HEADER = \"x-meet-pass\";\n\n/** The `x-meet-pass` header for a held token, or no header at all. */\nexport function meetingPassHeaders(token: RoomToken | null | undefined): Record<string, string> {\n  const pass = token?.meetingPass ?? null;\n  return pass !== null && pass.length > 0 ? { [MEETING_PASS_HEADER]: pass } : {};\n}\n\n/** Refresh at 80% of the token's life — never at the moment it dies. */\nconst REFRESH_RATIO = 0.8;\n\ninterface CacheEntry {\n  token: RoomToken;\n  mintedAt: number;\n  inFlight: Promise<RoomToken> | null;\n}\n\nfunction readString(source: Record<string, unknown>, key: string): string | null {\n  const value = source[key];\n  return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction readBoolean(source: Record<string, unknown>, key: string, fallback: boolean): boolean {\n  const value = source[key];\n  return typeof value === \"boolean\" ? value : fallback;\n}\n\nconst TOKEN_STANDINGS: readonly ParticipantStanding[] = [\"member\", \"invited\", \"outsider\", \"guest\"];\n\nfunction readStanding(source: Record<string, unknown>, key: string): ParticipantStanding | null {\n  const value = source[key];\n  return TOKEN_STANDINGS.includes(value as ParticipantStanding) ? (value as ParticipantStanding) : null;\n}\n\nconst TOKEN_ROLES: readonly ParticipantRole[] = [\"host\", \"cohost\", \"presenter\", \"participant\", \"viewer\"];\n\n/** A word this package does not know grants nothing — it is not a host. */\nfunction readRole(source: Record<string, unknown>, key: string): ParticipantRole | null {\n  const value = source[key];\n  return TOKEN_ROLES.includes(value as ParticipantRole) ? (value as ParticipantRole) : null;\n}\n\nexport function parseRoomToken(body: unknown, roomName: RoomName): RoomToken {\n  if (typeof body !== \"object\" || body === null) {\n    throw invalidMeetResponse(\"meet.token\", \"the response body was not an object\");\n  }\n  const envelope = body as Record<string, unknown>;\n  // aidream's ordinary envelope is `{ success, data, msg }`; a bare object is\n  // accepted too so a self-hosted route does not have to imitate it.\n  const payload =\n    typeof envelope[\"data\"] === \"object\" && envelope[\"data\"] !== null\n      ? (envelope[\"data\"] as Record<string, unknown>)\n      : envelope;\n\n  const isHost = readBoolean(payload, \"is_host\", false);\n  const token = readString(payload, \"token\");\n  const serverUrl = readString(payload, \"server_url\") ?? readString(payload, \"serverUrl\");\n  const identity = readString(payload, \"identity\");\n  const expiresAt = readString(payload, \"expires_at\") ?? readString(payload, \"expiresAt\");\n\n  const secondDeviceChoice = readString(payload, \"second_device_choice\");\n  if ((token === null && secondDeviceChoice === null) || serverUrl === null || identity === null) {\n    throw invalidMeetResponse(\n      \"meet.token\",\n      \"the response is missing token, server_url, or identity — joining with a partial \" +\n        \"token would fail inside LiveKit with an opaque error instead of here\",\n    );\n  }\n  if (expiresAt === null) {\n    throw invalidMeetResponse(\n      \"meet.token\",\n      \"the response carries no expires_at. Without it the package cannot refresh before \" +\n        \"the token dies, and a long meeting silently loses its ability to reconnect\",\n    );\n  }\n  const personKey = readString(payload, \"person_key\") ?? identity;\n  return {\n    token: token ?? \"\",\n    serverUrl,\n    roomName,\n    identity: personKey as ParticipantIdentity,\n    connectionIdentity: readString(payload, \"connection_identity\") ?? personKey,\n    connectionKind: readString(payload, \"connection_kind\") === \"companion\" ? \"companion\" : \"main\",\n    secondDeviceChoice,\n    secondDeviceRule: readString(payload, \"second_device_rule\"),\n    displayName: readString(payload, \"display_name\") ?? readString(payload, \"displayName\") ?? identity,\n    expiresAt,\n    canPublish: readBoolean(payload, \"can_publish\", true),\n    canSubscribe: readBoolean(payload, \"can_subscribe\", true),\n    canRecord: readBoolean(payload, \"can_record\", false),\n    isHost,\n    // An older server sends `is_host` and no `role`; a guest join sends neither.\n    // Deriving the role from what DID arrive keeps a host a host against a\n    // server that has not landed MRI-A11 — and never invents a host from\n    // silence, because both fallbacks below grant nothing.\n    // A word this package does not know grants nothing: `participant`, never a host.\n    role: readRole(payload, \"role\") ?? (isHost ? \"host\" : \"participant\"),\n    standing: readStanding(payload, \"standing\"),\n    meetingPass: readString(payload, \"meeting_pass\"),\n    meetingPassExpiresAt: readString(payload, \"meeting_pass_expires_at\"),\n    sessionId: readString(payload, \"session_id\"),\n    lobby: readBoolean(payload, \"lobby\", false),\n    admissionState: (readString(payload, \"admission_state\") as AdmissionState | null) ?? undefined,\n    pollSeconds: typeof payload[\"poll_seconds\"] === \"number\" ? (payload[\"poll_seconds\"] as number) : undefined,\n    breakoutRoomId: readString(payload, \"breakout_room_id\") ?? null,\n    observersVisibleTo: readString(payload, \"observers_visible_to\") === \"hosts\" ? \"hosts\" : \"everyone\",\n    connectionPolicy: connectionPolicyFrom(payload[\"connection_policy\"]),\n    leavePolicy: leavePolicyFrom(payload[\"leave_policy\"]),\n    canReclaim: payload[\"can_reclaim\"] === true,\n  };\n}\n\nexport function createTokenClient(options: TokenClientOptions): TokenClient {\n  const cache = new Map<RoomName, CacheEntry>();\n  const now = options.now ?? (() => Date.now());\n  const storage = options.storage;\n\n  /** A GUEST's pass is kept; a member's is not — they can always mint again. */\n  function remember(token: RoomToken): void {\n    if (storage === undefined) return;\n    if (token.standing !== \"guest\") return;\n    storage.write(token.roomName, JSON.stringify(token));\n  }\n\n  function recall(roomName: RoomName): RoomToken | null {\n    if (storage === undefined) return null;\n    const raw = storage.read(roomName);\n    if (raw === null) return null;\n    try {\n      const parsed = JSON.parse(raw) as RoomToken;\n      // A stored blob that is not a pass for THIS room proves nothing, and a\n      // half-written one must not be handed out as a credential.\n      if (typeof parsed.token !== \"string\" || parsed.token.length === 0) return null;\n      if (parsed.roomName !== roomName) return null;\n      return parsed;\n    } catch {\n      storage.remove(roomName);\n      return null;\n    }\n  }\n\n  function expired(entry: CacheEntry): boolean {\n    const expiry = Date.parse(entry.token.expiresAt);\n    if (Number.isNaN(expiry)) return true;\n    const life = expiry - entry.mintedAt;\n    if (life <= 0) return true;\n    return now() >= entry.mintedAt + life * REFRESH_RATIO;\n  }\n\n  async function request(input: TokenRequest, retryOnMissingSession: boolean): Promise<RoomToken> {\n    const guest = input.identity.userId === null;\n    let response: Response;\n    try {\n      // THE ORGANIZATION IS A HEADER, NOT ONLY A BODY FIELD — and it is put\n      // there by `core/api.ts`, the one client, so no caller can forget it\n      // (MRI-A16). A body-only `organization_id` looked right and never\n      // arrived: the org-admission middleware refuses first, 400, before the\n      // meet router is ever reached.\n      response = await options.api.request({\n        path: MEET_ROUTES.token,\n        method: \"POST\",\n        // A GUEST HAS NO SESSION AND IS STILL A FIRST-CLASS JOINER (D6), so\n        // only an authenticated join requires one.\n        requireAuth: !guest,\n        operation: \"meet.token\",\n        body: {\n          room_name: input.roomName,\n          ...(input.meetingId !== undefined ? { meeting_id: input.meetingId } : {}),\n          ...(input.slug !== undefined ? { slug: input.slug } : {}),\n          ...(input.breakoutRoomId != null ? { breakout_room_id: input.breakoutRoomId } : {}),\n          ...(input.observe === true ? { observe: true } : {}),\n          organization_id: input.identity.organizationId,\n          display_name: input.identity.displayName,\n          device_id: input.identity.deviceId,\n          guest,\n          ...(input.tabId !== undefined ? { tab_id: input.tabId } : {}),\n          ...(input.secondDevice !== undefined ? { second_device: input.secondDevice } : {}),\n        },\n      });\n    } catch (error) {\n      if (\n        retryOnMissingSession &&\n        (error as { code?: string }).code === \"session-unavailable\"\n      ) {\n        // ONE retry, after the host's session source has had a turn. This is\n        // the cure for \"909 captured errors in 0.6 seconds\": a read that lands\n        // between sign-in and token arrival is a lifecycle moment.\n        await Promise.resolve();\n        return request(input, false);\n      }\n      throw error;\n    }\n\n    if (response.status === 401 || response.status === 403) {\n      // THE SERVER'S SENTENCE IS THE ONE A PERSON READS. aidream answers every\n      // refusal with `{ message, remedy }` (\"The host did not admit you…\", \"A host\n      // removed you…\"); the fallback only covers a body that says nothing.\n      const said = await serverSentence(response);\n      throw new MeetError(\n        \"forbidden\",\n        said?.message ?? \"You can't join this meeting.\",\n        said?.remedy ??\n          \"Ask the person who shared the link to let you in, then open the link again.\",\n        undefined,\n        said?.reason ?? null,\n        said?.retryAfterSeconds ?? null,\n      );\n    }\n    if (response.status === 404) {\n      throw new MeetError(\n        \"not-found\",\n        \"meet.token: no such meeting\",\n        \"The link is wrong or the meeting was deleted. Show the 'meeting not found' screen; \" +\n          \"a durable link that 404s is never a retry.\",\n        undefined,\n        \"not_found\" satisfies JoinRefusalReason,\n      );\n    }\n    if (response.status === 410) {\n      // Meet wave 1: a CANCELED meeting. The link resolves; the room never opens.\n      // The server's own sentence (with the host's reason) is the message.\n      const said = await serverSentence(response);\n      throw new MeetError(\n        \"cancelled\",\n        said?.message ?? \"This meeting was canceled.\",\n        \"Nobody can join a canceled meeting. Show the canceled screen with this sentence; \" +\n          \"ask the host to schedule a new one.\",\n        undefined,\n        said?.reason ?? (\"cancelled\" satisfies JoinRefusalReason),\n      );\n    }\n    if (response.status === 423) {\n      const said = await serverSentence(response);\n      throw new MeetError(\n        \"room-locked\",\n        said?.message ?? \"The meeting is locked.\",\n        said?.remedy ??\n          \"The host locked the room. Ask them to unlock it, then join again.\",\n        undefined,\n        said?.reason ?? (\"locked\" satisfies JoinRefusalReason),\n      );\n    }\n    if (response.status === 503) {\n      throw new MeetError(\n        \"misconfigured\",\n        \"meet.token: the meeting service is not configured\",\n        \"aidream is missing LIVEKIT_URL / LIVEKIT_API_KEY / LIVEKIT_API_SECRET. That is a \" +\n          \"server deployment fix; the client cannot and must not supply them.\",\n      );\n    }\n    if (!response.ok) {\n      throw new MeetError(\n        \"token\",\n        `meet.token: the server returned ${response.status}`,\n        \"Transient. The package retries the join once; if it persists check aidream's meet \" +\n          \"router logs for the room name in question.\",\n      );\n    }\n\n    return parseRoomToken(await response.json(), input.roomName);\n  }\n\n  return {\n    get(input) {\n      const entry = cache.get(input.roomName);\n      // A pass for the main room is not a pass for a breakout room, and back.\n      const sameRoom =\n        entry !== undefined &&\n        (entry.token.breakoutRoomId ?? null) === (input.breakoutRoomId ?? null) &&\n        // An observer's pass is not a participant's, and back (MD-16).\n        (entry.token.role === \"viewer\") === (input.observe === true);\n      if (entry !== undefined && sameRoom) {\n        if (entry.inFlight !== null) return entry.inFlight;\n        if (!expired(entry)) return Promise.resolve(entry.token);\n      }\n      // SINGLE FLIGHT. Every concurrent caller shares this promise, so a strict\n      // mode double-mount cannot mint two tokens for one identity.\n      const pending = request(input, true)\n        .then((token) => {\n          if (token.secondDeviceChoice != null) {\n            // A QUESTION, NOT A CREDENTIAL (S7): never cached, never remembered.\n            cache.delete(input.roomName);\n            return token;\n          }\n          cache.set(input.roomName, { token, mintedAt: now(), inFlight: null });\n          // MRF-1: kept HERE, at the one place a pass is ever minted, so no\n          // future caller can acquire one without it being remembered.\n          remember(token);\n          return token;\n        })\n        .catch((error: unknown) => {\n          // A failure is NEVER cached — one wobble would otherwise leave the\n          // room unjoinable until a reload.\n          cache.delete(input.roomName);\n          throw error;\n        });\n      cache.set(input.roomName, {\n        token: entry?.token ?? placeholder(input.roomName),\n        mintedAt: entry?.mintedAt ?? now(),\n        inFlight: pending,\n      });\n      return pending;\n    },\n    invalidate(roomName) {\n      cache.delete(roomName);\n      // 🚨 THE STORED PASS SURVIVES `invalidate` ON PURPOSE. This is called on\n      // leave and after a refused mint, and a guest leaving a meeting is\n      // exactly the person who comes back to read its summary. What `get`\n      // refuses to REUSE and what the record read may PRESENT are two different\n      // questions; clearing the pass here would answer the second one wrong.\n    },\n    needsRefresh(roomName) {\n      const entry = cache.get(roomName);\n      return entry === undefined || expired(entry);\n    },\n    remembered(roomName) {\n      // The in-flight `placeholder()` occupies the cache slot with an EMPTY\n      // token string and is never handed out — including here, where handing it\n      // out would present \"\" as a credential and earn a 403 that means nothing.\n      const live = cache.get(roomName)?.token;\n      if (live !== undefined && live.token.length > 0) return live;\n      return recall(roomName);\n    },\n  };\n}\n\n/** Never handed out: it only occupies the slot while a mint is in flight. */\nfunction placeholder(roomName: RoomName): RoomToken {\n  return {\n    token: \"\",\n    serverUrl: \"\",\n    roomName,\n    identity: \"\" as ParticipantIdentity,\n    connectionIdentity: \"\",\n    connectionKind: \"main\",\n    secondDeviceChoice: null,\n    displayName: \"\",\n    expiresAt: new Date(0).toISOString(),\n    canPublish: false,\n    canSubscribe: false,\n    canRecord: false,\n    isHost: false,\n    role: \"participant\",\n    standing: null,\n    meetingPass: null,\n    meetingPassExpiresAt: null,\n    sessionId: null,\n    lobby: false,\n    breakoutRoomId: null,\n  };\n}\n\n/**\n * The `{ message, remedy }` aidream puts on a refusal (`MeetError` →\n * `{ error, message, user_message, remedy }`, or FastAPI's `{ detail: {…} }`),\n * or null when the body carries no sentence.\n */\nasync function serverSentence(\n  response: Response,\n): Promise<{\n  message: string;\n  remedy: string | undefined;\n  reason: string | null;\n  retryAfterSeconds: number | null;\n} | null> {\n  try {\n    const body = (await response.json()) as Record<string, unknown> | null;\n    const source =\n      body !== null && typeof body.detail === \"object\" && body.detail !== null\n        ? (body.detail as Record<string, unknown>)\n        : body;\n    if (source === null) return null;\n    const message =\n      typeof source.user_message === \"string\" && source.user_message.trim() !== \"\"\n        ? source.user_message\n        : typeof source.message === \"string\" && source.message.trim() !== \"\"\n          ? source.message\n          : null;\n    if (message === null) return null;\n    const remedy =\n      typeof source.remedy === \"string\" && source.remedy.trim() !== \"\" ? source.remedy : undefined;\n    const reason = typeof source.reason === \"string\" && source.reason !== \"\" ? source.reason : null;\n    const retry = source.retry_after_seconds;\n    const retryAfterSeconds = typeof retry === \"number\" && Number.isFinite(retry) && retry > 0 ? Math.ceil(retry) : null;\n    return { message, remedy, reason, retryAfterSeconds };\n  } catch {\n    return null;\n  }\n}\n","/**\n * THE ONE WAY THIS PACKAGE TALKS TO AIDREAM (MRI-A16).\n *\n * 🚨 **Every request to the aidream server carries `x-organization-id`, and the\n * only way to guarantee \"every\" is for there to be ONE place that builds the\n * request.** aidream's org-admission middleware refuses an authenticated\n * request that does not name the organization it is acting in — 400\n * `organization_required`, before the router is ever reached.\n *\n * 0.1.3 learned that lesson and put the header on the three meet callers by\n * hand. That fixed the instances and left the CLASS wide open, and on\n * 2026-09-09 the class collected its next victim: `<RecordingPlayer>` fetched\n * `GET /files/{id}/download?inline=1` through a bare `fetch` with only a bearer\n * token, so a perfectly landed 1.38 MB recording could not be played by the\n * host who made it (MRI-C8; the identical URL returned `200 video/mp4` the\n * moment the header was added by hand). A fourth caller was written months\n * after the lesson and never heard it, because a lesson written into three call\n * sites is not a lesson, it is three copies of a workaround.\n *\n * So: this module owns the base URL, the organization header and the bearer\n * token, and `api.test.ts` holds a guard that FAILS THE BUILD if any other file\n * in the package calls `fetch(` against a base URL or points an element `src=`\n * at one. A new caller cannot be written without the header any more.\n *\n * 🚨 **HOW A `<video>` GETS ITS BYTES, given that signed URLs are eradicated.**\n * A browser media element cannot attach a header, so a bare\n * `src=\"https://server…/files/{id}/download\"` carries no session and no\n * organization and is refused — which is precisely what MRI-C8 saw. The\n * platform's answer is NOT a signed URL (`aidream/api/routers/files` mints\n * none, by law) but the FILE-SESSION COOKIE: `POST /files/session` mints an\n * HttpOnly `SameSite=None` cookie that the auth middleware accepts on exactly\n * the GET byte-serving routes (`COOKIE_AUTH_PATH_RE` in\n * `matrx_connect/middleware/session_cookie.py`), and a cookie rides a media\n * request that a header cannot. Every private `<img>`/`<video>` in the platform\n * already renders this way.\n *\n * So `fileMedia` mints the cookie and hands back a STREAMING url — which is\n * what lets a person scrub a two-hour recording instead of waiting for a\n * gigabyte to arrive. When the mint is refused (no session, an older server,\n * a browser blocking third-party cookies) it falls back to reading the bytes\n * with the organization header into a `blob:` url — and it SAYS it did, with\n * the reason, because a silent fallback that downloads a gigabyte is exactly\n * the kind of automatic intervention that must announce itself.\n */\n\nimport {\n  applyOrganizationContextHeader,\n  createMatrxTransport,\n  credentialToHeaders,\n  sendMatrxRequest,\n  type MatrxCredential,\n  type MatrxTransport,\n} from \"@ai-matrx/api\";\n\nimport { MATRX_HEADERS } from \"@ai-matrx/auth/credentials\";\nimport { MeetError, normalizeMeetError } from \"./errors\";\nimport type { OrganizationId } from \"./types\";\n\n/**\n * How the host tells us who is asking. Returns null before sign-in resolves,\n * and for a guest, who has no session at all and is still a first-class joiner.\n *\n * It lives HERE rather than in `tokens.ts` (where it was born) because this is\n * now the one module that turns a session into a request.\n */\nexport type AccessTokenSource = () => Promise<string | null>;\n\n/** The header aidream's org-admission middleware demands. One definition. */\nexport const ORGANIZATION_HEADER = MATRX_HEADERS.organization.toLowerCase();\n\nexport interface MeetApiOptions {\n  /** aidream's origin. Never a LiveKit or provider URL. */\n  baseUrl: string;\n  /** Named on EVERY request; the server refuses one that omits it. */\n  organizationId: OrganizationId;\n  accessToken: AccessTokenSource;\n}\n\nexport interface MeetApiRequest {\n  /** An absolute path on the aidream origin, e.g. `/api/v1/meet/token`. */\n  path: string;\n  method?: \"GET\" | \"POST\" | undefined;\n  /** JSON body. Serialized here so no caller can forget the content type. */\n  body?: Record<string, unknown> | undefined;\n  /**\n   * `true` — refuse before the wire when there is no session, with the given\n   * operation named. `false` — send whatever session exists, or none (a guest\n   * minting a room token is a real, authorized case).\n   */\n  requireAuth?: boolean | undefined;\n  /** Names the caller in every error this raises. */\n  operation: string;\n  /** Extra headers. May not override the organization header. */\n  headers?: Record<string, string> | undefined;\n  /**\n   * `\"include\"` for the ONE request that mints the file-session cookie — a\n   * `Set-Cookie` on a cross-origin response is dropped without it.\n   */\n  credentials?: RequestCredentials | undefined;\n  /** Cancels the request. The Q&A stream is abortable by the person asking. */\n  signal?: AbortSignal | undefined;\n}\n\nexport interface MeetApi {\n  readonly baseUrl: string;\n  readonly organizationId: OrganizationId;\n  /** The URL a request to `path` would go to. For diagnostics, never for fetching. */\n  url(path: string): string;\n  /** One request, with the organization header and the session already on it. */\n  request(input: MeetApiRequest): Promise<Response>;\n  /**\n   * Read an authenticated file into a `blob:` URL an element can load. The\n   * caller MUST `URL.revokeObjectURL` it — a leaked one pins the whole file in\n   * memory for the life of the tab.\n   */\n  fetchObjectUrl(input: MeetApiRequest): Promise<string>;\n  /**\n   * A url a `<video>`/`<img>` can load for a platform file. Streams when the\n   * file-session cookie can be minted; otherwise reads the bytes with the\n   * organization header and says why it had to.\n   */\n  fileMedia(fileId: string, operation: string): Promise<MeetFileMedia>;\n  /** Re-mint the file-session cookie. Returns whether it now exists. */\n  refreshFileSession(): Promise<boolean>;\n}\n\n/** Where a media element's bytes are coming from, and whether that is plan A. */\nexport interface MeetFileMedia {\n  readonly url: string;\n  /** `stream` seeks and starts instantly; `bytes` is a fully downloaded blob. */\n  readonly kind: \"stream\" | \"bytes\";\n  /**\n   * Set only for `bytes`, and never null-and-hoping: the sentence a surface\n   * shows to explain why it had to download the whole file first.\n   */\n  readonly fallbackReason: string | null;\n}\n\n/** `POST /files/session` — mints the `mx_files_session` cookie (files law). */\nexport const FILE_SESSION_PATH = \"/files/session\";\n\nexport function createMeetApi(options: MeetApiOptions): MeetApi {\n  const base = options.baseUrl.replace(/\\/+$/, \"\");\n\n  const credentialFor = async (): Promise<MatrxCredential | null> => {\n    const accessToken = await options.accessToken();\n    return accessToken === null ? null : { kind: \"user\", accessToken };\n  };\n\n  // The package's one connection: bearer, organization and the fail-closed\n  // organization rule all come from `@ai-matrx/api`, never from this file.\n  const transport: MatrxTransport = createMatrxTransport({\n    baseUrl: base,\n    credentials: { get: credentialFor },\n    organizationId: options.organizationId,\n    source: \"meet\",\n  });\n\n  async function guardSession(input: MeetApiRequest): Promise<void> {\n    if (input.requireAuth === true && (await credentialFor()) === null) {\n      throw new MeetError(\n        \"session-unavailable\",\n        `${input.operation}: this request requires a signed-in session`,\n        \"Render the signed-out or guest surface rather than a control that will be refused.\",\n      );\n    }\n  }\n\n  /** A caller may not name its own organization; the client's is the only one. */\n  function withoutOrganization(headers: Record<string, string> | undefined): Record<string, string> {\n    return Object.fromEntries(\n      Object.entries(headers ?? {}).filter(([name]) => name.toLowerCase() !== ORGANIZATION_HEADER),\n    );\n  }\n\n  return {\n    baseUrl: base,\n    organizationId: options.organizationId,\n\n    url(path) {\n      return `${base}${path}`;\n    },\n\n    async request(input) {\n      await guardSession(input);\n      const method = input.method ?? (input.body !== undefined ? \"POST\" : \"GET\");\n      const headers = {\n        ...withoutOrganization(input.headers),\n        ...(input.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n      };\n      try {\n        if (input.credentials !== undefined) {\n          // The one request that needs `credentials: \"include\"` (the file-session\n          // cookie mint) — `fetch`-shaped transports cannot carry it, so it rides\n          // the raw lane with the kernel's own credential + organization headers.\n          const credential = await credentialFor();\n          return await sendMatrxRequest(`${base}${input.path}`, {\n            method,\n            headers: applyOrganizationContextHeader(\n              { ...headers, ...credentialToHeaders(credential) },\n              options.organizationId,\n            ),\n            credentials: input.credentials,\n            ...(input.signal !== undefined ? { signal: input.signal } : {}),\n          });\n        }\n        return await transport.fetch(input.path, {\n          method: method === \"POST\" ? \"POST\" : \"GET\",\n          headers,\n          ...(input.signal !== undefined ? { signal: input.signal } : {}),\n          ...(input.body !== undefined ? { body: JSON.stringify(input.body) } : {}),\n        });\n      } catch (error) {\n        throw normalizeMeetError(error, input.operation);\n      }\n    },\n\n    async fetchObjectUrl(input) {\n      const response = await this.request(input);\n      if (response.status === 401 || response.status === 403) {\n        throw new MeetError(\n          \"forbidden\",\n          `${input.operation}: you are not allowed to read this file`,\n          \"The file is safe — this is a read decision, not a lost file. Sign in with an \" +\n            \"account in this meeting's organization and try again.\",\n        );\n      }\n      if (!response.ok) {\n        throw new MeetError(\n          \"transport\",\n          `${input.operation}: the server returned ${response.status}`,\n          \"The file itself is unaffected. Try again; if it repeats, the platform files \" +\n            \"route is the thing to look at, not the recording.\",\n        );\n      }\n      return URL.createObjectURL(await response.blob());\n    },\n\n    async refreshFileSession() {\n      try {\n        const response = await this.request({\n          path: FILE_SESSION_PATH,\n          method: \"POST\",\n          // `Set-Cookie` on a cross-origin response is DROPPED without this.\n          credentials: \"include\",\n          requireAuth: true,\n          operation: \"meet.files.session\",\n        });\n        return response.ok;\n      } catch {\n        // A refused mint is a fallback, never a failure: the caller reads the\n        // bytes with the header instead and says so.\n        return false;\n      }\n    },\n\n    async fileMedia(fileId, operation) {\n      const path = fileDownloadPath(fileId);\n      if (await this.refreshFileSession()) {\n        return { url: `${base}${path}`, kind: \"stream\", fallbackReason: null };\n      }\n      return {\n        url: await this.fetchObjectUrl({ path, operation }),\n        kind: \"bytes\",\n        fallbackReason:\n          \"This file was downloaded in full before playing, because the browser session that \" +\n          \"lets it stream could not be established. Downloading can take longer, and seeking \" +\n          \"is unavailable until it finishes.\",\n      };\n    },\n  };\n}\n\n/** `GET /files/{id}/download?inline=1` — the platform files route (R3). */\nexport function fileDownloadPath(fileId: string): string {\n  return `/files/${encodeURIComponent(fileId)}/download?inline=1`;\n}\n","/**\n * THE MEET CHANNEL NAMESPACES.\n *\n * Zero hand-rolled `.channel(` in this package (the realtime doctrine). Every\n * topic is declared through `@ai-matrx/data/realtime`'s registry, which refuses a\n * colliding re-declaration.\n *\n * THREE channels, each because it has a different AUDIENCE:\n *\n * - `meet-user` (per user): where a call REACHES you — the ring, the cancel,\n *   the \"answered on another device\". You are subscribed to this everywhere the\n *   provider is mounted, whether or not you are in a meeting.\n * - `meet-room` (per room): the pre-media room — who is knocking, who was\n *   admitted, whether recording started. It carries the moments that happen\n *   BEFORE and AFTER media, which LiveKit's own data plane cannot: a guest in\n *   the lobby is not in the LiveKit room yet, by construction (D6).\n * - `meet-meeting` (per meeting): the durable record's feed — transcript\n *   segments, notes, the recording row going `available` — so a surface that is\n *   NOT in the call (a meeting page, an admin console) stays live.\n *\n * 🚨 The in-MEDIA control plane (hand raise, reactions, in-room chat) rides\n * LiveKit data messages, NOT these channels — see `DATA_TOPICS`. Splitting them\n * this way is deliberate: anything that must reach a guest with no Supabase\n * session travels on the media plane, where their room token is the authority.\n */\n\nimport { defineChannelNamespace, type ChannelNamespace } from \"@ai-matrx/data/realtime\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport type { MeetingId, RoomName, UserId } from \"./types\";\n\ninterface Namespaces {\n  user: ChannelNamespace;\n  room: ChannelNamespace;\n  meeting: ChannelNamespace;\n}\n\nfunction namespaces(): Namespaces {\n  // `defineChannelNamespace` throws on a conflicting re-declaration, so these\n  // are created lazily through a `globalThis` slot: with dual ESM/CJS output\n  // the module can be evaluated twice in one process, and a second identical\n  // declaration must be a no-op rather than a crash.\n  return globalSlot<Namespaces>(\"ai-matrx.meet.channel-namespaces\", () => ({\n    user: defineChannelNamespace({\n      namespace: \"meet-user\",\n      parts: [\"userId\"],\n      description:\n        \"One user's calling presence: incoming rings, cancellations, and the \" +\n        \"answered-elsewhere signal that stops every other device ringing.\",\n    }),\n    room: defineChannelNamespace({\n      namespace: \"meet-room\",\n      parts: [\"roomName\"],\n      description:\n        \"One media room's out-of-band plane: lobby knocks and admissions, lock \" +\n        \"state, and recording state — the moments that happen before a guest is \" +\n        \"in the LiveKit room at all.\",\n    }),\n    meeting: defineChannelNamespace({\n      namespace: \"meet-meeting\",\n      parts: [\"meetingId\"],\n      description:\n        \"One meeting record's live feed: transcript segments, AI notes, and the \" +\n        \"recording row settling — for surfaces that are not in the call.\",\n    }),\n  }));\n}\n\nexport function userTopic(userId: UserId): string {\n  return namespaces().user.topic({ userId });\n}\n\nexport function roomTopic(roomName: RoomName): string {\n  return namespaces().room.topic({ roomName });\n}\n\nexport function meetingTopic(meetingId: MeetingId): string {\n  return namespaces().meeting.topic({ meetingId });\n}\n\n/** Broadcast event names. One place, so a sender and a receiver cannot drift. */\nexport const MEET_EVENTS = {\n  /** A call is ringing you. Carries the whole invite; no follow-up read. */\n  ring: \"mx.call.ring\",\n  /** The caller hung up before you answered. */\n  cancel: \"mx.call.cancel\",\n  /** You answered (or declined) on another device. Stop ringing here. */\n  settled: \"mx.call.settled\",\n  /**\n   * 🚨 S4 (CORE-DESIGN §2.6): the ONE room-channel event — payload-free \"something changed,\n   * read again\". Nothing a person must see rides it: a waiting person learns admitted /\n   * denied / expired / ended by READING their row (`GET /v1/meet/state`) on a timer and on\n   * every hint. The four payload broadcasts (`mx.lobby.knock`, `mx.lobby.admission`,\n   * `mx.room.lock`, `mx.room.recording`) are gone with their senders and receivers. The\n   * server publishes the same event on the same topic (aidream `admission.room_topic`).\n   */\n  stateChanged: \"mx.state.changed\",\n} as const;\n\n/**\n * 🚨 `mx.meeting.transcript` and `mx.meeting.note` WERE declared here and\n * emitted and subscribed by nothing — a broadcast fallback that existed only as\n * a name (MRI-A10 found it; feedback `b25db4d4`). They are gone. The thing they\n * described is real now and lives somewhere better: the platform publishes the\n * durable rows into the LIVEKIT ROOM under `matrx.meet.*` (`core/room-events.ts`,\n * MRI-A12), where a session-less guest's room token is the authority. Sending\n * them over a Supabase broadcast channel would have required the guest to hold a\n * Supabase connection, which is the exact thing they do not have.\n */\n\nexport type MeetEvent = (typeof MEET_EVENTS)[keyof typeof MEET_EVENTS];\n","/**\n * THE JOIN GATE'S REASON CODES — ONE VOCABULARY (CORE-DESIGN §2.5).\n *\n * aidream's `services/meet/errors.py` (`JOIN_REFUSAL_REASONS`) emits exactly these codes and a\n * server test fails if the two lists differ; the consuming app decides every refusal screen by\n * one of them — never by the HTTP status and never by matching message text. Skins own the\n * words; the phase renders `refused:<reason>`, except `ended`, which renders the `ended` phase.\n */\nexport const JOIN_REFUSAL_REASONS = [\n  \"not_found\",\n  \"cancelled\",\n  \"ended\",\n  \"expired\",\n  \"too_early\",\n  \"sign_in_required\",\n  \"wrong_account\",\n  \"not_invited\",\n  \"locked\",\n  \"removed\",\n  \"lobby_rejects\",\n  \"meeting_full\",\n  \"platform_capacity\",\n  \"verification_required\",\n  \"registration_required\",\n] as const;\n\nexport type JoinRefusalReason = (typeof JOIN_REFUSAL_REASONS)[number];\n\n/** Is `value` one of the codes the join gate speaks? */\nexport function isJoinRefusalReason(value: unknown): value is JoinRefusalReason {\n  return typeof value === \"string\" && (JOIN_REFUSAL_REASONS as readonly string[]).includes(value);\n}\n","/**\n * THE PHASE MACHINE — the one place a meeting tab's top-level phase changes (CORE-DESIGN §3.1,\n * step S6a).\n *\n * The values ARE the observation contract's `data-meet-phase` column (HARNESS-CONTRACT §2), so\n * the core renders its own state with no translation layer. Every change goes through\n * `nextPhase(from, event)`: an explicit table of which event may move which phase where. An\n * event the table does not allow from the current phase is REFUSED (the store keeps the phase\n * and reports it) — never applied.\n *\n * 🚨 THE INVARIANT (guard: `phase.test.ts`, `in-call-phase-guard.test.ts`): nothing enters\n * `prejoin` except `resolving` (the link resolved) or the person's own click. In-call outcomes —\n * share, devices, recording, captions, chat, collab, moderation — live in REGIONS and have no\n * event here at all, so the MD-01 class (\"a canceled share picker threw a live meeting back to\n * Ready to join?\") cannot recur: from `in_call` the only ways out are the exit-reason\n * resolution (§3.4), the person's own Leave, and the meeting ending.\n *\n * 1:1 calls run on this same machine (§3.6): ringing is a pre-room phase set, and an answered\n * call goes `joining` → `in_call` exactly like a meeting.\n */\n\nimport { isJoinRefusalReason, type JoinRefusalReason } from \"./reasons\";\nimport type { AdmissionState } from \"./types\";\n\n/** Every gate reason except `ended`, which renders the `ended` phase (contract §2). */\nexport type RefusedReason = Exclude<JoinRefusalReason, \"ended\">;\n\n/** Where the person is (HARNESS-CONTRACT §2, verbatim). */\nexport type MeetPhase =\n  | \"resolving\"\n  | \"unsupported\"\n  | `refused:${RefusedReason}`\n  | \"guest_name\"\n  | \"prejoin\"\n  | \"joining\"\n  | \"waiting:host_not_started\"\n  | \"waiting:knocking\"\n  | \"denied\"\n  | \"knock_expired\"\n  | \"in_call\"\n  | \"disconnected\"\n  | \"left\"\n  | \"removed\"\n  | \"superseded\"\n  | \"inactive\"\n  | \"ended\"\n  | \"record\"\n  | \"ringing_out\"\n  | \"ringing_in\"\n  | \"call_declined\"\n  | \"call_missed\"\n  | \"call_busy\"\n  | \"answered_elsewhere\";\n\n/** The phases a §3.4 exit-reason resolution can land on. */\nexport type ExitPhase = \"removed\" | \"superseded\" | \"inactive\" | \"ended\" | \"disconnected\" | \"waiting:knocking\";\n\n/** How a 1:1 call ended before it connected (§3.6). */\nexport type CallOutcomePhase = \"call_declined\" | \"call_missed\" | \"call_busy\" | \"answered_elsewhere\";\n\n/**\n * Every event that can move the phase. `click: true` marks the ones only the person's own\n * press may send — the guard test reads it.\n */\nexport type PhaseEvent =\n  /** The link resolved on page load / mount: `resolving` → `prejoin` (first entry). */\n  | { readonly type: \"resolved\" }\n  /** Capability gate failed: this browser cannot join. */\n  | { readonly type: \"unsupported\" }\n  /**\n   * The link's door said, BEFORE any Join, that this run cannot be joined (`ended`, `cancelled`):\n   * `resolving` → that screen, never the pre-join with a Join button that will be refused.\n   */\n  | { readonly type: \"link_state\"; readonly reason: string | null }\n  /** The person pressed Join / Rejoin / Ask again. */\n  | { readonly type: \"join\"; readonly click: true }\n  /**\n   * S6b: the connection supervisor rejoins by itself from `disconnected` once the network and our\n   * servers answer (`auto_rejoin`). Not a click — and it can only ever lead to `joining`.\n   */\n  | { readonly type: \"auto_rejoin\" }\n  /**\n   * S6b: the page reloaded while this tab was in (or dropped from) the call — Chrome's offline\n   * page reloading, a refresh — so `resolving` goes straight back to `joining`, never pre-join.\n   */\n  | { readonly type: \"resumed\" }\n  /** The person chose to go back to the device check from `left` / `disconnected`. */\n  | { readonly type: \"back_to_prejoin\"; readonly click: true }\n  /** The person pressed Try again on a refusal: look the link up again. */\n  | { readonly type: \"retry\"; readonly click: true }\n  /** The server said wait (or decided a wait): the admission row's own word. */\n  | { readonly type: \"admission\"; readonly admission: AdmissionState }\n  /** Admitted from the waiting room: the core mints the real pass and joins. */\n  | { readonly type: \"admitted\" }\n  /** LiveKit said connected. */\n  | { readonly type: \"connected\" }\n  /**\n   * S7: the server answered the join with a QUESTION — this person is already in the meeting on\n   * another tab or device — so `joining` goes back to `prejoin`, which offers the choice.\n   */\n  | { readonly type: \"second_device\" }\n  /** The join itself failed: a gate reason (→ `refused:*` / `ended`) or none (→ `disconnected`). */\n  | { readonly type: \"join_failed\"; readonly reason: string | null }\n  /** §3.4: the exit-reason resolution decided where an in-call person went. */\n  | { readonly type: \"exit\"; readonly to: ExitPhase }\n  /** My Leave (in the room, joining, or withdrawing from the waiting room). */\n  | { readonly type: \"leave\" }\n  /** The meeting (or this run of it) is over, by any carrier. */\n  | { readonly type: \"ended\" }\n  /** §3.6: I placed a call / a call rings me while nothing else is on screen. */\n  | { readonly type: \"ring_out\" }\n  | { readonly type: \"ring_in\" }\n  /** §3.6: an answered call (by me, or my callee) — join its room. */\n  | { readonly type: \"call_answered\" }\n  /** §3.6: the call ended before it connected. */\n  | { readonly type: \"call_outcome\"; readonly outcome: CallOutcomePhase }\n  /**\n   * Back to the start: a different meeting mounted or the call surface was dismissed (refused\n   * from a live phase — leave first). `teardown: true` is the engine's own dispose: it has\n   * already closed the connection, so nothing live remains to protect and the reset applies from\n   * any phase.\n   */\n  | { readonly type: \"reset\"; readonly teardown?: true };\n\nexport type PhaseEventType = PhaseEvent[\"type\"];\n\n/** Phases in which this tab holds (or is getting) a live media connection. */\nexport const LIVE_PHASES: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\"joining\", \"in_call\"]);\n\n/** The waiting-room phase set (the core reads the server's state while in one of these). */\nexport const WAITING_PHASES: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\n  \"waiting:host_not_started\",\n  \"waiting:knocking\",\n  \"denied\",\n  \"knock_expired\",\n]);\n\n/** A phase the person can press Join / Rejoin from. */\nconst JOINABLE_FROM: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\n  \"prejoin\",\n  \"left\",\n  \"disconnected\",\n  \"superseded\",\n  \"inactive\",\n  \"denied\",\n  \"knock_expired\",\n  // A refused knock whose rule lets the person ask again (a cooldown that ran out): the machine\n  // allows the press; the server's gate decides whether it knocks or is refused again.\n  \"refused:lobby_rejects\",\n]);\n\n/**\n * Refusals that lift by themselves or by a host's act (the lock opens, the window opens, a seat\n * frees): Try again re-asks the gate with the same request. Every other refusal stays a refusal.\n */\nexport const RETRYABLE_REFUSALS: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\n  \"refused:locked\",\n  \"refused:too_early\",\n  \"refused:meeting_full\",\n  \"refused:platform_capacity\",\n]);\n\n/** A call that never connected has no meeting to end; an ended meeting stays ended. */\nconst NOT_ENDABLE: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\n  \"ended\",\n  \"record\",\n  \"unsupported\",\n  \"ringing_out\",\n  \"ringing_in\",\n  \"call_declined\",\n  \"call_missed\",\n  \"call_busy\",\n  \"answered_elsewhere\",\n]);\n\nconst RINGING: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\"ringing_out\", \"ringing_in\"]);\n\n/** Nothing live, nothing pending: a call may take the screen from here. */\nexport const IDLE_PHASES: ReadonlySet<MeetPhase> = new Set<MeetPhase>([\n  \"resolving\",\n  \"left\",\n  \"call_declined\",\n  \"call_missed\",\n  \"call_busy\",\n  \"answered_elsewhere\",\n]);\n\nexport function isLivePhase(phase: MeetPhase): boolean {\n  return LIVE_PHASES.has(phase);\n}\n\nexport function isWaitingPhase(phase: MeetPhase): boolean {\n  return WAITING_PHASES.has(phase);\n}\n\nexport function isRefusedPhase(phase: MeetPhase): phase is `refused:${RefusedReason}` {\n  return phase.startsWith(\"refused:\");\n}\n\n/** The reason a refused / terminal phase carries (`data-meet-reason`). */\nexport function reasonOf(phase: MeetPhase): string | null {\n  return isRefusedPhase(phase) ? phase.slice(\"refused:\".length) : null;\n}\n\n/** A gate reason → the phase it renders. `ended` is the ended phase, never `refused:ended`. */\nexport function refusalPhase(reason: string | null): MeetPhase {\n  if (reason === null || !isJoinRefusalReason(reason)) return \"disconnected\";\n  return reason === \"ended\" ? \"ended\" : (`refused:${reason}` as const);\n}\n\n/** The server's admission word → the waiting phase it renders (§3.1, S4). */\nexport function admissionPhase(admission: AdmissionState): MeetPhase | null {\n  switch (admission) {\n    case \"waiting_host\":\n      return \"waiting:host_not_started\";\n    case \"knocking\":\n      return \"waiting:knocking\";\n    case \"denied\":\n      return \"denied\";\n    case \"expired\":\n      return \"knock_expired\";\n    case \"withdrawn\":\n      return \"left\";\n    case \"ended\":\n      return \"ended\";\n    case \"removed\":\n      return \"refused:removed\";\n    default:\n      // `admitted` is never a waiting phase: it is a join (`admitted` event).\n      return null;\n  }\n}\n\n/**\n * THE TABLE. Returns the next phase, or null when `event` may not move `from` (refused).\n * Pure — the store applies it, and the guard tests enumerate it.\n */\nexport function nextPhase(from: MeetPhase, event: PhaseEvent): MeetPhase | null {\n  switch (event.type) {\n    case \"resolved\":\n      return from === \"resolving\" ? \"prejoin\" : null;\n    case \"unsupported\":\n      return from === \"resolving\" ? \"unsupported\" : null;\n    case \"link_state\":\n      return from === \"resolving\" && event.reason !== null && isJoinRefusalReason(event.reason)\n        ? refusalPhase(event.reason)\n        : null;\n    case \"join\":\n      // A refusal's Try again re-asks the gate with the same request (CORE-DESIGN §11\n      // `meeting-locked-join`, `before-start-early-entry`): the server decides again.\n      return JOINABLE_FROM.has(from) || RETRYABLE_REFUSALS.has(from) ? \"joining\" : null;\n    case \"auto_rejoin\":\n      return from === \"disconnected\" ? \"joining\" : null;\n    case \"resumed\":\n      return from === \"resolving\" ? \"joining\" : null;\n    case \"back_to_prejoin\":\n      return from === \"left\" || from === \"disconnected\" ? \"prejoin\" : null;\n    case \"retry\":\n      return isRefusedPhase(from) || from === \"unsupported\" ? \"resolving\" : null;\n    case \"admission\": {\n      // The server's word on a wait applies while joining or waiting — never to a live call\n      // (being sent back to waiting from the room is an EXIT, resolved by §3.4).\n      if (from !== \"joining\" && !WAITING_PHASES.has(from)) return null;\n      return admissionPhase(event.admission);\n    }\n    case \"admitted\":\n      return WAITING_PHASES.has(from) ? \"joining\" : null;\n    case \"connected\":\n      return from === \"joining\" ? \"in_call\" : null;\n    case \"second_device\":\n      return from === \"joining\" ? \"prejoin\" : null;\n    case \"join_failed\":\n      // ONLY a join can fail the join. A failure reported while in the room is not this event.\n      return from === \"joining\" ? refusalPhase(event.reason) : null;\n    case \"exit\":\n      return from === \"in_call\" || from === \"joining\" ? event.to : null;\n    case \"leave\":\n      return from === \"in_call\" || from === \"joining\" || WAITING_PHASES.has(from) ? \"left\" : null;\n    case \"ended\":\n      return NOT_ENDABLE.has(from) ? null : \"ended\";\n    case \"ring_out\":\n      return IDLE_PHASES.has(from) || from === \"prejoin\" ? \"ringing_out\" : null;\n    case \"ring_in\":\n      return IDLE_PHASES.has(from) ? \"ringing_in\" : null;\n    case \"call_answered\":\n      return RINGING.has(from) ? \"joining\" : null;\n    case \"call_outcome\":\n      return RINGING.has(from) ? event.outcome : null;\n    case \"reset\":\n      // Never out from under a live connection: leave first.\n      return LIVE_PHASES.has(from) && event.teardown !== true ? null : \"resolving\";\n  }\n}\n\n/* ------------------------------------------------------- §3.4 exit-reason resolution (ER) */\n\n/** What the server's state read (`GET /v1/meet/state?connection=`) says about this exit. */\nexport interface ExitServerWord {\n  /** `meet_connections.exit_reason` of THIS connection, if the server recorded one. */\n  readonly exitReason: string | null;\n  /** The run's phase: `ended` means the meeting (this run) is over. */\n  readonly sessionPhase: string | null;\n  readonly meetingPhase?: string | null;\n}\n\nexport interface ExitInput {\n  /** The server's word; `null` = the state read failed (offline / unreachable); undefined = no ST for this room (a call). */\n  readonly server: ExitServerWord | null | undefined;\n  /** LiveKit's `DisconnectReason` name (`PARTICIPANT_REMOVED`, `DUPLICATE_IDENTITY`, …), or null. */\n  readonly hint: string | null;\n  /** The page was frozen (Page Lifecycle) when the connection dropped. */\n  readonly frozen?: boolean;\n}\n\nexport interface ExitResolution {\n  readonly to: ExitPhase;\n  /** `data-meet-reason` for the exit (null when the phase says it all). */\n  readonly reason: string | null;\n  /** `data-meet-connection` to show beside `disconnected`. */\n  readonly connection: \"stable\" | \"offline\" | \"server_unreachable\";\n  /** A notice code the skin renders with it (`sent-to-waiting`), when one applies. */\n  readonly notice: string | null;\n}\n\n/** §3.4, row by row. Pure: the engine gathers the inputs, this decides. */\nexport function resolveExit(input: ExitInput): ExitResolution {\n  const { server, hint } = input;\n  if (server === null) {\n    return { to: \"disconnected\", reason: null, connection: \"server_unreachable\", notice: null };\n  }\n  const word = server?.exitReason ?? null;\n  if (server !== undefined && (server.sessionPhase === \"ended\" || server.meetingPhase === \"ended\" || word === \"ended\" || word === \"time_limit\")) {\n    return { to: \"ended\", reason: word === \"time_limit\" ? \"time_limit\" : \"ended\", connection: \"stable\", notice: null };\n  }\n  if (word === \"removed\") return { to: \"removed\", reason: \"removed\", connection: \"stable\", notice: null };\n  if (word === \"displaced\") return { to: \"superseded\", reason: \"displaced\", connection: \"stable\", notice: null };\n  if (word === \"sent_to_waiting\") {\n    return { to: \"waiting:knocking\", reason: \"sent_to_waiting\", connection: \"stable\", notice: \"sent-to-waiting\" };\n  }\n  if (hint === \"DUPLICATE_IDENTITY\") return { to: \"superseded\", reason: \"displaced\", connection: \"stable\", notice: null };\n  if (hint === \"PARTICIPANT_REMOVED\" && word === null && server === undefined) {\n    // A call room has no state read: LiveKit's own word is all there is.\n    return { to: \"removed\", reason: \"removed\", connection: \"stable\", notice: null };\n  }\n  if (hint === \"ROOM_DELETED\" && server === undefined) {\n    return { to: \"ended\", reason: \"ended\", connection: \"stable\", notice: null };\n  }\n  if (input.frozen === true) return { to: \"inactive\", reason: \"inactive\", connection: \"stable\", notice: null };\n  return { to: \"disconnected\", reason: null, connection: \"stable\", notice: null };\n}\n","/**\n * THE MEET DOMAIN MODEL.\n *\n * D3: an audio call, a video call, and a meeting are ONE thing — a room. An\n * audio call is a room with video off; a meeting is a room plus scheduling,\n * lobby and host metadata. That ruling is expressed here as ONE `MeetRoom`\n * identity carried by both `/calls` and `/meetings`, not as three parallel\n * hierarchies that drift.\n *\n * Identity-bearing values are BRANDED (C22). A `MeetingId` and a `RoomName` are\n * both strings and are NOT interchangeable — passing the meeting's row id where\n * LiveKit wants the room name produces a room nobody else joins, which looks\n * exactly like \"the other person's camera is broken\".\n */\n\ndeclare const brand: unique symbol;\ntype Brand<T, B extends string> = T & { readonly [brand]: B };\n\nexport type MeetingId = Brand<string, \"MeetingId\">;\nexport type CallId = Brand<string, \"CallId\">;\n/** The LiveKit room name. THE MEDIA ROOM KEY — durable for a meeting link. */\nexport type RoomName = Brand<string, \"RoomName\">;\nexport type UserId = Brand<string, \"UserId\">;\nexport type OrganizationId = Brand<string, \"OrganizationId\">;\n/** LiveKit participant identity. `user:<uuid>` or `guest:<opaque>`. */\nexport type ParticipantIdentity = Brand<string, \"ParticipantIdentity\">;\n\nexport const asMeetingId = (value: string): MeetingId => value as MeetingId;\nexport const asCallId = (value: string): CallId => value as CallId;\nexport const asRoomName = (value: string): RoomName => value as RoomName;\nexport const asUserId = (value: string): UserId => value as UserId;\nexport const asOrganizationId = (value: string): OrganizationId =>\n  value as OrganizationId;\nexport const asParticipantIdentity = (value: string): ParticipantIdentity =>\n  value as ParticipantIdentity;\n\nexport type JsonValue =\n  | string\n  | number\n  | boolean\n  | null\n  | JsonValue[]\n  | { [key: string]: JsonValue };\nexport type JsonObject = { [key: string]: JsonValue };\n\n/** Audio-only or with video. A call escalates; it never becomes a new call. */\nexport type CallMode = \"audio\" | \"video\";\n\n/**\n * WHO IS IN THE ROOM, as far as authorization is concerned.\n *\n * A guest has no `userId` — by construction, not by convention. Everything that\n * requires authentication (host powers, recording, starting a call) takes a\n * `userId` and therefore cannot compile against a guest identity (D6).\n */\nexport interface MeetIdentity {\n  readonly userId: UserId | null;\n  readonly organizationId: OrganizationId;\n  readonly displayName: string;\n  readonly avatarUrl: string | null;\n  /** Stable per-device value so a reconnect keeps ONE LiveKit identity. */\n  readonly deviceId: string;\n}\n\nexport function isGuest(identity: MeetIdentity): boolean {\n  return identity.userId === null;\n}\n\n/**\n * WHO SOMEBODY IS IN A ROOM — the SERVER's word, never this client's (MRI-A11).\n *\n * THE ROLE VOCABULARY (CORE-DESIGN §2.1, S3): `host · cohost · presenter · participant ·\n * viewer`. `host` is `meet_meetings.host_user_id`; `cohost` is a real `iam` grant on the\n * meeting. Being a guest is a STANDING (`ParticipantStanding`), never a role: a guest is a\n * `participant` whose standing is `guest`. Pinned against aidream's `config.py` by\n * `test_meet_service.py`.\n */\nexport type ParticipantRole = \"host\" | \"cohost\" | \"presenter\" | \"participant\" | \"viewer\";\n\n/**\n * Where a person stands with the meeting, beside the role: `member` of its organization,\n * `invited` (shared with them), `outsider` (signed in, followed the link), `guest` (no\n * session). The server mints it (attribute `matrx.participant.standing`).\n */\nexport type ParticipantStanding = \"member\" | \"invited\" | \"outsider\" | \"guest\";\n\n/** Rank, so \"can this actor do that to that participant\" is one comparison. */\nexport const ROLE_RANK: Readonly<Record<ParticipantRole, number>> = {\n  host: 4,\n  cohost: 3,\n  presenter: 2,\n  participant: 1,\n  viewer: 0,\n};\n\n/** Does this standing follow the link-holder (guest) rules? `outsider` and `guest`. */\nexport function isLinkFollower(standing: ParticipantStanding | null | undefined): boolean {\n  return standing === \"guest\" || standing === \"outsider\";\n}\n\n/**\n * 🚨 THE ONE PREDICATE FOR \"DOES THIS PERSON HOLD HOST POWERS\".\n *\n * Every host control in this package answers this question and no other. It is\n * a pure function of a SERVER-minted role, so there is no path by which a\n * client's own state can grant it anything.\n */\nexport function isHostRole(role: ParticipantRole): boolean {\n  return role === \"host\" || role === \"cohost\";\n}\n\n/**\n * THE SILENT OBSERVER (HR-360 wave 2, MD-16) — the watch-only role `viewer` the core design\n * already froze: publishes nothing, has no tile on anyone's stage, and is listed in People\n * as \"Observing\". The server decides it at the join gate; nothing here grants it.\n */\nexport function isObserverRole(role: ParticipantRole | null | undefined): boolean {\n  return role === \"viewer\";\n}\n\n/** Who sees the \"Observing\" line in People — knob `meet.observers_visible_to`. */\nexport type ObserversVisibleTo = \"everyone\" | \"hosts\";\n\n/**\n * THE LOBBY LADDER (D6). A guest link-follower starts `knocking`; the host\n * admits or denies. An authenticated member of the meeting's org is `admitted`\n * on arrival unless the meeting is locked.\n */\nexport type AdmissionState =\n  | \"waiting_host\"\n  | \"knocking\"\n  | \"admitted\"\n  | \"denied\"\n  | \"expired\"\n  | \"withdrawn\"\n  | \"removed\"\n  | \"ended\";\n\n/** States a person is still WAITING in (CORE-DESIGN §2.2). */\nexport const WAITING_ADMISSION_STATES: readonly AdmissionState[] = [\"waiting_host\", \"knocking\"];\n\nexport interface LobbyEntry {\n  readonly identity: ParticipantIdentity;\n  readonly displayName: string;\n  readonly avatarUrl: string | null;\n  readonly userId: UserId | null;\n  readonly state: AdmissionState;\n  readonly knockedAt: string;\n  /** When an unanswered knock lapses (`knock_timeout_minutes`); null = never. */\n  readonly knockExpiresAt?: string | null | undefined;\n  readonly decidedAt: string | null;\n  readonly decidedBy: UserId | null;\n  /**\n   * The server's flag on this knock (`mod-removed-bypass`): `previously_removed` when its coarse\n   * signals match someone a host removed from this meeting. Advice for the host, never a block.\n   */\n  readonly flag?: string | null | undefined;\n}\n\nexport type ConnectionQuality = \"excellent\" | \"good\" | \"poor\" | \"lost\" | \"unknown\";\n\n/** One person in the room, as the UI needs them. Media state is a FACT here. */\nexport interface MeetParticipant {\n  readonly identity: ParticipantIdentity;\n  readonly userId: UserId | null;\n  readonly displayName: string;\n  readonly avatarUrl: string | null;\n  readonly role: ParticipantRole;\n  /** Where they stand with the meeting (server-minted); null when the server sent none. */\n  readonly standing?: ParticipantStanding | null;\n  /**\n   * Whether the SERVER granted this participant the power to start a recording\n   * (MRI-A11). It is not `role === \"host\"`: a meeting whose recording policy is\n   * `always-on` is the server's to start and a host may not touch it, and a\n   * `disabled` policy grants it to nobody. The client renders this; it never\n   * recomputes the policy.\n   */\n  readonly canRecord: boolean;\n  readonly isLocal: boolean;\n  readonly isAgent: boolean;\n  readonly micEnabled: boolean;\n  readonly cameraEnabled: boolean;\n  readonly screenSharing: boolean;\n  readonly speaking: boolean;\n  readonly handRaised: boolean;\n  /**\n   * When the hand went up (epoch ms), or null. The HAND QUEUE is ordered by it —\n   * first raised, first called on (Meet wave 2). Optional so a roster built by a\n   * host before 0.8 still type-checks.\n   */\n  readonly handRaisedAt?: number | null | undefined;\n  readonly quality: ConnectionQuality;\n  /**\n   * S6b (`net-others-see-drop`): this person dropped without leaving and is held as a\n   * `reconnecting` tile for `reconnect_grace_seconds`. Absent/false = a live participant.\n   */\n  readonly reconnecting?: boolean | undefined;\n  /**\n   * P1 `net-video-auto-off`: this person's camera is paused by their network (to keep their\n   * audio), not by their choice — from their own heartbeat. Absent/false = not paused.\n   */\n  readonly videoPaused?: boolean | undefined;\n  readonly joinedAt: string;\n  /**\n   * LiveKit participant attributes, verbatim. The note-taker announces itself\n   * here (`matrx.agent.consent_notice`), which is how a consent notice can be\n   * rendered for a participant whose token metadata this client cannot read.\n   */\n  readonly attributes: Readonly<Record<string, string>>;\n}\n\nexport type MeetingKind = \"instant\" | \"scheduled\" | \"recurring\";\n\n/**\n * WHAT THE LINK'S CURRENT RUN IS, read through the no-pass link door (`meet_link_state`) so the\n * entry screen can say it before any Join (CORE-DESIGN §2.3). One vocabulary: `reason` is a\n * join-gate reason code (`ended` · `cancelled`) or null; no private data rides it.\n */\nexport interface LinkRunState {\n  readonly state: \"open\" | \"not_started\" | \"ended\" | \"cancelled\";\n  readonly reason: \"ended\" | \"cancelled\" | null;\n  /** `ended`: the next run's start (null = the meeting can never run again). `not_started`: when it starts. */\n  readonly nextStart: string | null;\n}\n\nexport interface MeetingRecord {\n  readonly id: MeetingId;\n  readonly organizationId: OrganizationId;\n  /** Durable: the same room name before, during, and after (R3). */\n  readonly roomName: RoomName;\n  /** The public slug in a meeting link. Durable for recurring meetings. */\n  readonly slug: string;\n  readonly title: string;\n  readonly kind: MeetingKind;\n  readonly hostUserId: UserId;\n  readonly scheduledFor: string | null;\n  readonly scheduledDurationMinutes: number | null;\n  readonly startedAt: string | null;\n  readonly endedAt: string | null;\n  /** Present only on a row resolved through the link door; absent = unknown (never guessed). */\n  readonly linkRun?: LinkRunState | undefined;\n  readonly locked: boolean;\n  readonly lobbyEnabled: boolean;\n  readonly recordingPolicy: RecordingPolicy;\n  readonly aiEnabled: boolean;\n  readonly metadata: JsonObject;\n  /*\n   * ── MEET WAVE 1 — management (0.8). Always present on a row read from the\n   * database by this package; optional in the type only so a hand-built\n   * fixture from before 0.8 still compiles.\n   */\n  /** IANA zone the meeting's wall-clock time is authored in (`America/Los_Angeles`). */\n  readonly timeZone?: string;\n  /** Description / agenda text. */\n  readonly agenda?: string | null;\n  /** RFC 5545 RRULE subset — one row and one durable link per series. */\n  readonly recurrenceRule?: string | null;\n  /** Signed-in members and invitees may enter before a host arrives. */\n  readonly joinBeforeHost?: boolean;\n  /** Cancel is a STATE: the link still resolves and says so; nobody can join. */\n  readonly cancelledAt?: string | null;\n  readonly cancellationReason?: string | null;\n  /** Archived (soft deleted). Restorable by the host or a co-host. */\n  readonly deletedAt?: string | null;\n  /** iCalendar SEQUENCE — bumped by the database on every reschedule and on cancel. */\n  readonly calendarSequence?: number;\n  /** Row version, for the compare-and-swap in `updateMeeting`. */\n  readonly version?: number;\n}\n\n/* ─────────────────────────────── MEET WAVE 1 — management vocabulary (0.8) */\n\n/** An invitee's answer. `needs_action` = not answered yet (iCalendar NEEDS-ACTION). */\nexport type RsvpState = \"needs_action\" | \"accepted\" | \"declined\" | \"tentative\";\n/** The answers a person can give. */\nexport type RsvpAnswer = Exclude<RsvpState, \"needs_action\">;\n/** A co-host holds host moderation through a real `iam` admin grant on the meeting. */\nexport type InviteeRole = \"invitee\" | \"cohost\";\n\n/** One person a meeting was sent to (`communication.meet_invitees`). */\nexport interface MeetingInvitee {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  /** Set when the person has an account — they skip the waiting room and answer in-app. */\n  readonly userId: UserId | null;\n  readonly email: string | null;\n  readonly displayName: string | null;\n  readonly role: InviteeRole;\n  readonly rsvpState: RsvpState;\n  readonly respondedAt: string | null;\n  readonly rsvpNote: string | null;\n  /** The calendar_sequence of the last invitation they were sent; null = never told. */\n  readonly lastSentSequence: number | null;\n  readonly lastSentAt: string | null;\n}\n\n/** Who to invite: an account (`userId`) or an address (`email`), or both. */\nexport interface InviteeInput {\n  readonly userId?: UserId | undefined;\n  readonly email?: string | undefined;\n  readonly displayName?: string | undefined;\n  /** Omit to keep an existing invitee's role; `cohost` needs the host or a co-host. */\n  readonly role?: InviteeRole | undefined;\n}\n\n/** Where one occurrence of a meeting stands. */\nexport type OccurrenceState = \"scheduled\" | \"moved\" | \"cancelled\";\n\n/** One occurrence — for a one-off meeting, the meeting itself. */\nexport interface MeetingOccurrence {\n  readonly meetingId: MeetingId;\n  /** The start the rule generates (iCalendar RECURRENCE-ID). The key for exceptions. */\n  readonly originalStart: string;\n  /** When it actually happens (differs from `originalStart` only when `moved`). */\n  readonly occurrenceStart: string;\n  readonly durationMinutes: number | null;\n  readonly state: OccurrenceState;\n  readonly sequence: number;\n}\n\n/** One row of the Upcoming list — an occurrence plus what the list shows about its meeting. */\nexport interface UpcomingOccurrence extends MeetingOccurrence {\n  readonly organizationId: OrganizationId;\n  readonly title: string;\n  readonly slug: string;\n  readonly kind: MeetingKind;\n  readonly hostUserId: UserId;\n  readonly timeZone: string;\n  readonly meetingCancelled: boolean;\n  /** The signed-in reader's own answer, when they are an invitee. */\n  readonly myRsvp: RsvpState | null;\n  /** `host`, `cohost` or `invitee` — null when the reader simply can see it (org member). */\n  readonly myRole: \"host\" | InviteeRole | null;\n}\n\n/** An exception row (`communication.meet_occurrence_overrides`). */\nexport interface OccurrenceOverride {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly originalStart: string;\n  readonly state: \"cancelled\" | \"moved\";\n  readonly newStart: string | null;\n  readonly newDurationMinutes: number | null;\n  readonly reason: string | null;\n  readonly calendarSequence: number;\n  /** Set when the exception was withdrawn (`restore`) and the occurrence is back on schedule. */\n  readonly deletedAt: string | null;\n}\n\n/** Settings a meeting carries; unset ones come from the person's / organization's knobs. */\nexport interface MeetingSettings {\n  readonly lobbyEnabled?: boolean | undefined;\n  readonly recordingPolicy?: RecordingPolicy | undefined;\n  readonly aiEnabled?: boolean | undefined;\n  readonly joinBeforeHost?: boolean | undefined;\n}\n\n/** A partial edit. `null` clears a clearable field (agenda, recurrence rule, time). */\nexport interface MeetingChanges extends MeetingSettings {\n  readonly title?: string | undefined;\n  readonly agenda?: string | null | undefined;\n  readonly timeZone?: string | undefined;\n  readonly scheduledFor?: string | null | undefined;\n  readonly scheduledDurationMinutes?: number | null | undefined;\n  readonly recurrenceRule?: string | null | undefined;\n  /**\n   * When the SERIES moves (start, rule or zone), carry its per-date changes\n   * (canceled or moved occurrences) to the new schedule instead of archiving\n   * them — Google Calendar's and Outlook's \"keep changes to individual events\".\n   * Absent or false archives them (restorable). Ask the person; never decide.\n   */\n  readonly keepExceptions?: boolean | undefined;\n}\n\n/** What the emailed RSVP link shows and answers (no account needed). */\nexport type RsvpInvitation =\n  | {\n      readonly ok: true;\n      readonly meeting: {\n        readonly title: string;\n        readonly slug: string;\n        readonly scheduledFor: string | null;\n        readonly durationMinutes: number | null;\n        readonly timeZone: string;\n        readonly agenda: string | null;\n        readonly recurrenceRule: string | null;\n        readonly cancelledAt: string | null;\n        readonly cancellationReason: string | null;\n        readonly endedAt: string | null;\n      };\n      readonly invitee: {\n        readonly displayName: string | null;\n        readonly email: string | null;\n        readonly rsvpState: RsvpState;\n        readonly respondedAt: string | null;\n      };\n    }\n  | { readonly ok: false; readonly message: string };\n\n/** Org-configurable, never hardcoded taste (Law 6 / \"opinions become knobs\"). */\nexport type RecordingPolicy = \"disabled\" | \"host-controlled\" | \"always-on\";\n\nexport type RecordingState =\n  | \"idle\"\n  | \"starting\"\n  | \"recording\"\n  | \"stopping\"\n  | \"processing\"\n  | \"available\"\n  /** Bytes were purged under retention; notes and transcript remain durable. */\n  | \"expired\"\n  | \"failed\";\n\n/**\n * WHICH transport last said what the recording is doing (MRI-A16).\n *\n * `local` — this browser's own optimistic `starting`/`stopping`, which is all\n * the indicator ever had through 0.4.7, and the reason it never went solid.\n * `room` — the room's replicated state (metadata), the ONLY feed a guest has.\n * `record` — the durable `meet_recordings` row. It outranks both (D16).\n */\nexport type RecordingSource = \"local\" | \"room\" | \"record\";\n\n/** The server's durable retention receipt; never inferred from a browser clock. */\nexport interface RecordingRetention {\n  readonly operationId: string;\n  readonly policyId: string;\n  readonly policyUpdatedAt: string;\n  readonly phase: \"warning\" | \"expired\";\n  readonly dueAt: string;\n  readonly expiredAt: string | null;\n}\n\nexport interface RecordingRecord {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly state: RecordingState;\n  readonly startedAt: string | null;\n  readonly endedAt: string | null;\n  readonly startedBy: UserId | null;\n  /** The PLATFORM file id. Never a provider URL (R3). */\n  readonly fileId: string | null;\n  readonly failureReason: string | null;\n  /** Present when central retention warned or purged this recording. */\n  readonly retention: RecordingRetention | null;\n}\n\n/**\n * WHERE A TRANSCRIPT LINE CAME FROM — and therefore how much it is worth.\n *\n * D16: `lk.transcription` is published by a room participant and its\n * `sender_identity` is client-supplied and unvalidated by LiveKit, so a caption\n * is a HINT — good enough to read live, never good enough to reason from. A\n * `record` line is a durable `meet_transcript_segments` row written server-side\n * by the note-taker: that is the transcript. A record always beats a caption;\n * a caption never overwrites a record.\n */\nexport type TranscriptSource = \"caption\" | \"record\";\n\nexport interface TranscriptSegment {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly identity: ParticipantIdentity;\n  readonly speaker: string;\n  readonly text: string;\n  readonly startedAt: string;\n  /** Interim text is replaced in place by its final; it is never appended. */\n  readonly final: boolean;\n  readonly source: TranscriptSource;\n  /**\n   * The `lk.segment_id` this line was captioned under, when known. A durable\n   * row carries it too (the worker writes it into the row's metadata), which is\n   * what lets a record REPLACE the caption it supersedes rather than doubling it.\n   */\n  readonly captionId: string | null;\n}\n\n/**\n * SOMEBODY WHO WAS IN THE MEETING — the durable `meet_participants` row, which\n * outlives the LiveKit room (MRI-D2). `MeetParticipant` above is a live tile;\n * THIS is the attendance record a person reads a week later.\n */\nexport interface MeetingAttendee {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly identity: ParticipantIdentity;\n  readonly displayName: string;\n  readonly avatarUrl: string | null;\n  readonly userId: UserId | null;\n  readonly role: ParticipantRole;\n  readonly admissionState: AdmissionState;\n  /** When this person knocked, and when an unanswered knock lapses (null = never). */\n  readonly knockedAt?: string | null | undefined;\n  readonly knockExpiresAt?: string | null | undefined;\n  /** The server's flag on a knock (`metadata.knock_flag`), e.g. `previously_removed`. */\n  readonly knockFlag?: string | null | undefined;\n  readonly isAgent: boolean;\n  /** FIRST arrival in the room — a rejoin never moves it. */\n  readonly joinedAt: string | null;\n  /** Null while in the room, else the last time they left. */\n  readonly leftAt: string | null;\n  /**\n   * Every stay in the room, oldest first (`metadata.sessions`, written by the\n   * server's one attendance rule). Empty for a row recorded before stays were\n   * kept; the report then falls back to `joinedAt`–`leftAt`.\n   */\n  readonly sessions?: readonly AttendanceStay[] | undefined;\n}\n\n/** One stay in the room: arrived, and left (null = still there or never recorded). */\nexport interface AttendanceStay {\n  readonly joinedAt: string;\n  readonly leftAt: string | null;\n}\n\nexport type MeetingNoteKind = \"note\" | \"decision\" | \"action-item\";\n\n/**\n * ONE ROW OF WHAT THE MEETING DECIDED. `meet_notes.kind` is a live CHECK\n * constraint of exactly three values (D5) — there is no `summary` kind and no\n * `transcript` kind — so the wrap-up summary is a `note` carrying\n * `metadata.role = \"summary\"`, and a live-window note carries `metadata.window`.\n * Both are projected here so the UI never re-reads raw metadata.\n */\nexport interface MeetingNote {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly text: string;\n  readonly createdAt: string;\n  readonly kind: MeetingNoteKind;\n  /** Set ONLY when the assignee resolved to a real user (D18). */\n  readonly assigneeUserId: UserId | null;\n  /** Who the item is for, as a person reads it. A guest keeps their name here. */\n  readonly assigneeDisplayName: string | null;\n  /** `\"summary\"` for the wrap-up; `null` for everything else. */\n  readonly role: \"summary\" | null;\n  /** The live-notes window index this came out of, when it came from one. */\n  readonly window: number | null;\n  /**\n   * 🚨 THE WRAP-UP IS THE AUTHORITATIVE POST-MEETING SET (D20).\n   *\n   * A live-notes window and the wrap-up both write decisions and action items,\n   * and on production 2026-09-09 meeting `9cb-39f8-782` carried the SAME\n   * decision twice — once from the note-taker at 04:43:57 and once from the\n   * wrap-up at 04:47:15 — and the record view listed both. A reader cannot tell\n   * a repeated decision from two decisions.\n   *\n   * So when the wrap-up lands, the server MARKS the window-written decisions\n   * and action items it supersedes (`metadata.superseded_by` = the wrap-up's\n   * run id) and never deletes them: the row is still the timeline of what was\n   * known at 04:43. This field carries that marker, and the record view and the\n   * assistant panel render only the rows where it is `null`.\n   */\n  readonly supersededBy: string | null;\n  /**\n   * WHICH TRANSPORT DELIVERED THIS COPY (MRI-A12). The same durable row reaches\n   * a signed-in member twice — once as a `meet_notes` row over Postgres Changes\n   * (`\"record\"`) and once as a `matrx.meet.note` packet on the media plane\n   * (`\"room\"`), which is the ONLY copy a session-less guest can receive, because\n   * `anon` holds no grant on the table (MRI-A10).\n   *\n   * They carry the same id and the same words, so the store renders one note.\n   * Where they could ever disagree, `\"record\"` wins and `\"room\"` never overwrites\n   * it — the database is the record and the packet is the courtesy copy. That is\n   * the same precedence captions and segments already follow (D16).\n   */\n  readonly source: \"record\" | \"room\";\n}\n\n/**\n * THE WRAP-UP, ANNOUNCED (MRI-A12). The summary, decisions and action items\n * arrive as ordinary notes; this says the pass that wrote them FINISHED, which\n * is the difference between \"no summary yet\" and \"no summary is coming\".\n *\n * 🚨 It reaches a screen only while the room still exists. `POST /v1/meet/end`\n * deletes the LiveKit room and the wrap-up runs afterwards, so on the ordinary\n * ending path nobody is in the room to be told — the post-meeting record view is\n * where the summary is read. A surface must therefore treat `null` as \"not\n * announced\", never as \"not written\".\n */\nexport interface WrapUpAnnouncement {\n  readonly meetingId: MeetingId;\n  /** The `meet_notes` ids the pass wrote, in the order it wrote them. */\n  readonly noteIds: readonly string[];\n  /** How many durable transcript segments it summarized. */\n  readonly segmentCount: number;\n  readonly at: string;\n}\n\n/**\n * THE NOTE-TAKER'S STATE, as the meeting row records it\n * (`meet_meetings.metadata.note_taker.state`, MRI-A2). Five values and no\n * spinner: a surface renders the state it is in, or the server's refusal.\n *\n * - `absent` — nobody summoned it. The control offers to.\n * - `joining` — dispatched; it has not entered the room yet.\n * - `transcribing` — the server recorded active transcription and the exact\n *   deterministic actor is present in the room.\n * - `handoff_pending` — a row that said transcribing no longer has that exact\n *   actor in the room. The next state and any missed audio are not inferred.\n * - `ended` — the recorded note-taker stopped. The cause is not inferred.\n */\nexport type NoteTakerState =\n  | \"absent\"\n  | \"joining\"\n  | \"transcribing\"\n  | \"handoff_pending\"\n  | \"ended\";\n\n/** The lifecycle of a 1:1 or ad-hoc group call (R2). */\nexport type CallState =\n  | \"idle\"\n  | \"dialing\"\n  | \"ringing\"\n  | \"connecting\"\n  | \"active\"\n  | \"declined\"\n  | \"missed\"\n  | \"busy\"\n  | \"cancelled\"\n  | \"ended\"\n  | \"failed\";\n\nexport interface CallInvite {\n  readonly id: CallId;\n  readonly organizationId: OrganizationId;\n  readonly roomName: RoomName;\n  readonly mode: CallMode;\n  readonly callerUserId: UserId;\n  readonly callerName: string;\n  readonly callerAvatarUrl: string | null;\n  readonly calleeUserIds: readonly UserId[];\n  /** The durable conversation the invite was delivered into, if any. */\n  readonly conversationId: string | null;\n  readonly createdAt: string;\n  readonly expiresAt: string;\n  readonly state: CallState;\n  readonly declineMessage: string | null;\n}\n\n/** A person the UI can call. Deliberately minimal: hosts already have this. */\nexport interface CallablePerson {\n  readonly userId: UserId;\n  readonly displayName: string;\n  readonly avatarUrl: string | null;\n}\n\nexport type StageLayout = \"grid\" | \"speaker\" | \"sidebar\";\n","/**\n * THE CALL CENTER — ringing, answering, and the six ways a call ends badly.\n *\n * A call reaches you on whatever surface you are on (R2), which is why this is\n * mounted by the provider and not by a call page. It is also why delivery is\n * DUAL by design, not by belt-and-braces nervousness:\n *\n * - **The durable leg** is the invite ROW plus its Postgres Changes event. It\n *   survives a reload, a late-joining tab, and a dropped socket, and it is what\n *   makes a missed call a fact rather than a lost packet.\n * - **The instant leg** is a broadcast on the callee's user channel, which\n *   arrives without a database round trip.\n *\n * Both are deduplicated on the invite id, so a call rings ONCE however it\n * arrives. Neither is a fallback for the other: removing the durable leg loses\n * calls, and removing the instant leg makes ringing feel slow.\n *\n * 🚨 THE FOUR RULES THAT MAKE RINGING SURVIVABLE\n *\n * 1. **A ring always ends.** Every outgoing call arms a timeout that writes\n *    `missed`. A ring with no terminal state is a phone that never stops.\n * 2. **Answering on one device stops every other.** The `settled` signal on\n *    your OWN user channel silences the other tabs. Without it, answering on a\n *    laptop leaves a phone ringing in the room.\n * 3. **Busy is answered, not ignored.** Being in an active call auto-declines\n *    with `busy`, so the caller learns something instead of ringing out.\n * 4. **The state machine is a MACHINE.** Transitions are validated: a\n *    `declined` call cannot become `active` because a late accept arrived.\n */\n\nimport type { ChannelHandle, RealtimeManager } from \"@ai-matrx/data/realtime\";\nimport { MEET_EVENTS, userTopic } from \"./channels\";\nimport { MeetError } from \"./errors\";\nimport type { MeetRepository } from \"./repository\";\nimport type { MeetStore } from \"./store\";\nimport { isLivePhase, type CallOutcomePhase } from \"./phase\";\nimport {\n  asCallId,\n  asRoomName,\n  type CallId,\n  type CallInvite,\n  type CallMode,\n  type CallState,\n  type MeetIdentity,\n  type RoomName,\n  type UserId,\n} from \"./types\";\n\n/** Which states may follow which. An invalid transition throws, never silently applies. */\nconst TRANSITIONS: Readonly<Record<CallState, readonly CallState[]>> = {\n  idle: [\"dialing\", \"ringing\"],\n  dialing: [\"ringing\", \"connecting\", \"cancelled\", \"declined\", \"busy\", \"missed\", \"failed\"],\n  ringing: [\"connecting\", \"declined\", \"busy\", \"missed\", \"cancelled\", \"failed\"],\n  connecting: [\"active\", \"failed\", \"ended\"],\n  active: [\"ended\", \"failed\"],\n  declined: [],\n  missed: [],\n  busy: [],\n  cancelled: [],\n  ended: [],\n  failed: [],\n};\n\nexport function canTransition(from: CallState, to: CallState): boolean {\n  return TRANSITIONS[from].includes(to);\n}\n\nexport interface CallCenterOptions {\n  manager: RealtimeManager;\n  repository: MeetRepository;\n  store: MeetStore;\n  identity: MeetIdentity;\n  /** Ring for this long before the call is `missed`. Org knob, not a constant. */\n  ringTimeoutMs?: number | undefined;\n  onIncoming?: ((invite: CallInvite) => void) | undefined;\n  onSettled?: ((invite: CallInvite) => void) | undefined;\n  /**\n   * §3.6: MY outgoing call was answered — join its room on the same engine and machine\n   * (`ringing_out` → `joining` → `in_call`). The provider wires this to `engine.join`.\n   */\n  onAnswered?: ((invite: CallInvite) => void) | undefined;\n  onDiagnostic?: ((event: { level: \"info\" | \"warn\" | \"error\"; message: string; remedy?: string }) => void) | undefined;\n  timers?: {\n    setTimeout: (run: () => void, ms: number) => unknown;\n    clearTimeout: (handle: unknown) => void;\n    now: () => number;\n  };\n}\n\nexport interface CallCenter {\n  /** Subscribe to this user's calling channel. Call once, from the provider. */\n  start(): Promise<void>;\n  /** Ring someone. Returns the invite the UI shows as \"calling…\". */\n  call(args: {\n    people: readonly UserId[];\n    mode: CallMode;\n    conversationId?: string | undefined;\n  }): Promise<CallInvite>;\n  accept(id: CallId, mode: CallMode): Promise<CallInvite>;\n  decline(id: CallId, message?: string): Promise<CallInvite>;\n  cancel(id: CallId): Promise<CallInvite>;\n  /** Every invite currently ringing this device. */\n  incoming(): readonly CallInvite[];\n  outgoing(): CallInvite | null;\n  /** Feed a ring that arrived through another path (a messaging action chip). */\n  ingest(invite: CallInvite): void;\n  dispose(): void;\n}\n\nconst DEFAULT_RING_TIMEOUT_MS = 45_000;\n\nexport function createCallCenter(options: CallCenterOptions): CallCenter {\n  const { manager, repository, identity } = options;\n  const timers = options.timers ?? {\n    setTimeout: (run, ms) => setTimeout(run, ms),\n    clearTimeout: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n    now: () => Date.now(),\n  };\n  const ringTimeoutMs = options.ringTimeoutMs ?? DEFAULT_RING_TIMEOUT_MS;\n\n  const incoming = new Map<CallId, CallInvite>();\n  const timeouts = new Map<CallId, unknown>();\n  let outgoing: CallInvite | null = null;\n  let channel: ChannelHandle | null = null;\n\n  /**\n   * Send-only handles on OTHER people's user channels.\n   *\n   * 🚨 CACHED AND CLOSED, deliberately. Since `@ai-matrx/data/realtime` 0.2.0 a\n   * channel is ref-counted per DECLARED topic, so `manager.open(...).send(...)`\n   * without a matching `close()` increments a refcount that is never released —\n   * a leaked subscription per ring, forever. One handle per peer, all closed on\n   * dispose.\n   */\n  const outbound = new Map<string, ChannelHandle>();\n\n  function to(userId: UserId): ChannelHandle {\n    const topic = userTopic(userId);\n    const existing = outbound.get(topic);\n    if (existing !== undefined) return existing;\n    const opened = manager.open({ topic });\n    outbound.set(topic, opened);\n    return opened;\n  }\n\n  function report(level: \"info\" | \"warn\" | \"error\", message: string, remedy?: string): void {\n    options.onDiagnostic?.(remedy === undefined ? { level, message } : { level, message, remedy });\n  }\n\n  function requireUser(operation: string): UserId {\n    if (identity.userId === null) {\n      throw new MeetError(\n        \"forbidden\",\n        `${operation}: a guest cannot place or receive calls`,\n        \"Guests join meetings by link (D6); calling requires an account. Render the join-by-\" +\n          \"link path instead of a call button for guest identities.\",\n      );\n    }\n    return identity.userId;\n  }\n\n  function clearRing(id: CallId): void {\n    const handle = timeouts.get(id);\n    if (handle !== undefined) {\n      timers.clearTimeout(handle);\n      timeouts.delete(id);\n    }\n  }\n\n  function settleLocal(invite: CallInvite): void {\n    clearRing(invite.id);\n    incoming.delete(invite.id);\n    if (outgoing !== null && outgoing.id === invite.id) outgoing = invite;\n    // §3.6 on the machine: a ring that ended here without this device answering it.\n    const held = options.store.snapshot().call;\n    if (held !== null && held.invite.id === invite.id && held.direction === \"incoming\") {\n      const outcome: CallOutcomePhase | \"reset\" =\n        invite.state === \"connecting\" || invite.state === \"active\"\n          ? \"answered_elsewhere\"\n          : invite.state === \"declined\"\n            ? \"reset\"\n            : \"call_missed\";\n      const moved = outcome === \"reset\"\n        ? options.store.dispatch({ type: \"reset\" })\n        : options.store.dispatch({ type: \"call_outcome\", outcome });\n      if (moved) options.store.patch({ call: outcome === \"reset\" ? null : { ...held, invite } });\n    }\n    options.onSettled?.(invite);\n  }\n\n  /** §3.6: the callee's answer reached the caller. */\n  function settleOutgoing(invite: CallInvite): void {\n    if (outgoing === null || outgoing.id !== invite.id) return;\n    clearRing(invite.id);\n    outgoing = invite;\n    const store = options.store;\n    const held = store.snapshot().call;\n    if (held !== null && held.invite.id === invite.id) store.patch({ call: { ...held, invite } });\n    switch (invite.state) {\n      case \"connecting\":\n      case \"active\":\n        if (store.dispatch({ type: \"call_answered\" })) options.onAnswered?.(invite);\n        break;\n      case \"declined\":\n        store.dispatch({ type: \"call_outcome\", outcome: \"call_declined\" });\n        break;\n      case \"busy\":\n        store.dispatch({ type: \"call_outcome\", outcome: \"call_busy\" });\n        break;\n      case \"missed\":\n      case \"failed\":\n        store.dispatch({ type: \"call_outcome\", outcome: \"call_missed\" });\n        break;\n      default:\n        break;\n    }\n    options.onSettled?.(invite);\n  }\n\n  function ingest(invite: CallInvite): void {\n    // ONE ring per invite, whichever leg arrived first.\n    if (incoming.has(invite.id)) return;\n    if (invite.state !== \"ringing\" && invite.state !== \"dialing\") return;\n    if (identity.userId === null) return;\n    if (invite.callerUserId === identity.userId) return;\n\n    // RULE 3: busy is ANSWERED. The caller learns why rather than ringing out.\n    const phase = options.store.snapshot().phase;\n    if (isLivePhase(phase) || phase === \"ringing_out\") {\n      void repository\n        .settleCallInvite(invite.id, \"busy\", null)\n        .then((settled) => {\n          // The CALLER is who needs to know. Sending this on my own topic\n          // would tell my other devices something they already worked out and\n          // leave the caller ringing out into silence.\n          to(settled.callerUserId).send(MEET_EVENTS.settled, settled);\n        })\n        .catch((error: unknown) => {\n          report(\"warn\", `meet.calls: could not report busy — ${String(error)}`,\n            \"The caller will ring out and see a missed call. Harmless, but the busy signal \" +\n              \"is what makes a second call feel intentional.\");\n        });\n      return;\n    }\n\n    incoming.set(invite.id, { ...invite, state: \"ringing\" });\n    // §3.6: when nothing else is on screen the ring IS the phase; otherwise (a pre-join, a\n    // waiting room) the card rings over it and the phase stays where the person is.\n    if (options.store.snapshot().call === null && options.store.dispatch({ type: \"ring_in\" })) {\n      options.store.patch({ call: { invite: { ...invite, state: \"ringing\" }, direction: \"incoming\" } });\n    }\n    options.onIncoming?.(invite);\n    // RULE 1: every ring ends. Even if the caller vanishes mid-ring.\n    timeouts.set(\n      invite.id,\n      timers.setTimeout(() => {\n        const held = incoming.get(invite.id);\n        if (held === undefined) return;\n        settleLocal({ ...held, state: \"missed\" });\n      }, ringTimeoutMs),\n    );\n  }\n\n  return {\n    async start() {\n      const me = requireUser(\"meet.calls.start\");\n      channel = manager.open({\n        topic: userTopic(me),\n        broadcast: [\n          {\n            event: MEET_EVENTS.ring,\n            onMessage: (message) => {\n              ingest(message.data as CallInvite);\n            },\n          },\n          {\n            event: MEET_EVENTS.cancel,\n            onMessage: (message) => {\n              const invite = message.data as CallInvite;\n              const held = incoming.get(invite.id);\n              if (held === undefined) return;\n              settleLocal({ ...held, state: \"cancelled\" });\n            },\n          },\n          {\n            event: MEET_EVENTS.settled,\n            onMessage: (message) => {\n              // RULE 2: answered elsewhere. Stop ringing HERE.\n              const invite = message.data as CallInvite;\n              const held = incoming.get(invite.id);\n              if (held !== undefined) settleLocal(invite);\n              // THE CALLER'S LEG: the callee answered, declined or was busy. Through 0.10 this\n              // handler only knew incoming rings, so a caller never learned the call was answered.\n              else if (outgoing?.id === invite.id) settleOutgoing(invite);\n            },\n          },\n        ],\n        postgresChanges: [\n          {\n            event: \"INSERT\",\n            schema: repository.schema,\n            table: repository.tables.invites,\n            filter: `callee_ids=cs.{${me}}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: (delivery) => {\n              if (delivery.row === null) return;\n              ingest(repository.projectInvite(delivery.row));\n            },\n          },\n          {\n            event: \"UPDATE\",\n            schema: repository.schema,\n            table: repository.tables.invites,\n            filter: `callee_ids=cs.{${me}}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: (delivery) => {\n              if (delivery.row === null) return;\n              const invite = repository.projectInvite(delivery.row);\n              if (invite.state !== \"ringing\" && invite.state !== \"dialing\") {\n                const held = incoming.get(invite.id);\n                if (held !== undefined) settleLocal(invite);\n              }\n            },\n          },\n        ],\n        // THE BACKFILL DOOR. Realtime has no replay: a socket that dropped for\n        // 20 seconds must re-read, or a call placed during the gap rings on the\n        // caller's screen and nowhere else.\n        onBackfill: async () => {\n          const pending = await repository.pendingInvites(me);\n          for (const invite of pending) ingest(invite);\n        },\n      });\n      const pending = await repository.pendingInvites(me);\n      for (const invite of pending) ingest(invite);\n    },\n\n    async call({ people, mode, conversationId }) {\n      const me = requireUser(\"meet.calls.call\");\n      if (people.length === 0) {\n        throw new MeetError(\n          \"misconfigured\",\n          \"meet.calls.call: no callees\",\n          \"Pass at least one user id. An empty call would create a room nobody is invited to.\",\n        );\n      }\n      // This is a compatible proposal only. The server authors the room name;\n      // outgoing state, signaling and joins must use the returned persisted invite.\n      const roomName: RoomName = asRoomName(\n        `call-${me}-${timers.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`,\n      );\n      const invite = await repository.createCallInvite({\n        roomName,\n        mode,\n        callerUserId: me,\n        callerName: identity.displayName,\n        callerAvatarUrl: identity.avatarUrl,\n        calleeUserIds: people,\n        organizationId: identity.organizationId,\n        conversationId: conversationId ?? null,\n        expiresAt: new Date(timers.now() + ringTimeoutMs).toISOString(),\n      });\n      outgoing = invite;\n      // §3.6: placing a call is a phase on the same machine.\n      if (options.store.dispatch({ type: \"ring_out\" })) {\n        options.store.patch({ call: { invite, direction: \"outgoing\" } });\n      }\n\n      // The instant leg. The durable leg already happened — the row is written.\n      for (const callee of people) {\n        to(callee).send(MEET_EVENTS.ring, invite);\n      }\n      timeouts.set(\n        invite.id,\n        timers.setTimeout(() => {\n          if (outgoing?.id !== invite.id) return;\n          void repository\n            .settleCallInvite(invite.id, \"missed\", null)\n            .then((settled) => {\n              settleOutgoing(settled);\n            })\n            .catch(() => undefined);\n        }, ringTimeoutMs),\n      );\n      return invite;\n    },\n\n    async accept(id, mode) {\n      const held = incoming.get(id);\n      if (held !== undefined && !canTransition(held.state, \"connecting\")) {\n        throw new MeetError(\n          \"conflict\",\n          `meet.calls.accept: this call is already ${held.state}`,\n          \"A late accept must not resurrect a settled call. Close the ringing UI; the caller \" +\n            \"has already moved on.\",\n        );\n      }\n      // §3.6: the server settles FIRST. A settle that fails (the caller gave up, the network\n      // dropped) throws with the phase still `ringing_in` — the ring screen is honest — instead of\n      // stranding the tab on `joining` with nothing joining. Only a settled answer moves it.\n      const settled = await repository.settleCallInvite(id, \"connecting\", null);\n      // `ringing_in` → `joining` BEFORE this device hears its own settle, so it never reads its\n      // own answer as \"answered elsewhere\". The join itself is the provider's.\n      if (options.store.snapshot().phase === \"ringing_in\") options.store.dispatch({ type: \"call_answered\" });\n      options.store.patch({ call: { invite: settled, direction: \"incoming\" } });\n      settleLocal(settled);\n      // Tell my OTHER devices to stop ringing, and the caller to stop waiting.\n      channel?.send(MEET_EVENTS.settled, settled);\n      to(settled.callerUserId).send(MEET_EVENTS.settled, { ...settled, mode });\n      return settled;\n    },\n\n    async decline(id, message) {\n      const settled = await repository.settleCallInvite(id, \"declined\", message ?? null);\n      if (options.store.snapshot().call?.invite.id === id && options.store.dispatch({ type: \"reset\" })) {\n        options.store.patch({ call: null });\n      }\n      settleLocal(settled);\n      channel?.send(MEET_EVENTS.settled, settled);\n      to(settled.callerUserId).send(MEET_EVENTS.settled, settled);\n      return settled;\n    },\n\n    async cancel(id) {\n      const settled = await repository.settleCallInvite(id, \"cancelled\", null);\n      clearRing(id);\n      if (outgoing?.id === id) outgoing = settled;\n      if (options.store.snapshot().call?.invite.id === id && options.store.dispatch({ type: \"reset\" })) {\n        options.store.patch({ call: null });\n      }\n      for (const callee of settled.calleeUserIds) {\n        to(callee).send(MEET_EVENTS.cancel, settled);\n      }\n      return settled;\n    },\n\n    incoming: () => [...incoming.values()],\n    outgoing: () => outgoing,\n    ingest,\n\n    dispose() {\n      for (const id of [...timeouts.keys()]) clearRing(asCallId(id));\n      incoming.clear();\n      for (const handle of outbound.values()) handle.close();\n      outbound.clear();\n      channel?.close();\n      channel = null;\n    },\n  };\n}\n","/**\n * DEVICE MANAGEMENT — the part users blame the product for.\n *\n * Every rule here exists because it is a support ticket somewhere:\n *\n * - **Labels are empty until permission is granted.** `enumerateDevices()`\n *   happily returns three cameras with blank labels before the prompt. A picker\n *   rendering \"Camera 1 / Camera 2\" is the classic symptom; we report\n *   `labelsHidden` so the UI can say *why* instead.\n * - **A remembered device can vanish.** Unplug a headset between meetings and a\n *   stored `deviceId` produces `OverconstrainedError`. The manager falls back to\n *   the system default AND SAYS SO — a silent fallback is how someone joins on\n *   the laptop mic while believing they are on their headset.\n * - **Selections persist per KIND, per device.** Injected storage (C10:\n *   persistence-injected — this package's core purpose is not storage), with a\n *   memory fallback that announces itself rather than pretending to be durable.\n * - **Enumeration is repeated on `devicechange`.** A picker that lists what was\n *   plugged in at mount is wrong within seconds of a headset arriving.\n */\n\nimport { listMediaDevices, watchMediaDevices, type MediaDeviceList, type MediaDevicesLike as BrowserMediaDevicesLike } from \"@ai-matrx/browser-audio/core\";\n\nimport { MeetError, normalizeDeviceError } from \"./errors\";\n\nexport type DeviceKind = \"audioinput\" | \"videoinput\" | \"audiooutput\";\n\nexport interface MeetDevice {\n  readonly deviceId: string;\n  readonly kind: DeviceKind;\n  readonly label: string;\n}\n\nexport interface DeviceSnapshot {\n  readonly devices: Readonly<Record<DeviceKind, readonly MeetDevice[]>>;\n  readonly selected: Readonly<Record<DeviceKind, string | null>>;\n  /** True when the browser is hiding labels because permission was not granted. */\n  readonly labelsHidden: boolean;\n  readonly permission: \"unknown\" | \"granted\" | \"denied\";\n  /** Set when a remembered device was gone and we fell back. Shown, not swallowed. */\n  readonly fallbackNotice: string | null;\n}\n\nexport interface DeviceStorage {\n  read(): Record<string, string>;\n  write(value: Record<string, string>): void;\n  readonly durable: boolean;\n}\n\nexport interface MediaDevicesLike extends BrowserMediaDevicesLike {\n  getUserMedia(constraints: { audio?: unknown; video?: unknown }): Promise<{\n    getTracks(): readonly { stop(): void }[];\n  }>;\n}\n\nexport interface DeviceManagerOptions {\n  media: MediaDevicesLike;\n  storage?: DeviceStorage | undefined;\n  onChange?: ((snapshot: DeviceSnapshot) => void) | undefined;\n}\n\nexport interface DeviceManager {\n  /**\n   * 🚨 THE SAME REFERENCE until something actually changes. This is a\n   * `useSyncExternalStore` `getSnapshot` source (see `useDeviceSnapshot`), and\n   * React compares snapshots by IDENTITY: a fresh object literal per call makes\n   * every render report a change, which React reports as *\"The result of\n   * getSnapshot should be cached\"* and then kills the tree with *\"Maximum\n   * update depth exceeded\"*. `createMeetStore()` has always held this contract;\n   * 0.2.0 shipped without it here and every room crashed at `<PreJoin>`.\n   */\n  snapshot(): DeviceSnapshot;\n  /** Enumerate without prompting. Labels may be hidden; that is reported. */\n  refresh(): Promise<DeviceSnapshot>;\n  /** Prompt, then enumerate with real labels. The pre-join screen calls this. */\n  requestPermission(kinds: { audio: boolean; video: boolean }): Promise<DeviceSnapshot>;\n  select(kind: DeviceKind, deviceId: string): DeviceSnapshot;\n  /** The id to actually use — the remembered one, or the default when it is gone. */\n  resolve(kind: DeviceKind): string | null;\n  subscribe(listener: (snapshot: DeviceSnapshot) => void): () => void;\n  dispose(): void;\n}\n\nfunction toMeetDevice(device: { deviceId: string; kind: string; label: string }): MeetDevice {\n  return { deviceId: device.deviceId, kind: device.kind as DeviceKind, label: device.label };\n}\n\nconst KINDS: readonly DeviceKind[] = [\"audioinput\", \"videoinput\", \"audiooutput\"];\n\n/** localStorage when it exists; memory otherwise — and it says which. */\nexport function createWebDeviceStorage(key = \"mx.meet.devices\"): DeviceStorage {\n  const store = (globalThis as { localStorage?: Storage }).localStorage;\n  if (store === undefined) return createMemoryDeviceStorage();\n  return {\n    durable: true,\n    read() {\n      try {\n        const raw = store.getItem(key);\n        if (raw === null) return {};\n        const parsed: unknown = JSON.parse(raw);\n        return typeof parsed === \"object\" && parsed !== null\n          ? (parsed as Record<string, string>)\n          : {};\n      } catch {\n        return {};\n      }\n    },\n    write(value) {\n      try {\n        store.setItem(key, JSON.stringify(value));\n      } catch {\n        // A full or blocked storage must not break joining a call.\n      }\n    },\n  };\n}\n\nexport function createMemoryDeviceStorage(): DeviceStorage {\n  let value: Record<string, string> = {};\n  return {\n    durable: false,\n    read: () => value,\n    write: (next) => {\n      value = next;\n    },\n  };\n}\n\nexport function createDeviceManager(options: DeviceManagerOptions): DeviceManager {\n  const storage = options.storage ?? createMemoryDeviceStorage();\n  const listeners = new Set<(snapshot: DeviceSnapshot) => void>();\n  const stored = storage.read();\n\n  let devices: Record<DeviceKind, readonly MeetDevice[]> = {\n    audioinput: [],\n    videoinput: [],\n    audiooutput: [],\n  };\n  let selected: Record<DeviceKind, string | null> = {\n    audioinput: stored[\"audioinput\"] ?? null,\n    videoinput: stored[\"videoinput\"] ?? null,\n    audiooutput: stored[\"audiooutput\"] ?? null,\n  };\n  let labelsHidden = true;\n  let permission: DeviceSnapshot[\"permission\"] = \"unknown\";\n  let fallbackNotice: string | null = null;\n\n  // 🚨 THE MEMOIZED SNAPSHOT. `current` IS the snapshot; readers get this exact\n  // object until `commit()` replaces it, which happens only when one of the\n  // five fields above actually moved. See the `DeviceManager.snapshot` doc\n  // comment for the crash this prevents.\n  let current: DeviceSnapshot = {\n    devices,\n    selected,\n    labelsHidden,\n    permission,\n    fallbackNotice,\n  };\n\n  function snapshot(): DeviceSnapshot {\n    return current;\n  }\n\n  /** Rebuild the snapshot from the current state. Call after ANY mutation. */\n  function commit(): DeviceSnapshot {\n    current = { devices, selected, labelsHidden, permission, fallbackNotice };\n    return current;\n  }\n\n  function emit(): DeviceSnapshot {\n    const next = commit();\n    options.onChange?.(next);\n    for (const listener of listeners) listener(next);\n    return next;\n  }\n\n  function apply(list: MediaDeviceList): DeviceSnapshot {\n    const grouped: Record<DeviceKind, MeetDevice[]> = {\n      audioinput: list.audioInputs.map(toMeetDevice),\n      videoinput: list.videoInputs.map(toMeetDevice),\n      audiooutput: list.audioOutputs.map(toMeetDevice),\n    };\n    devices = grouped;\n    labelsHidden = list.labelsHidden;\n\n    // THE VANISHED-DEVICE FALLBACK. A remembered id that is no longer present\n    // is dropped to the system default, and the notice is part of the snapshot\n    // so the UI can say \"your headset is unplugged — using the built-in mic\".\n    const lost: string[] = [];\n    for (const kind of KINDS) {\n      const current = selected[kind];\n      if (current === null) continue;\n      if (!grouped[kind].some((device) => device.deviceId === current)) {\n        selected = { ...selected, [kind]: null };\n        lost.push(kind);\n      }\n    }\n    fallbackNotice =\n      lost.length === 0\n        ? null\n        : `A remembered ${lost.join(\" and \")} device is no longer connected — using the ` +\n          \"system default. Pick another in the device menu.\";\n    return emit();\n  }\n\n  async function enumerate(): Promise<DeviceSnapshot> {\n    let list: MediaDeviceList;\n    try {\n      list = await listMediaDevices({ mediaDevices: options.media });\n    } catch (error) {\n      throw normalizeDeviceError(error, \"meet.enumerateDevices\");\n    }\n    return apply(list);\n  }\n\n  // `devicechange` re-lists through the shared watcher (queued, in order). The first list is\n  // taken by `refresh()`, so skip the subscribe-time one. A failed re-list keeps the last list.\n  const stopWatching = watchMediaDevices(apply, { mediaDevices: options.media, skipInitial: true });\n\n  return {\n    snapshot,\n    refresh: enumerate,\n    async requestPermission(kinds) {\n      if (!kinds.audio && !kinds.video) {\n        throw new MeetError(\n          \"misconfigured\",\n          \"meet.requestPermission: asked for neither audio nor video\",\n          \"Request at least one kind. Prompting for nothing silently resolves and leaves \" +\n            \"labels hidden, which looks like a broken picker.\",\n        );\n      }\n      try {\n        const stream = await options.media.getUserMedia({\n          ...(kinds.audio ? { audio: true } : {}),\n          ...(kinds.video ? { video: true } : {}),\n        });\n        // 🚨 STOP THE PROBE STREAM. Holding it keeps the camera light on and,\n        // on Windows, makes the real join fail with NotReadableError — the\n        // device is busy with our own probe.\n        for (const track of stream.getTracks()) track.stop();\n        permission = \"granted\";\n      } catch (error) {\n        permission = \"denied\";\n        emit();\n        throw normalizeDeviceError(error, \"meet.requestPermission\");\n      }\n      return enumerate();\n    },\n    select(kind, deviceId) {\n      selected = { ...selected, [kind]: deviceId };\n      fallbackNotice = null;\n      storage.write({\n        ...storage.read(),\n        [kind]: deviceId,\n      });\n      return emit();\n    },\n    resolve(kind) {\n      const current = selected[kind];\n      if (current !== null && devices[kind].some((device) => device.deviceId === current)) {\n        return current;\n      }\n      return devices[kind][0]?.deviceId ?? null;\n    },\n    subscribe(listener) {\n      listeners.add(listener);\n      return () => listeners.delete(listener);\n    },\n    dispose() {\n      stopWatching();\n      listeners.clear();\n    },\n  };\n}\n","/**\n * WHO SAID THAT — one answer, every surface, both lanes (MRI-A16).\n *\n * 🚨 **A RAW LIVEKIT IDENTITY IS NEVER A PERSON'S NAME.** On production\n * 2026-09-09 the host's caption rail read *\"Ada Lovelace: I planted a marigold\n * in the courtyard\"* and the guest's — the same meeting, the same second —\n * read *\"guest:c8-spk-1\"*, because the host resolved the name from the durable\n * rows it can read and the guest had no fallback at all and printed the token\n * (MRI-C8). Two surfaces disagreeing about who is speaking is worse than either\n * one being ugly: a person reading the transcript cannot tell whether those are\n * one speaker or two.\n *\n * The cure is that nothing resolves a name for itself. Every source that\n * happens to KNOW a name teaches this book — the LiveKit roster, a durable\n * `meet_transcript_segments` row, a durable `meet_participants` row, a chat\n * message, our own identity — and every surface asks it. Three rules:\n *\n * 1. **A name is learned, never unlearned.** Someone who leaves the room keeps\n *    the name they had; a caption that lands after them still says who spoke.\n *    This is the \"last known name\" rule, and it is why the book is a store\n *    field rather than a derivation over the current roster.\n * 2. **An identity is not a name.** `learn` refuses a \"name\" that is the\n *    identity itself — which is exactly what the LiveKit roster hands back for\n *    a participant whose token carried no name, and exactly how the token got\n *    onto the screen in the first place.\n * 3. **When nobody knows, SAY nobody knows.** `displayNameFor` answers with an\n *    honest placeholder — \"Unnamed guest\" / \"Unnamed participant\" — never a\n *    token, and never an invented name. The placeholder is deliberately not\n *    unique, so surfaces that must keep two unnamed people apart group by\n *    IDENTITY rather than by the rendered name.\n */\n\nimport type { ParticipantIdentity } from \"./types\";\n\n/** Identity → the best display name anything has ever known for it. */\nexport type NameBook = Readonly<Record<string, string>>;\n\n/**\n * S7 (CORE-DESIGN §2.1): a LiveKit identity is `<person key>~<tab id>` — one CONNECTION per\n * browser tab. The person key (`user:<id>` · `guest:<device>` · `agent:<capability>:<meeting>`)\n * is what every tile, row and roster entry uses. THIS is the one helper that reads the shape;\n * `names.test.ts` fails on any identity prefix test elsewhere in the package.\n */\nexport const CONNECTION_SEPARATOR = \"~\";\n\n/** The person key of any identity (a connection identity or a person key). */\nexport function personOf(identity: ParticipantIdentity | string): ParticipantIdentity {\n  const value = String(identity ?? \"\").trim();\n  const cut = value.indexOf(CONNECTION_SEPARATOR);\n  return (cut === -1 ? value : value.slice(0, cut)) as ParticipantIdentity;\n}\n\n/** Do two identities (connections or person keys) name the same person? */\nexport function samePerson(a: ParticipantIdentity | string | null | undefined, b: ParticipantIdentity | string | null | undefined): boolean {\n  if (a == null || b == null) return false;\n  return personOf(a) === personOf(b);\n}\n\n/** The account id behind an identity, or null for a guest or an agent. */\nexport function userIdOfIdentity(identity: ParticipantIdentity | string): string | null {\n  const person = personOf(identity);\n  return person.startsWith(\"user:\") ? person.slice(\"user:\".length) : null;\n}\n\n/** A guest's identity is minted `guest:<something>` by the token route. */\nexport function isGuestIdentity(identity: ParticipantIdentity | string): boolean {\n  return personOf(identity).startsWith(\"guest:\");\n}\n\n/**\n * An AGENT's identity is minted `agent:<capability>:<meeting>` by the server\n * (`services/meet/worker.py`). An agent is never an anonymous \"participant\":\n * it is a product with a name, and a room that cannot say which product is\n * listening has failed the consent notice it is required to carry (D10).\n */\nexport function isAgentIdentity(identity: ParticipantIdentity | string): boolean {\n  return personOf(identity).startsWith(\"agent:\");\n}\n\n/** The note-taker's product name — `services/meet/worker.py::AGENT_DISPLAY_NAME`. */\nexport const NOTE_TAKER_PRODUCT_NAME = \"Matrx note-taker\";\n/** Any other Matrx agent whose dispatch carried no name. */\nexport const AGENT_PRODUCT_NAME = \"Matrx agent\";\n/** Somebody in the room whose name nothing has ever known. */\nexport const UNNAMED_GUEST = \"Unnamed guest\";\n/** The same, for a participant whose identity is not a guest token. */\nexport const UNNAMED_PARTICIPANT = \"Unnamed participant\";\n\n/**\n * The strings THIS MODULE invents when nobody knows a name. They are answers,\n * never facts: `isRealName` refuses them, so a placeholder can never be learned\n * as somebody's name and can never outrank a real name that arrives later.\n *\n * 🚨 This is what makes the roster safe to route through the book. A roster\n * event projects \"Unnamed guest\" for a nameless participant; a durable\n * transcript row then teaches \"Ada Lovelace\"; without this rule the placeholder\n * — a perfectly ordinary-looking string — would win, and the screen would keep\n * saying \"Unnamed guest\" about somebody the meeting plainly knows.\n */\nconst PLACEHOLDER_NAMES: readonly string[] = [\n  NOTE_TAKER_PRODUCT_NAME,\n  AGENT_PRODUCT_NAME,\n  UNNAMED_GUEST,\n  UNNAMED_PARTICIPANT,\n];\n\n/** Is this string one of the placeholders this module produces? */\nexport function isPlaceholderName(name: string | null | undefined): boolean {\n  return typeof name === \"string\" && PLACEHOLDER_NAMES.includes(name.trim());\n}\n\n/** What an identity is called when NOTHING knows a name for it. Never a token. */\nexport function placeholderNameFor(identity: ParticipantIdentity | string): string {\n  const key = String(identity);\n  if (isAgentIdentity(key)) {\n    return key.startsWith(\"agent:note_taker:\") || key.startsWith(\"agent:note-taker\")\n      ? NOTE_TAKER_PRODUCT_NAME\n      : AGENT_PRODUCT_NAME;\n  }\n  return isGuestIdentity(key) ? UNNAMED_GUEST : UNNAMED_PARTICIPANT;\n}\n\n/**\n * Would this string be a real name for this identity? A name equal to the\n * identity is the roster's way of saying it has none.\n */\nexport function isRealName(\n  identity: ParticipantIdentity | string,\n  name: string | null | undefined,\n): boolean {\n  if (typeof name !== \"string\") return false;\n  const trimmed = name.trim();\n  if (trimmed.length === 0) return false;\n  if (trimmed === String(identity)) return false;\n  // Our own answer is not new information. See PLACEHOLDER_NAMES.\n  if (isPlaceholderName(trimmed)) return false;\n  return true;\n}\n\n/**\n * Teach the book one identity's name. Returns the SAME book when nothing was\n * learned, so a store commit can be skipped rather than waking every subscriber\n * on every caption.\n */\nexport function learnName(\n  book: NameBook,\n  identity: ParticipantIdentity | string,\n  name: string | null | undefined,\n): NameBook {\n  const key = String(identity);\n  if (key.length === 0) return book;\n  if (!isRealName(key, name)) return book;\n  const learned = (name as string).trim();\n  if (book[key] === learned) return book;\n  return { ...book, [key]: learned };\n}\n\n/** Teach the book several at once — a roster replace, or a durable read. */\nexport function learnNames(\n  book: NameBook,\n  entries: readonly {\n    identity: ParticipantIdentity | string;\n    displayName?: string | null | undefined;\n  }[],\n): NameBook {\n  let next = book;\n  for (const entry of entries) next = learnName(next, entry.identity, entry.displayName);\n  return next;\n}\n\n/**\n * The name a surface renders for `identity`. Never a raw token, never invented.\n *\n * `preferred` is what the arriving thing itself claimed (a caption's roster\n * lookup, a durable row's `speaker` column); it wins when it is a real name,\n * because it is the freshest, and teaches the book on its way past.\n */\nexport function displayNameFor(\n  book: NameBook,\n  identity: ParticipantIdentity | string,\n  preferred?: string | null | undefined,\n): string {\n  const key = String(identity);\n  if (isRealName(key, preferred)) return (preferred as string).trim();\n  const known = book[key];\n  if (known !== undefined) return known;\n  // NOBODY KNOWS, AND THAT IS WHAT IT SAYS. A person reading this can tell the\n  // difference between \"someone whose name we never learned\" and a name.\n  return placeholderNameFor(key);\n}\n","/**\n * RECORDING — LiveKit Egress, host-controlled, consent-enforced (R3/R5).\n *\n * 🚨 **CONSENT IS NOT OPTIONAL AND NOT A PROP.** There is no\n * `showRecordingIndicator={false}`. Recording a person without telling them is\n * illegal in a two-party-consent jurisdiction and is indefensible everywhere\n * else, so the indicator and the join-time notice are properties of the\n * package, not decisions a consumer gets to make. The only knob is the org's\n * `recordingPolicy` — disabled / host-controlled / always-on — which decides\n * whether recording may happen at all, never whether people are told.\n *\n * 🚨 **THE RECORDING BELONGS TO THE PLATFORM, NOT TO LIVEKIT.** The server\n * lands the artifact in the platform files system and returns a FILE ID. A\n * provider URL would be an orphan the day the room is garbage collected — the\n * reason `RecordingRecord.fileId` is not `url`.\n *\n * The client half is small on purpose: start/stop are aidream calls (the API\n * secret never comes near a browser), and the truth about a recording arrives\n * from the server's webhook through the room channel. This module never\n * *guesses* that a recording started.\n */\n\nimport type { MeetApi } from \"./api\";\nimport { MeetError } from \"./errors\";\nimport type { MeetStore } from \"./store\";\nimport { MEET_ROUTES } from \"./tokens\";\nimport type {\n  MeetingId,\n  MeetingRecord,\n  RecordingState,\n  RoomName,\n  UserId,\n} from \"./types\";\n\nexport interface RecordingControllerOptions {\n  /** The ONE org-aware aidream client (MRI-A16). Owns base url and headers. */\n  api: MeetApi;\n  store: MeetStore;\n  /** Announce the new state to everyone in the room (the indicator is for all). */\n  announce?: ((state: RecordingState, by: UserId | null) => void) | undefined;\n  /** Persist that this participant saw the notice. Consent is RECORDED (R5). */\n  acknowledgeConsent?: ((meetingId: MeetingId) => Promise<void>) | undefined;\n}\n\nexport interface RecordingController {\n  /** True when the org policy and the actor's role allow starting a recording. */\n  canStart(meeting: MeetingRecord | null, isHost: boolean): boolean;\n  start(args: { meetingId: MeetingId; roomName: RoomName; by: UserId }): Promise<void>;\n  stop(args: { meetingId: MeetingId; by: UserId }): Promise<void>;\n  /** The join-time notice text. One sentence, one place, every surface. */\n  consentNotice(meeting: MeetingRecord | null): string | null;\n  acknowledge(meetingId: MeetingId): Promise<void>;\n}\n\nexport function createRecordingController(\n  options: RecordingControllerOptions,\n): RecordingController {\n  async function post(route: string, body: Record<string, unknown>): Promise<void> {\n    let response: Response;\n    try {\n      response = await options.api.request({\n        path: route,\n        method: \"POST\",\n        // A GUEST CAN NEVER START OR STOP A RECORDING (R5) — refused here,\n        // before the wire, with the same sentence the hidden control implies.\n        requireAuth: true,\n        operation: \"meet.recording\",\n        body,\n      });\n    } catch (error) {\n      if ((error as { code?: string }).code === \"session-unavailable\") {\n        throw new MeetError(\n          \"forbidden\",\n          \"meet.recording: recording requires an authenticated host\",\n          \"A guest can never start or stop a recording (R5). The control is hidden for guests.\",\n        );\n      }\n      throw error;\n    }\n    if (response.status === 403) {\n      throw new MeetError(\n        \"forbidden\",\n        \"meet.recording: the server refused this recording action\",\n        \"The actor is not a host of this meeting, or the org policy is `disabled`. The server \" +\n          \"is the authority; do not re-decide it on the client.\",\n      );\n    }\n    if (!response.ok) {\n      throw new MeetError(\n        \"transport\",\n        `meet.recording: the server returned ${response.status}`,\n        \"Egress could not be controlled. The recording state stays where it was rather than \" +\n          \"showing a recording indicator for a recording that is not running.\",\n      );\n    }\n  }\n\n  return {\n    canStart(meeting, isHost) {\n      if (meeting === null) return false;\n      if (meeting.recordingPolicy === \"disabled\") return false;\n      // `always-on` is started by the SERVER when the room opens; a host cannot\n      // start (or stop) it, which is the point of the policy.\n      if (meeting.recordingPolicy === \"always-on\") return false;\n      return isHost;\n    },\n\n    async start({ meetingId, roomName, by }) {\n      // OPTIMISTIC ONLY AS FAR AS \"starting\", and marked `\"local\"` so the\n      // durable row overrules it the moment it lands (D16). The indicator turns\n      // solid when the SERVER says the egress is running — never on a client's\n      // hope, and never STUCK on that hope either: `meet_recordings` is\n      // subscribed and the room state carries it to the guests (S8).\n      options.store.setRecording(\"starting\", by, \"local\");\n      try {\n        await post(MEET_ROUTES.recordingStart, {\n          meeting_id: meetingId,\n          room_name: roomName,\n        });\n      } catch (error) {\n        options.store.setRecording(\"idle\", null, \"local\");\n        throw error;\n      }\n      options.announce?.(\"starting\", by);\n    },\n\n    async stop({ meetingId, by }) {\n      options.store.setRecording(\"stopping\", options.store.snapshot().recordingStartedBy, \"local\");\n      try {\n        await post(MEET_ROUTES.recordingStop, { meeting_id: meetingId });\n      } catch (error) {\n        options.store.setRecording(\n          \"recording\",\n          options.store.snapshot().recordingStartedBy,\n          \"local\",\n        );\n        throw error;\n      }\n      options.announce?.(\"stopping\", by);\n    },\n\n    consentNotice(meeting) {\n      if (meeting === null || meeting.recordingPolicy === \"disabled\") return null;\n      if (meeting.recordingPolicy === \"always-on\") {\n        return \"This meeting is recorded and transcribed automatically. By joining, you consent to being recorded.\";\n      }\n      return \"The host can record and transcribe this meeting. You will see a recording indicator whenever it is running.\";\n    },\n\n    async acknowledge(meetingId) {\n      await options.acknowledgeConsent?.(meetingId);\n    },\n  };\n}\n\n/**\n * 🚨 IS A RECORDING IN FLIGHT RIGHT NOW? One definition (MRI-A16).\n *\n * The control used to ask `state === \"idle\"`, which was survivable only while\n * the store never learned any state but its own: the moment the DURABLE states\n * started arriving, a meeting whose first recording had finished sat on\n * `available` forever and the host could never start a second one — the Start\n * button simply stopped existing. `processing`, `available` and `failed` all\n * mean \"nothing is recording\"; only these three mean it is.\n */\nexport const RECORDING_IN_FLIGHT: readonly RecordingState[] = [\n  \"starting\",\n  \"recording\",\n  \"stopping\",\n];\n\nexport function isRecordingInFlight(state: RecordingState): boolean {\n  return RECORDING_IN_FLIGHT.includes(state);\n}\n\n/** The indicator's words. One definition, so no surface invents a softer one. */\nexport function recordingLabel(state: RecordingState): string | null {\n  switch (state) {\n    case \"starting\":\n      return \"Starting recording…\";\n    case \"recording\":\n      return \"Recording\";\n    case \"stopping\":\n      return \"Stopping recording…\";\n    case \"processing\":\n      return \"Processing recording…\";\n    case \"available\":\n      return \"Recording ready\";\n    case \"expired\":\n      return \"Recording expired\";\n    case \"failed\":\n      return \"Recording failed\";\n    default:\n      return null;\n  }\n}\n","/**\n * THE RULES A SCREEN REDRAWS FROM WHILE THE CALL IS RUNNING (P1: chat-restrictions,\n * mod-attendee-av-disabled, time-limit-warning, rec-consent-gate).\n *\n * The host can change a meeting's rules mid-call through the meeting's own rules door, which\n * never talks to the room. The server's state read answers the live values (`live_policy`), and\n * the room reads it on a short timer while the person is in the call — so a rule changed at\n * second 40 is on every screen within one poll. Pure functions here; the timer lives in\n * `meetings.ts`.\n */\n\nimport type { ParticipantRole } from \"./types\";\n\nexport type ChatMode = \"everyone\" | \"hosts_only\" | \"off\";\nexport type AvLock = \"off\" | \"mic\" | \"camera\" | \"both\";\nexport type RecordingConsent = \"notice\" | \"ok_or_leave\" | \"view_only_until_agree\";\n/** Who may share a screen (`share_who_can`) and how many may at once (`share_concurrency`). */\nexport type ShareWhoCan = \"everyone\" | \"host_only\" | \"org\" | \"presenters\";\nexport type ShareConcurrency = \"one_takeover\" | \"one_replace\" | \"multiple\";\n\n/** What remains when no host or co-host is in the room (`headless_powers`, CORE-DESIGN §4.2). */\nexport type HeadlessPowers = \"members_admit\" | \"none\" | \"cohosts_only\";\n\nexport interface LivePolicy {\n  readonly headlessPowers: HeadlessPowers;\n  readonly chatMode: ChatMode;\n  readonly avLock: AvLock;\n  /** 0 = no limit. */\n  readonly timeLimitMinutes: number;\n  readonly timeLimitWarningMinutes: number;\n  readonly recordingConsent: RecordingConsent;\n  readonly shareWhoCan: ShareWhoCan;\n  readonly shareConcurrency: ShareConcurrency;\n}\n\nexport const DEFAULT_LIVE_POLICY: LivePolicy = {\n  headlessPowers: \"members_admit\",\n  chatMode: \"everyone\",\n  avLock: \"off\",\n  timeLimitMinutes: 0,\n  timeLimitWarningMinutes: 5,\n  recordingConsent: \"notice\",\n  shareWhoCan: \"everyone\",\n  shareConcurrency: \"one_takeover\",\n};\n\nfunction oneOf<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {\n  return typeof value === \"string\" && (allowed as readonly string[]).includes(value) ? (value as T) : fallback;\n}\n\nfunction whole(value: unknown, fallback: number): number {\n  const n = typeof value === \"number\" ? value : typeof value === \"string\" ? Number(value) : NaN;\n  return Number.isFinite(n) && n >= 0 ? Math.floor(n) : fallback;\n}\n\n/** Reads the server's `live_policy` object; a key it did not send keeps its default. */\nexport function livePolicyFrom(raw: unknown): LivePolicy {\n  const o = typeof raw === \"object\" && raw !== null ? (raw as Record<string, unknown>) : {};\n  return {\n    headlessPowers: oneOf(o[\"headless_powers\"], [\"members_admit\", \"none\", \"cohosts_only\"], DEFAULT_LIVE_POLICY.headlessPowers),\n    chatMode: oneOf(o[\"chat_mode\"], [\"everyone\", \"hosts_only\", \"off\"], DEFAULT_LIVE_POLICY.chatMode),\n    avLock: oneOf(o[\"attendee_av_lock\"], [\"off\", \"mic\", \"camera\", \"both\"], DEFAULT_LIVE_POLICY.avLock),\n    timeLimitMinutes: whole(o[\"time_limit_minutes\"], 0),\n    timeLimitWarningMinutes: whole(o[\"time_limit_warning_minutes\"], DEFAULT_LIVE_POLICY.timeLimitWarningMinutes),\n    recordingConsent: oneOf(\n      o[\"recording_consent\"],\n      [\"notice\", \"ok_or_leave\", \"view_only_until_agree\"],\n      DEFAULT_LIVE_POLICY.recordingConsent,\n    ),\n    shareWhoCan: oneOf(o[\"share_who_can\"], [\"everyone\", \"host_only\", \"org\", \"presenters\"], DEFAULT_LIVE_POLICY.shareWhoCan),\n    shareConcurrency: oneOf(o[\"share_concurrency\"], [\"one_takeover\", \"one_replace\", \"multiple\"], DEFAULT_LIVE_POLICY.shareConcurrency),\n  };\n}\n\nexport function samePolicy(a: LivePolicy, b: LivePolicy): boolean {\n  return (\n    a.headlessPowers === b.headlessPowers &&\n    a.chatMode === b.chatMode &&\n    a.avLock === b.avLock &&\n    a.timeLimitMinutes === b.timeLimitMinutes &&\n    a.timeLimitWarningMinutes === b.timeLimitWarningMinutes &&\n    a.recordingConsent === b.recordingConsent &&\n    a.shareWhoCan === b.shareWhoCan &&\n    a.shareConcurrency === b.shareConcurrency\n  );\n}\n\nconst MODERATORS: ReadonlySet<ParticipantRole> = new Set([\"host\", \"cohost\"]);\n\n/** Hosts and co-hosts are never locked. */\nexport function isLockedFor(policy: LivePolicy, role: ParticipantRole, kind: \"microphone\" | \"camera\"): boolean {\n  if (MODERATORS.has(role)) return false;\n  return policy.avLock === \"both\" || (kind === \"microphone\" ? policy.avLock === \"mic\" : policy.avLock === \"camera\");\n}\n\n/**\n * share-who-can: may this person share a screen under the meeting's current rule? Mirrors the\n * server's `sharing.may_share` (which is what actually decides); this only decides whether the\n * control is drawn. A word the package does not know leaves it open.\n */\nexport function canShareUnder(\n  policy: LivePolicy,\n  role: ParticipantRole,\n  standing: \"member\" | \"invited\" | \"outsider\" | \"guest\" | null,\n): boolean {\n  if (role === \"viewer\") return false;\n  if (MODERATORS.has(role)) return true;\n  switch (policy.shareWhoCan) {\n    case \"host_only\":\n      return false;\n    case \"presenters\":\n      return role === \"presenter\";\n    case \"org\":\n      return role === \"presenter\" || standing === \"member\";\n    default:\n      return true;\n  }\n}\n\n/**\n * rec-consent-gate: the person has not yet agreed to being recorded, under a rule that makes them\n * wait (`ok_or_leave` shows a dialog, `view_only_until_agree` also takes the microphone and camera).\n */\nexport function consentPending(policy: LivePolicy, role: ParticipantRole, recordingOn: boolean, given: boolean): boolean {\n  return recordingOn && !given && policy.recordingConsent !== \"notice\" && !MODERATORS.has(role);\n}\n\n/** May this role write in the chat under the meeting's current mode? */\nexport function canChat(policy: LivePolicy, role: ParticipantRole): boolean {\n  if (policy.chatMode === \"everyone\") return true;\n  return policy.chatMode === \"hosts_only\" && MODERATORS.has(role);\n}\n\n/** Whole minutes left before the time limit, or null with no limit / unknown start. */\nexport function minutesLeft(policy: LivePolicy, startedAtMs: number | null, nowMs: number): number | null {\n  if (policy.timeLimitMinutes <= 0 || startedAtMs === null) return null;\n  return Math.ceil((startedAtMs + policy.timeLimitMinutes * 60_000 - nowMs) / 60_000);\n}\n\n/**\n * May this person let waiting people in right now? A host or co-host always may. When NO host or\n * co-host is in the room, the meeting's `headless_powers` decides: `members_admit` lets any admitted\n * member (the server's door enforces the same rule); `none` and `cohosts_only` add nobody.\n * (meeting-without-host)\n */\nexport function mayAdmitNow(\n  role: ParticipantRole | \"none\",\n  participants: readonly { readonly role: ParticipantRole }[],\n  policy: LivePolicy,\n): boolean {\n  if (role === \"none\") return false;\n  if (role === \"host\" || role === \"cohost\") return true;\n  if (role === \"viewer\") return false;\n  const hostIn = participants.some((p) => p.role === \"host\" || p.role === \"cohost\");\n  return !hostIn && policy.headlessPowers === \"members_admit\";\n}\n","/**\n * LISTEN-ONLY ATTENDANCE — being IN the room is never contingent on a device.\n *\n * 0.3.1 and every version before it enabled the microphone as the last step of\n * `connect()`, inside the same `try` as the join. So a denied, absent, or busy\n * microphone did not produce a muted participant — it threw, the join was\n * failed with a device remedy, and the user was dropped back to `<PreJoin>`\n * having never entered the meeting. The whole in-room surface (tiles, captions,\n * live notes, Q&A, the note-taker consent notice) was unreachable to anyone\n * without a working mic, which is ordinary: a locked-down laptop, a conference\n * room dial-in, a phone on a call, a browser profile that denies capture by\n * policy, or a person who simply wants to listen. Every competitor allows it.\n *\n * THE CLASS, and how it is closed here:\n *\n * 1. **Connecting and publishing are two different operations.** The engine\n *    reaches `connected` the moment the transport is up. Media is attempted\n *    AFTER that, per track, and a rejection never unwinds the join.\n * 2. **A track that could not be acquired is STATE, not an exception.** The\n *    reason and its remedy — the browser's own, translated by\n *    `normalizeDeviceError` — ride in the snapshot so the UI says WHY the mic\n *    is off instead of showing a mute button that silently does nothing.\n * 3. **Enabling later runs the SAME code path.** `setMicrophoneEnabled(true)`\n *    from the control bar records exactly what the join attempt records, so a\n *    person who plugs in a headset mid-meeting is one click from speaking and\n *    a person whose second attempt also fails gets the same honest sentence.\n *    A separate \"retry\" path is how the two drift.\n * 4. **The notice is one sentence, defined once.** Both the package's own room\n *    chrome and any host that renders its own read `listenOnlyNotice()`, so\n *    there is no second wording to keep in sync.\n */\n\nimport type { MeetError } from \"./errors\";\n\n/**\n * WHY a device is unusable, in the contract's words (CORE-DESIGN §3.2, the `mic` / `camera`\n * region's `unavailable:<reason>`). The media supervisor (`media-supervisor.ts`) decides it from\n * the browser's error AND the Permissions API, because the error alone cannot tell a person's\n * Block from an operating-system refusal or a stale device id.\n */\nexport type DeviceUnavailableReason =\n  | \"denied\"\n  | \"blocked_site\"\n  | \"blocked_os\"\n  | \"none\"\n  | \"busy\"\n  | \"failed\"\n  | \"revoked\";\n\n/** Why a local track is not publishing, in the browser's terms plus a remedy. */\nexport interface MediaUnavailable {\n  readonly code: string;\n  readonly message: string;\n  readonly remedy: string;\n  /** The region reason (S6c). Absent on states recorded before the supervisor classified them. */\n  readonly reason?: DeviceUnavailableReason | undefined;\n}\n\n/** What the browser's permission store says for one device kind. `unknown` = no Permissions API. */\nexport type PermissionReading = \"granted\" | \"denied\" | \"prompt\" | \"unknown\";\n\n/** A device change the person is told about (S6c): unplugged → switched, or nothing left. */\nexport interface DeviceNotice {\n  readonly id: number;\n  readonly kind: \"microphone\" | \"camera\";\n  /** `switched` = the meeting moved to another device; `lost` = none of this kind is left. */\n  readonly outcome: \"switched\" | \"lost\";\n  /** The device that went away, by label (empty when the browser hid labels). */\n  readonly from: string;\n  /** The device that went away, by id, so Undo can go back to it if it is plugged in again. */\n  readonly fromId?: string | undefined;\n  /** The device now in use (`switched` only). */\n  readonly to: string | null;\n}\n\n/** A device that just appeared — offered, never switched to silently (catalog `device-default-changed`). */\nexport interface DeviceOffer {\n  readonly kind: \"microphone\" | \"camera\";\n  readonly deviceId: string;\n  readonly label: string;\n}\n\n/**\n * THE MEDIA REGIONS THE SUPERVISOR OWNS (CORE-DESIGN §3.2 `audio_output`, and the inputs the\n * `mic` / `camera` regions are derived from). None of it can change the call phase.\n */\nexport interface MediaRegionState {\n  readonly permission: { readonly microphone: PermissionReading; readonly camera: PermissionReading };\n  /** `blocked` = the browser's autoplay policy is holding remote audio until a gesture. */\n  readonly audioOutput: \"ok\" | \"blocked\";\n  readonly notice: DeviceNotice | null;\n  readonly offer: DeviceOffer | null;\n  /**\n   * THE PRE-JOIN CHECK per kind (P1 `perm-prompt-pending`, `perm-blocked-site`, `device-none-found`,\n   * `device-busy`): what the preview found BEFORE the room exists. `prompting` = the browser was\n   * asked and has not answered (Join stays usable); `unavailable` carries the classified refusal.\n   */\n  readonly preview: { readonly microphone: DevicePreview; readonly camera: DevicePreview };\n}\n\n/** One kind's pre-join check. `idle` = nothing was tried (or the person turned it off before). */\nexport interface DevicePreview {\n  readonly state: \"idle\" | \"prompting\" | \"on\" | \"off\" | \"unavailable\";\n  readonly unavailable: MediaUnavailable | null;\n}\n\nexport const IDLE_PREVIEW: DevicePreview = { state: \"idle\", unavailable: null };\n\nexport const IDLE_MEDIA_REGION: MediaRegionState = {\n  permission: { microphone: \"unknown\", camera: \"unknown\" },\n  audioOutput: \"ok\",\n  notice: null,\n  offer: null,\n  preview: { microphone: IDLE_PREVIEW, camera: IDLE_PREVIEW },\n};\n\nexport interface LocalTrackState {\n  /** True only when the track is actually published. Never optimistic. */\n  readonly enabled: boolean;\n  /**\n   * Set when acquisition was ATTEMPTED and refused. `null` covers both \"on\"\n   * and \"deliberately off\" — a user who unchecked the mic in pre-join is not\n   * looking at an error, they are looking at a choice they made.\n   */\n  readonly unavailable: MediaUnavailable | null;\n}\n\nexport interface LocalMediaState {\n  readonly microphone: LocalTrackState;\n  readonly camera: LocalTrackState;\n}\n\nexport const IDLE_TRACK: LocalTrackState = { enabled: false, unavailable: null };\n\nexport const IDLE_MEDIA: LocalMediaState = {\n  microphone: IDLE_TRACK,\n  camera: IDLE_TRACK,\n};\n\nexport function unavailableFrom(error: MeetError, reason?: DeviceUnavailableReason): MediaUnavailable {\n  return reason === undefined\n    ? { code: error.code, message: error.message, remedy: error.remedy }\n    : { code: error.code, message: error.message, remedy: error.remedy, reason };\n}\n\n/**\n * THE SENTENCE. One definition, so the room chrome, a host's own chrome and the\n * tests cannot say three different things about the same fact.\n */\nexport const LISTEN_ONLY_NOTICE =\n  \"You're attending without a microphone — others can't hear you\";\n\n/**\n * True when this participant is in the room with NO USABLE microphone — the\n * device was refused or is missing. A person who simply muted themselves has a\n * working microphone and is not \"attending without\" one, so a mute never\n * counts: `unavailable` is the only signal.\n */\nexport function isListenOnly(media: LocalMediaState): boolean {\n  return !media.microphone.enabled && media.microphone.unavailable !== null;\n}\n\n/**\n * The notice to render while in the room, or `null` when the mic is live.\n * Returns the plain sentence; the reason and remedy, when there is one, are\n * rendered beside it from `media.microphone.unavailable`.\n */\nexport function listenOnlyNotice(media: LocalMediaState): string | null {\n  return isListenOnly(media) ? LISTEN_ONLY_NOTICE : null;\n}\n","/**\n * THE DATA CONTRACT — the ONE place a meet table or RPC name exists.\n *\n * 🚨 **STATE OF THE SCHEMA (read this before believing a green test).** The\n * `communication.meet_*` tables below are the canonical schema DESIGNED by this\n * package per R8; they are **not deployed to Matrx Main yet**. They were placed\n * by inspecting the live database on 2026-08-31: `communication` is the schema\n * that already holds `dm_*` (messaging) and `sms_*` (telephony), so meet takes\n * the `meet_*` prefix in the same schema rather than inventing a new one. Until\n * the migration lands, every read here fails LOUDLY with `not-found` and a\n * remedy naming this file — never silently, and never with a fabricated row.\n * The migration and the aidream server half are one deliverable; see FEATURE.md\n * § Deliberately NOT in this package.\n *\n * Four rules hold this file together — the same four that hold messaging's:\n *\n * 1. **Org is explicit on every write (R5).** Not defaulted by a trigger we\n *    hope fires — passed, and refused in-package when absent.\n * 2. **Authorization is the database's job.** There is no permission branch in\n *    this file. An RPC that says no is a `forbidden` MeetError, never a\n *    client-side re-decision. Guest capability is scoped by the room TOKEN, not\n *    by a row this client could write.\n * 3. **Writes go through SECURITY DEFINER RPCs; reads are RLS-backed table\n *    reads** (C17's hybrid ruling). Every write here is an RPC, which is also\n *    what keeps admission and settle-a-call ATOMIC — two hosts clicking \"admit\"\n *    and a callee accepting on two devices are the ordinary case, not the edge.\n * 4. **Pagination is keyset, terminated by a unique column.** `(created_at,\n *    id)` — never a timestamp alone, which duplicates or skips rows whenever\n *    two share a millisecond.\n *\n * The Supabase client is accepted STRUCTURALLY, through the shape\n * `@ai-matrx/messaging` already owns. One definition of \"a Supabase client\" for\n * the whole communications family; this package adds no second copy.\n *\n * 🚨 AND THE PUBLIC BOUNDARY IS THE SHALLOW ONE (0.2.1). `RepositoryOptions`\n * and `<MeetProvider client>` take `MessagingSupabaseClient` — method names and\n * arity, results as `unknown` — never the rich `SupabaseLike`. Checking a\n * host's real `SupabaseClient<Database>` (built from generated types) against\n * the rich shape makes tsc chase PostgREST's schema machinery until it bails\n * with `TS2589: Type instantiation is excessively deep and possibly infinite`,\n * so the only way to pass the client a host ALREADY HAS was a cast — which is\n * what the first real consumer had to write (register MRI-D1). Messaging 0.9.0\n * learned this and wrote it down; this package did not apply the lesson until\n * now. The rich shape stays the INTERNAL contract, and we narrow to it ONCE,\n * here, in-package.\n */\n\nimport { scheduleSettingsPatch } from \"./app-panel\";\nimport type { MessagingSupabaseClient, SupabaseLike } from \"@ai-matrx/messaging\";\nimport { invalidMeetResponse, MeetError, normalizeMeetError } from \"./errors\";\nimport {\n  asCallId,\n  asMeetingId,\n  asOrganizationId,\n  asParticipantIdentity,\n  asRoomName,\n  asUserId,\n  type CallId,\n  type CallInvite,\n  type CallMode,\n  type CallState,\n  type JsonObject,\n  type MeetingId,\n  type MeetingKind,\n  type MeetingAttendee,\n  type MeetingNote,\n  type LinkRunState,\n  type MeetingRecord,\n  type ParticipantRole,\n  type AdmissionState,\n  type OrganizationId,\n  type RecordingPolicy,\n  type RecordingRecord,\n  type RecordingRetention,\n  type RecordingState,\n  type RoomName,\n  type TranscriptSegment,\n  type UserId,\n  type InviteeInput,\n  type InviteeRole,\n  type MeetingChanges,\n  type AttendanceStay,\n  type MeetingInvitee,\n  type MeetingOccurrence,\n  type MeetingSettings,\n  type OccurrenceOverride,\n  type OccurrenceState,\n  type RsvpAnswer,\n  type RsvpInvitation,\n  type RsvpState,\n  type UpcomingOccurrence,\n} from \"./types\";\n\n/** The schema. Meet is never in `public`. */\nexport const MEET_SCHEMA = \"communication\";\n\nexport const MEET_TABLES = {\n  meetings: \"meet_meetings\",\n  participants: \"meet_participants\",\n  invites: \"meet_call_invites\",\n  recordings: \"meet_recordings\",\n  transcripts: \"meet_transcript_segments\",\n  notes: \"meet_notes\",\n  /** Wave 1 (0.8): who a meeting was sent to, and what they answered. */\n  invitees: \"meet_invitees\",\n  /** Wave 1 (0.8): one occurrence of a series canceled or moved. */\n  occurrenceOverrides: \"meet_occurrence_overrides\",\n  /** S5: one row per RUN of a meeting; carries that run's note-taker state. */\n  sessions: \"meet_sessions\",\n} as const;\n\nexport const MEET_RPCS = {\n  /** Atomic: create the invite row and stamp its expiry in one statement. */\n  createCallInvite: \"meet_create_call_invite\",\n  /** Atomic settle. Refuses a transition out of a terminal state. */\n  settleCallInvite: \"meet_settle_call_invite\",\n  /** Every invite still ringing this user — the reconnect backfill door. */\n  pendingCallInvites: \"meet_pending_call_invites\",\n  /** Instant meeting, or the durable one behind a recurring link. */\n  getOrCreateMeeting: \"meet_get_or_create_meeting\",\n  /** Resolve a durable public link, before/during/after its scheduled time. */\n  meetingBySlug: \"meet_meeting_by_slug\",\n  /** The current run of a durable link (open / not started / ended + next start), no pass needed. */\n  linkState: \"meet_link_state\",\n  /*\n   * ── S4 ADMISSION (CORE-DESIGN §2.4). Each returns the decided row; the caller then\n   * sends the payload-free `mx.state.changed` hint. Authorized by `who_may_admit`.\n   */\n  admit: \"meet_admit\",\n  deny: \"meet_deny\",\n  undeny: \"meet_undeny\",\n  admitAll: \"meet_admit_all\",\n  setLock: \"meet_set_lock\",\n  recordConsent: \"meet_record_consent\",\n  /** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */\n  meetingRule: \"meet_policy\",\n  /** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */\n  setMeetingRule: \"meet_policy_set\",\n  /*\n   * ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door\n   * authorized by the meeting's host or a real iam grant (editor to change,\n   * admin = co-host to archive or name a co-host) — never an organization\n   * match. After any of these writes, call `announceMeeting` so the server\n   * sends invitations / updates / cancellations and re-queues reminders.\n   */\n  /** Schedule with every setting at create; unset settings come from the knobs. */\n  scheduleMeeting: \"meet_schedule_meeting\",\n  /** Edit / reschedule — a JSON patch with a version compare-and-swap. */\n  updateMeeting: \"meet_update_meeting\",\n  /** Cancel is a state (`cancelled_at`); the link keeps resolving. */\n  cancelMeeting: \"meet_cancel_meeting\",\n  /** Archive (soft delete) — the invitations and exceptions cascade. */\n  archiveMeeting: \"meet_archive_meeting\",\n  restoreMeeting: \"meet_restore_meeting\",\n  /** Cancel, move or restore ONE occurrence of a series by its original start. */\n  setOccurrence: \"meet_set_occurrence\",\n  addInvitees: \"meet_add_invitees\",\n  setInviteeRole: \"meet_set_invitee_role\",\n  removeInvitee: \"meet_remove_invitee\",\n  /** A signed-in invitee answers for themselves. */\n  respond: \"meet_respond\",\n  /** The emailed RSVP link (no account): read and answer. */\n  invitationByToken: \"meet_invitation_by_token\",\n  respondByToken: \"meet_respond_by_token\",\n  /** One meeting's occurrences between two instants (INVOKER — the reader's RLS). */\n  meetingOccurrences: \"meet_meeting_occurrences\",\n  /** Every occurrence the reader can see between two instants — the Upcoming list. */\n  occurrencesBetween: \"meet_occurrences_between\",\n  /*\n   * ── MEET WAVE 3 — after the meeting. Both INVOKER (the reader's RLS) and both\n   * scoped to the reader's OWN meetings (host, invitee, attended) — RLS is the\n   * ceiling, never the view.\n   */\n  /** The recordings library. */\n  myRecordings: \"meet_my_recordings\",\n  /** Titles, agendas, current notes and final transcript lines; snippets mark hits with ⟦ ⟧. */\n  search: \"meet_search\",\n} as const;\n\n/**\n * THE RPCs THAT RETURN NOTHING, verified against the live database\n * (`pg_get_function_result`, 2026-09-08). They go through `guardVoid`; every\n * other RPC returns a row and goes through `guard`. Wiring a void RPC to\n * `guard` makes a SUCCESSFUL write look like a failure — see `guardVoid`.\n */\nexport const VOID_RPCS: readonly string[] = [MEET_RPCS.recordConsent];\n\nconst MEETING_COLUMNS =\n  \"id,organization_id,room_name,slug,title,kind,host_user_id,scheduled_for,\" +\n  \"scheduled_duration_minutes,started_at,ended_at,locked,lobby_enabled,\" +\n  \"recording_policy,ai_enabled,metadata,\" +\n  // Wave 1 (0.8).\n  \"time_zone,agenda,recurrence_rule,join_before_host,cancelled_at,cancellation_reason,\" +\n  \"deleted_at,calendar_sequence,version\";\n\nconst INVITEE_COLUMNS =\n  \"id,meeting_id,invitee_user_id,email,display_name,role,rsvp_state,responded_at,\" +\n  \"rsvp_note,last_sent_sequence,last_sent_at\";\n\n/**\n * The invite row's columns. Not used by a `select` today — every invite read\n * and write goes through an RPC (C17's hybrid: writes are SECURITY DEFINER,\n * and a settle must be atomic) — but it is part of the contract S2's migration\n * has to satisfy, and it is what `projectInvite` reads out of an RPC's return\n * row. Keep it in step with that function.\n */\nconst INVITE_COLUMNS =\n  \"id,organization_id,room_name,mode,caller_user_id,caller_name,caller_avatar_url,\" +\n  \"callee_ids,conversation_id,created_at,expires_at,state,decline_message\";\n\nconst RECORDING_COLUMNS =\n  \"id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason\";\n\n/**\n * THE TRANSCRIPT'S COLUMNS. `is_final` — not `final` — is the live column name,\n * and only final rows are ever written (D6: an interim is a caption and a\n * caption is never persisted).\n */\nconst SEGMENT_COLUMNS = \"id,meeting_id,identity,speaker,text,started_at,is_final,metadata\";\n\n/** What the meeting decided. `kind` is a three-value CHECK constraint (D5). */\nconst NOTE_COLUMNS = \"id,meeting_id,text,kind,assignee_user_id,created_at,metadata\";\n\n/**\n * WHO WAS THERE. The row survives the room, which is the whole point: an\n * attendance list that only exists while LiveKit holds the room is not a record\n * of anything (MRI-D2).\n */\nconst ATTENDEE_COLUMNS =\n  \"id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,\" +\n  \"admission_state,knocked_at,knock_expires_at,is_agent,joined_at,left_at,sessions:metadata->sessions,\" +\n  \"knock_flag:metadata->>knock_flag\";\n\ntype Row = Record<string, unknown>;\n\n/** `metadata.sessions` → stays; anything malformed is skipped, never guessed. */\nfunction projectStays(value: unknown): readonly AttendanceStay[] {\n  if (!Array.isArray(value)) return [];\n  const stays: AttendanceStay[] = [];\n  for (const item of value) {\n    if (item === null || typeof item !== \"object\") continue;\n    const joined = (item as Row)[\"joined_at\"];\n    const left = (item as Row)[\"left_at\"];\n    if (typeof joined !== \"string\" || joined.length === 0) continue;\n    stays.push({ joinedAt: joined, leftAt: typeof left === \"string\" && left.length > 0 ? left : null });\n  }\n  return stays;\n}\n\nfunction text(row: Row, key: string): string | null {\n  const value = row[key];\n  return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction requireText(row: Row, key: string, operation: string): string {\n  const value = text(row, key);\n  if (value === null) {\n    throw invalidMeetResponse(operation, `the row is missing \"${key}\"`);\n  }\n  return value;\n}\n\nfunction bool(row: Row, key: string, fallback: boolean): boolean {\n  const value = row[key];\n  return typeof value === \"boolean\" ? value : fallback;\n}\n\nfunction stringArray(row: Row, key: string): readonly string[] {\n  const value = row[key];\n  if (!Array.isArray(value)) return [];\n  return value.filter((entry): entry is string => typeof entry === \"string\");\n}\n\nconst CALL_STATES: readonly CallState[] = [\n  \"idle\",\n  \"dialing\",\n  \"ringing\",\n  \"connecting\",\n  \"active\",\n  \"declined\",\n  \"missed\",\n  \"busy\",\n  \"cancelled\",\n  \"ended\",\n  \"failed\",\n];\n\nfunction callState(value: string | null): CallState {\n  return CALL_STATES.includes(value as CallState) ? (value as CallState) : \"failed\";\n}\n\nexport interface CreateCallInviteInput {\n  readonly roomName: RoomName;\n  readonly mode: CallMode;\n  readonly callerUserId: UserId;\n  readonly callerName: string;\n  readonly callerAvatarUrl: string | null;\n  readonly calleeUserIds: readonly UserId[];\n  readonly organizationId: OrganizationId;\n  readonly conversationId: string | null;\n  readonly expiresAt: string;\n}\n\nexport interface CreateMeetingInput {\n  readonly organizationId: OrganizationId;\n  readonly hostUserId: UserId;\n  readonly title: string;\n  readonly kind: MeetingKind;\n  readonly scheduledFor?: string | null;\n  readonly scheduledDurationMinutes?: number | null;\n  readonly lobbyEnabled?: boolean;\n  readonly recordingPolicy?: RecordingPolicy;\n  readonly aiEnabled?: boolean;\n  /** Reuse a durable slug (a recurring meeting keeps ONE link — R3). */\n  readonly slug?: string | undefined;\n}\n\nexport interface MeetRepository {\n  readonly schema: string;\n  readonly tables: typeof MEET_TABLES;\n  projectInvite(row: Row): CallInvite;\n  projectMeeting(row: Row): MeetingRecord;\n  createCallInvite(input: CreateCallInviteInput): Promise<CallInvite>;\n  settleCallInvite(id: CallId, state: CallState, declineMessage: string | null): Promise<CallInvite>;\n  pendingInvites(userId: UserId): Promise<readonly CallInvite[]>;\n  getOrCreateMeeting(input: CreateMeetingInput): Promise<MeetingRecord>;\n  meetingBySlug(slug: string): Promise<MeetingRecord>;\n  meeting(id: MeetingId): Promise<MeetingRecord>;\n  /**\n   * Keyset paged, `(scheduled_for, id)`. Every meeting the person can access, in\n   * ALL their organizations — `organizationId` is an OPTIONAL page filter\n   * (absent/null = all organizations), never the active organization\n   * (active-org-is-never-a-list-filter.md). Access is decided by RLS.\n   */\n  listMeetings(args: {\n    organizationId?: OrganizationId | null;\n    limit?: number;\n    before?: { scheduledFor: string; id: MeetingId } | null;\n  }): Promise<{ readonly items: readonly MeetingRecord[]; readonly hasMore: boolean }>;\n  /** S4: one decision on one waiting person; returns the row as it now stands. */\n  decideAdmission(args: {\n    meetingId: MeetingId;\n    identity: string;\n    decision: \"admit\" | \"deny\" | \"undeny\";\n    byUserId: UserId;\n  }): Promise<MeetingAttendee>;\n  /** S4: admit everyone still waiting (not expired); returns the admitted rows. */\n  admitAll(meetingId: MeetingId, byUserId: UserId): Promise<readonly MeetingAttendee[]>;\n  setLock(meetingId: MeetingId, locked: boolean, byUserId: UserId): Promise<MeetingRecord>;\n  /** `wr-policy-who-waits`: read one rule of this meeting (`lobby_bypass`, `access_type`…). */\n  meetingRule(meetingId: MeetingId, key: string): Promise<unknown>;\n  /** A host sets one rule for this meeting; a refusal throws with the server's sentence. */\n  setMeetingRule(meetingId: MeetingId, key: string, value: string | number | boolean): Promise<unknown>;\n  projectSegment(row: Row): TranscriptSegment;\n  projectNote(row: Row): MeetingNote;\n  /** One `meet_recordings` row, however it arrived (row or room packet). */\n  projectRecording(row: Row): RecordingRecord;\n  /** One durable `meet_participants` row — attendance, and the lobby queue. */\n  projectAttendee(row: Row): MeetingAttendee;\n  projectAttendee(row: Row): MeetingAttendee;\n  /**\n   * WHO ATTENDED, oldest arrival first. Everyone the meeting ever admitted —\n   * including the note-taker, which is a labeled participant and never a hidden\n   * listener (R4) — so the record can say who was in the room AND that it was\n   * transcribed.\n   */\n  attendees(meetingId: MeetingId): Promise<readonly MeetingAttendee[]>;\n  /**\n   * THE DURABLE TRANSCRIPT (D16). Final rows only — the table holds nothing\n   * else — oldest first, capped so a four-hour meeting cannot hand a surface\n   * fifty thousand rows in one read.\n   */\n  transcript(meetingId: MeetingId, limit?: number): Promise<readonly TranscriptSegment[]>;\n  /** Live notes, decisions, action items and the wrap-up summary, oldest first. */\n  notes(meetingId: MeetingId): Promise<readonly MeetingNote[]>;\n  /** R5: consent is RECORDED, not assumed. One row per participant per recording. */\n  recordConsent(args: {\n    meetingId: MeetingId;\n    identity: string;\n    acknowledgedAt: string;\n  }): Promise<void>;\n  recordings(meetingId: MeetingId): Promise<readonly RecordingRecord[]>;\n  /** Meet wave 3: every recording of the reader's own meetings, newest first. */\n  myRecordings(args?: { includeArchived?: boolean; limit?: number }): Promise<readonly LibraryRecording[]>;\n  /** Meet wave 3: search the reader's own meetings. */\n  searchMeetings(query: string, limit?: number): Promise<readonly MeetingSearchHit[]>;\n  /** Meet wave 3: name a recording (`null` = back to the meeting's title and date). */\n  renameRecording(recordingId: string, title: string | null): Promise<void>;\n  /** Meet wave 3: archive (soft delete) or restore a recording. Never a purge. */\n  setRecordingArchived(recordingId: string, archived: boolean): Promise<void>;\n\n  /* ── MEET WAVE 1 — management (0.8) ── */\n  scheduleMeeting(input: ScheduleMeetingInput): Promise<MeetingRecord>;\n  /** `expectedVersion` from the row you edited; a stale one is a `conflict`. */\n  updateMeeting(\n    meetingId: MeetingId,\n    changes: MeetingChanges,\n    options?: { expectedVersion?: number | null; byUserId?: UserId | null },\n  ): Promise<MeetingRecord>;\n  cancelMeeting(meetingId: MeetingId, reason: string | null, byUserId?: UserId | null): Promise<MeetingRecord>;\n  archiveMeeting(meetingId: MeetingId, byUserId?: UserId | null): Promise<MeetingRecord>;\n  restoreMeeting(meetingId: MeetingId, byUserId?: UserId | null): Promise<MeetingRecord>;\n  setOccurrence(args: {\n    meetingId: MeetingId;\n    originalStart: string;\n    action: \"cancel\" | \"move\" | \"restore\";\n    newStart?: string | null;\n    newDurationMinutes?: number | null;\n    reason?: string | null;\n    byUserId?: UserId | null;\n  }): Promise<OccurrenceOverride>;\n  meetingOccurrences(\n    meetingId: MeetingId,\n    range: { from: string; to: string; limit?: number },\n  ): Promise<readonly MeetingOccurrence[]>;\n  /** The Upcoming list: every occurrence the reader may see. `organizationId` FILTERS; RLS decides. */\n  occurrencesBetween(range: {\n    from: string;\n    to: string;\n    organizationId?: OrganizationId | null;\n    limit?: number;\n  }): Promise<readonly UpcomingOccurrence[]>;\n  invitees(meetingId: MeetingId): Promise<readonly MeetingInvitee[]>;\n  addInvitees(meetingId: MeetingId, people: readonly InviteeInput[], byUserId?: UserId | null): Promise<readonly MeetingInvitee[]>;\n  setInviteeRole(inviteeId: string, role: InviteeRole, byUserId?: UserId | null): Promise<MeetingInvitee>;\n  removeInvitee(inviteeId: string, byUserId?: UserId | null): Promise<MeetingInvitee>;\n  respond(meetingId: MeetingId, answer: RsvpAnswer, note?: string | null): Promise<MeetingInvitee>;\n  invitationByToken(secret: string): Promise<RsvpInvitation>;\n  respondByToken(secret: string, answer: RsvpAnswer, note?: string | null): Promise<RsvpInvitation>;\n  projectInvitee(row: Row): MeetingInvitee;\n}\n\nexport interface ScheduleMeetingInput {\n  readonly organizationId: OrganizationId;\n  readonly hostUserId: UserId;\n  readonly title: string;\n  readonly scheduledFor: string | null;\n  /** IANA zone, e.g. `America/Los_Angeles`. The wall-clock time a series keeps across DST. */\n  readonly timeZone: string;\n  /** Omit to use the person's `meet.default_duration_minutes`. */\n  readonly durationMinutes?: number | null | undefined;\n  readonly agenda?: string | null | undefined;\n  /** RRULE subset: FREQ=DAILY|WEEKLY|MONTHLY, INTERVAL, BYDAY, BYMONTHDAY, COUNT, UNTIL. */\n  readonly recurrenceRule?: string | null | undefined;\n  readonly settings?: MeetingSettings | undefined;\n  /** HR-360 wave 2 (MD-15): the registered app panel the call opens beside it. */\n  readonly appPanel?: { readonly key: string; readonly recordId: string } | undefined;\n  /** HR-360 wave 2 (MD-16): user ids the host names as silent observers. */\n  readonly observers?: readonly string[] | undefined;\n}\n\nexport interface RepositoryOptions {\n  /**\n   * Any Supabase client. Deliberately the SHALLOW public shape — pass the\n   * `SupabaseClient<Database>` you already have, with no cast. See the header.\n   */\n  client: MessagingSupabaseClient;\n  /** Resolve a session; used to retry ONCE across the sign-in gap. */\n  session?: (() => Promise<unknown>) | undefined;\n}\n\n/**\n * 🚨 THE PROJECTIONS ARE MODULE-LEVEL AND EXPORTED, DELIBERATELY (MRI-A12).\n *\n * A durable Meet row reaches a client on one of two transports: as a\n * `meet_notes` / `meet_transcript_segments` row over Postgres Changes, which\n * needs a Supabase session and an org grant, or as a `matrx.meet.*` packet on\n * the LiveKit data plane, which needs only the room token — and is therefore the\n * ONLY one a session-less guest can receive (MRI-A10 settled that `anon` never\n * gets a grant on an org-scoped table).\n *\n * Both carry the same row. If each transport projected it with its own function,\n * a guest and a member would render the same meeting differently the first time\n * the two drifted. So there is one function per row shape, it takes no client,\n * and `core/room-events.ts` calls exactly these.\n */\nexport function projectSegment(row: Row): TranscriptSegment {\n  const operation = \"meet.projectSegment\";\n  const id = requireText(row, \"id\", operation);\n  return {\n    id,\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    identity: asParticipantIdentity(text(row, \"identity\") ?? \"unknown\"),\n    // A nameless line is a line nobody can act on. The identity is a worse\n    // name than a real one and a far better one than an empty string.\n    speaker: text(row, \"speaker\") ?? text(row, \"identity\") ?? \"Someone\",\n    text: text(row, \"text\") ?? \"\",\n    startedAt: text(row, \"started_at\") ?? new Date(0).toISOString(),\n    // The table holds finals only; a row that somehow says otherwise is still\n    // a durable record and is rendered as one.\n    final: bool(row, \"is_final\", true),\n    source: \"record\",\n    // The worker publishes the caption under THIS row's id (`lk.segment_id` =\n    // the durable segment id), which is what lets a record replace the exact\n    // caption it supersedes instead of doubling the line (D16).\n    captionId: id,\n  };\n}\n\nexport function projectNote(row: Row): MeetingNote {\n  const operation = \"meet.projectNote\";\n  const kind = text(row, \"kind\");\n  const rawMetadata = row[\"metadata\"];\n  const metadata: Record<string, unknown> =\n    typeof rawMetadata === \"object\" && rawMetadata !== null && !Array.isArray(rawMetadata)\n      ? (rawMetadata as Record<string, unknown>)\n      : {};\n  const assignee = metadata[\"assignee\"];\n  const assigneeRow: Record<string, unknown> =\n    typeof assignee === \"object\" && assignee !== null && !Array.isArray(assignee)\n      ? (assignee as Record<string, unknown>)\n      : {};\n  const windowValue = metadata[\"window\"];\n  const windowRow: Record<string, unknown> =\n    typeof windowValue === \"object\" && windowValue !== null && !Array.isArray(windowValue)\n      ? (windowValue as Record<string, unknown>)\n      : {};\n  const assigneeUserId = text(row, \"assignee_user_id\");\n  const displayName = assigneeRow[\"display_name\"];\n  return {\n    id: requireText(row, \"id\", operation),\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    text: (text(row, \"text\") ?? \"\").trim(),\n    createdAt: text(row, \"created_at\") ?? new Date().toISOString(),\n    // An unknown kind is a NOTE, never dropped: a row the database accepted\n    // is a row a person wrote down, whatever a future migration calls it.\n    kind:\n      kind === \"decision\" || kind === \"action-item\" ? (kind as MeetingNote[\"kind\"]) : \"note\",\n    assigneeUserId: assigneeUserId === null ? null : asUserId(assigneeUserId),\n    // D18: a guest never gets an `assignee_user_id` (the FK targets\n    // `auth.users`), so their name lives in the metadata and is read here —\n    // an action item whose owner has no name is an action item nobody owns.\n    assigneeDisplayName:\n      typeof displayName === \"string\" && displayName.length > 0 ? displayName : null,\n    role: metadata[\"role\"] === \"summary\" ? \"summary\" : null,\n    window: typeof windowRow[\"index\"] === \"number\" ? windowRow[\"index\"] : null,\n    // D20. `superseded_by` is in `NOTE_PUBLIC_METADATA_KEYS` server-side, so a\n    // session-less guest's room-borne copy carries it too — otherwise the guest\n    // would be the one lane still reading a decision twice.\n    supersededBy:\n      typeof metadata[\"superseded_by\"] === \"string\" && metadata[\"superseded_by\"].length > 0\n        ? (metadata[\"superseded_by\"] as string)\n        : null,\n    // THE DATABASE ROW. `core/room-events.ts` marks its copy of the same row\n    // `\"room\"`, and the store's precedence rule reads this field (MRI-A12).\n    source: \"record\",\n  };\n}\n\n\n\n/* ─────────────────────────────── MEET WAVE 1 — management projections (0.8) */\n\nconst RSVP_STATES: readonly RsvpState[] = [\"needs_action\", \"accepted\", \"declined\", \"tentative\"];\nconst OCCURRENCE_STATES: readonly OccurrenceState[] = [\"scheduled\", \"moved\", \"cancelled\"];\n\nfunction rsvpState(value: string | null): RsvpState {\n  return RSVP_STATES.includes(value as RsvpState) ? (value as RsvpState) : \"needs_action\";\n}\n\nfunction num(row: Row, key: string): number | null {\n  const value = row[key];\n  return typeof value === \"number\" ? value : null;\n}\n\n/** A database timestamp as ISO text. PostgREST sends strings; a test double may send Dates. */\nfunction when(row: Row, key: string): string | null {\n  const value = row[key];\n  if (value instanceof Date) return value.toISOString();\n  return text(row, key);\n}\n\nexport function projectInvitee(row: Row): MeetingInvitee {\n  const operation = \"meet.projectInvitee\";\n  const userId = text(row, \"invitee_user_id\");\n  return {\n    id: requireText(row, \"id\", operation),\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    userId: userId === null ? null : asUserId(userId),\n    email: text(row, \"email\"),\n    displayName: text(row, \"display_name\"),\n    role: text(row, \"role\") === \"cohost\" ? \"cohost\" : \"invitee\",\n    rsvpState: rsvpState(text(row, \"rsvp_state\")),\n    respondedAt: when(row, \"responded_at\"),\n    rsvpNote: text(row, \"rsvp_note\"),\n    lastSentSequence: num(row, \"last_sent_sequence\"),\n    lastSentAt: when(row, \"last_sent_at\"),\n  };\n}\n\nexport function projectOccurrence(row: Row): MeetingOccurrence {\n  const operation = \"meet.projectOccurrence\";\n  const state = text(row, \"state\");\n  return {\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    originalStart: when(row, \"original_start\") ?? requireText(row, \"original_start\", operation),\n    occurrenceStart: when(row, \"occurrence_start\") ?? requireText(row, \"occurrence_start\", operation),\n    durationMinutes: num(row, \"duration_minutes\"),\n    // An unknown state is shown as scheduled, never dropped: the row is real.\n    state: OCCURRENCE_STATES.includes(state as OccurrenceState) ? (state as OccurrenceState) : \"scheduled\",\n    sequence: num(row, \"sequence\") ?? 0,\n  };\n}\n\nexport function projectUpcoming(row: Row): UpcomingOccurrence {\n  const operation = \"meet.projectUpcoming\";\n  const kind = text(row, \"kind\");\n  const myRole = text(row, \"my_role\");\n  const myRsvp = text(row, \"my_rsvp\");\n  return {\n    ...projectOccurrence(row),\n    organizationId: asOrganizationId(requireText(row, \"organization_id\", operation)),\n    title: text(row, \"title\") ?? \"Meeting\",\n    slug: requireText(row, \"slug\", operation),\n    kind: kind === \"scheduled\" || kind === \"recurring\" ? (kind as MeetingKind) : \"instant\",\n    hostUserId: asUserId(requireText(row, \"host_user_id\", operation)),\n    timeZone: text(row, \"time_zone\") ?? \"UTC\",\n    meetingCancelled: bool(row, \"meeting_cancelled\", false),\n    myRsvp: myRsvp === null ? null : rsvpState(myRsvp),\n    myRole: myRole === \"host\" || myRole === \"cohost\" || myRole === \"invitee\" ? myRole : null,\n  };\n}\n\nexport function projectOverride(row: Row): OccurrenceOverride {\n  const operation = \"meet.projectOverride\";\n  return {\n    id: requireText(row, \"id\", operation),\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    originalStart: when(row, \"original_start\") ?? requireText(row, \"original_start\", operation),\n    state: text(row, \"state\") === \"moved\" ? \"moved\" : \"cancelled\",\n    newStart: when(row, \"new_start\"),\n    newDurationMinutes: num(row, \"new_duration_minutes\"),\n    reason: text(row, \"reason\"),\n    calendarSequence: num(row, \"calendar_sequence\") ?? 0,\n    deletedAt: when(row, \"deleted_at\"),\n  };\n}\n\n/** The jsonb the RSVP doors return, typed. A body that is neither shape is refused loudly. */\nexport function projectRsvpInvitation(body: unknown): RsvpInvitation {\n  const operation = \"meet.projectRsvpInvitation\";\n  if (typeof body !== \"object\" || body === null) {\n    throw invalidMeetResponse(operation, \"the RSVP door returned no object\");\n  }\n  const row = body as Row;\n  if (row[\"ok\"] !== true) {\n    return {\n      ok: false,\n      message: text(row, \"message\") ?? \"This invitation link is no longer valid — ask the host to send it again.\",\n    };\n  }\n  const meeting = (row[\"meeting\"] ?? {}) as Row;\n  const invitee = (row[\"invitee\"] ?? {}) as Row;\n  return {\n    ok: true,\n    meeting: {\n      title: text(meeting, \"title\") ?? \"Meeting\",\n      slug: requireText(meeting, \"slug\", operation),\n      scheduledFor: when(meeting, \"scheduled_for\"),\n      durationMinutes: num(meeting, \"duration_minutes\"),\n      timeZone: text(meeting, \"time_zone\") ?? \"UTC\",\n      agenda: text(meeting, \"agenda\"),\n      recurrenceRule: text(meeting, \"recurrence_rule\"),\n      cancelledAt: when(meeting, \"cancelled_at\"),\n      cancellationReason: text(meeting, \"cancellation_reason\"),\n      endedAt: when(meeting, \"ended_at\"),\n    },\n    invitee: {\n      displayName: text(invitee, \"display_name\"),\n      email: text(invitee, \"email\"),\n      rsvpState: rsvpState(text(invitee, \"rsvp_state\")),\n      respondedAt: when(invitee, \"responded_at\"),\n    },\n  };\n}\n\n/** Settings → the door's snake_case object, carrying ONLY what was set. */\nexport function settingsPatch(settings: MeetingSettings): Record<string, unknown> {\n  const patch: Record<string, unknown> = {};\n  if (settings.lobbyEnabled !== undefined) patch[\"lobby_enabled\"] = settings.lobbyEnabled;\n  if (settings.recordingPolicy !== undefined) patch[\"recording_policy\"] = settings.recordingPolicy;\n  if (settings.aiEnabled !== undefined) patch[\"ai_enabled\"] = settings.aiEnabled;\n  if (settings.joinBeforeHost !== undefined) patch[\"join_before_host\"] = settings.joinBeforeHost;\n  return patch;\n}\n\n/**\n * A partial edit → the `meet_update_meeting` patch. `undefined` = leave alone,\n * `null` = clear — the difference a JSON patch exists to carry.\n */\nexport function changesPatch(changes: MeetingChanges): Record<string, unknown> {\n  const patch = settingsPatch(changes);\n  if (changes.title !== undefined) patch[\"title\"] = changes.title;\n  if (changes.agenda !== undefined) patch[\"agenda\"] = changes.agenda;\n  if (changes.timeZone !== undefined) patch[\"time_zone\"] = changes.timeZone;\n  if (changes.scheduledFor !== undefined) patch[\"scheduled_for\"] = changes.scheduledFor;\n  if (changes.scheduledDurationMinutes !== undefined) {\n    patch[\"scheduled_duration_minutes\"] = changes.scheduledDurationMinutes;\n  }\n  if (changes.recurrenceRule !== undefined) patch[\"recurrence_rule\"] = changes.recurrenceRule;\n  if (changes.keepExceptions !== undefined) patch[\"keep_exceptions\"] = changes.keepExceptions;\n  return patch;\n}\n\nexport function createMeetRepository(options: RepositoryOptions): MeetRepository {\n  // THE ONE NARROWING, in-package. Everything below works against the rich\n  // internal contract; no consumer ever has to satisfy it.\n  const db = (options.client as SupabaseLike).schema(MEET_SCHEMA);\n\n  /**\n   * 🚨 A `RETURNS void` RPC RESOLVES TO `null`, AND THAT IS SUCCESS.\n   *\n   * `guard` below treats a null `data` as an invalid response, which is right\n   * for every RPC that returns a row and CATASTROPHIC for one that returns\n   * nothing: `communication.meet_admit_participant` and `meet_record_consent`\n   * are both `RETURNS void`, so from the day this package shipped, admitting\n   * somebody from the lobby and recording consent BOTH performed their write\n   * and then threw \"the database returned no row\" on the way back — the write\n   * landed, the client believed it failed, the broadcast that tells the guest\n   * never went out, and the guest sat in the waiting room forever. Found in a\n   * browser (MRI-A11); the RPC return types are pinned in `VOID_RPCS` below so\n   * a future void RPC cannot be wired to the wrong guard by accident.\n   */\n  async function guardVoid(\n    operation: string,\n    run: () => PromiseLike<{ data: unknown; error: { message: string; code?: string } | null }>,\n  ): Promise<void> {\n    let response = await run();\n    if (response.error !== null) {\n      const normalized = normalizeMeetError(response.error, operation);\n      if (normalized.code === \"session-unavailable\" && options.session !== undefined) {\n        await options.session();\n        response = await run();\n      }\n      if (response.error !== null) throw normalizeMeetError(response.error, operation);\n    }\n    // No row is expected and none is read. The absence of an error IS the\n    // result — anything else would be inventing a postcondition the database\n    // never promised.\n  }\n\n  /**\n   * The link's current run. It adds to the lookup and never replaces it: a failed read leaves the\n   * run UNKNOWN (undefined) and the join gate still decides on Join — an unknown is never guessed.\n   */\n  async function readLinkRun(slug: string): Promise<LinkRunState | undefined> {\n    try {\n      const response = await db.rpc<Row>(MEET_RPCS.linkState, { p_slug: slug });\n      return projectLinkRun(response.error === null ? response.data : null);\n    } catch {\n      return undefined;\n    }\n  }\n\n  async function guard<T>(operation: string, run: () => PromiseLike<{ data: T | null; error: { message: string; code?: string } | null }>): Promise<T> {\n    let response = await run();\n    if (response.error !== null) {\n      const normalized = normalizeMeetError(response.error, operation);\n      // ONE retry, and only for the sign-in gap. A permission denial is NEVER\n      // retried — retrying one is how a request storm is built.\n      if (normalized.code === \"session-unavailable\" && options.session !== undefined) {\n        await options.session();\n        response = await run();\n      }\n      if (response.error !== null) throw normalizeMeetError(response.error, operation);\n    }\n    if (response.data === null) {\n      throw invalidMeetResponse(operation, \"the database returned no row\");\n    }\n    return response.data;\n  }\n\n  function projectInvite(row: Row): CallInvite {\n    const operation = \"meet.projectInvite\";\n    const mode = text(row, \"mode\");\n    return {\n      id: asCallId(requireText(row, \"id\", operation)),\n      organizationId: asOrganizationId(requireText(row, \"organization_id\", operation)),\n      roomName: asRoomName(requireText(row, \"room_name\", operation)),\n      mode: mode === \"video\" ? \"video\" : \"audio\",\n      callerUserId: asUserId(requireText(row, \"caller_user_id\", operation)),\n      callerName: text(row, \"caller_name\") ?? \"Someone\",\n      callerAvatarUrl: text(row, \"caller_avatar_url\"),\n      calleeUserIds: stringArray(row, \"callee_ids\").map(asUserId),\n      conversationId: text(row, \"conversation_id\"),\n      createdAt: requireText(row, \"created_at\", operation),\n      expiresAt: text(row, \"expires_at\") ?? requireText(row, \"created_at\", operation),\n      state: callState(text(row, \"state\")),\n      declineMessage: text(row, \"decline_message\"),\n    };\n  }\n\n  function projectMeeting(row: Row): MeetingRecord {\n    const operation = \"meet.projectMeeting\";\n    const kind = text(row, \"kind\");\n    const policy = text(row, \"recording_policy\");\n    const duration = row[\"scheduled_duration_minutes\"];\n    const metadata = row[\"metadata\"];\n    return {\n      id: asMeetingId(requireText(row, \"id\", operation)),\n      organizationId: asOrganizationId(requireText(row, \"organization_id\", operation)),\n      roomName: asRoomName(requireText(row, \"room_name\", operation)),\n      slug: requireText(row, \"slug\", operation),\n      title: text(row, \"title\") ?? \"Meeting\",\n      kind: kind === \"scheduled\" || kind === \"recurring\" ? (kind as MeetingKind) : \"instant\",\n      hostUserId: asUserId(requireText(row, \"host_user_id\", operation)),\n      scheduledFor: text(row, \"scheduled_for\"),\n      scheduledDurationMinutes: typeof duration === \"number\" ? duration : null,\n      startedAt: text(row, \"started_at\"),\n      endedAt: text(row, \"ended_at\"),\n      locked: bool(row, \"locked\", false),\n      lobbyEnabled: bool(row, \"lobby_enabled\", true),\n      recordingPolicy:\n        policy === \"disabled\" || policy === \"always-on\"\n          ? (policy as RecordingPolicy)\n          : \"host-controlled\",\n      aiEnabled: bool(row, \"ai_enabled\", true),\n      metadata:\n        typeof metadata === \"object\" && metadata !== null && !Array.isArray(metadata)\n          ? (metadata as JsonObject)\n          : {},\n      timeZone: text(row, \"time_zone\") ?? \"UTC\",\n      agenda: text(row, \"agenda\"),\n      recurrenceRule: text(row, \"recurrence_rule\"),\n      joinBeforeHost: bool(row, \"join_before_host\", true),\n      cancelledAt: text(row, \"cancelled_at\"),\n      cancellationReason: text(row, \"cancellation_reason\"),\n      deletedAt: text(row, \"deleted_at\"),\n      calendarSequence: typeof row[\"calendar_sequence\"] === \"number\" ? row[\"calendar_sequence\"] : 0,\n      version: typeof row[\"version\"] === \"number\" ? row[\"version\"] : 1,\n    };\n  }\n\n  function projectRecording(row: Row): RecordingRecord {\n    const operation = \"meet.projectRecording\";\n    const state = text(row, \"state\");\n    const known: readonly RecordingState[] = [\n      \"idle\",\n      \"starting\",\n      \"recording\",\n      \"stopping\",\n      \"processing\",\n      \"available\",\n      \"expired\",\n      \"failed\",\n    ];\n    return {\n      id: requireText(row, \"id\", operation),\n      meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n      state: known.includes(state as RecordingState) ? (state as RecordingState) : \"failed\",\n      startedAt: text(row, \"started_at\"),\n      endedAt: text(row, \"ended_at\"),\n      startedBy: text(row, \"started_by\") === null ? null : asUserId(text(row, \"started_by\") as string),\n      // A PLATFORM file id, never a provider URL (R3). A recording that only\n      // exists as a LiveKit URL is orphaned the day the room is garbage\n      // collected, which is the whole reason this column is not `url`.\n      fileId: text(row, \"file_id\"),\n      failureReason: text(row, \"failure_reason\"),\n      retention: projectRecordingRetention(row[\"metadata\"]),\n    };\n  }\n\n  function projectRecordingRetention(value: unknown): RecordingRetention | null {\n    if (typeof value !== \"object\" || value === null || Array.isArray(value)) return null;\n    const retention = (value as Record<string, unknown>)[\"retention\"];\n    if (typeof retention !== \"object\" || retention === null || Array.isArray(retention)) return null;\n    const row = retention as Record<string, unknown>;\n    const phase = row[\"phase\"];\n    const operationId = row[\"operation_id\"];\n    const policyId = row[\"policy_id\"];\n    const policyUpdatedAt = row[\"policy_updated_at\"];\n    const dueAt = row[\"due_at\"];\n    const expiredAt = row[\"expired_at\"];\n    if (\n      (phase !== \"warning\" && phase !== \"expired\") ||\n      typeof operationId !== \"string\" ||\n      typeof policyId !== \"string\" ||\n      typeof policyUpdatedAt !== \"string\" ||\n      typeof dueAt !== \"string\" ||\n      (expiredAt !== null && typeof expiredAt !== \"string\")\n    ) return null;\n    return { operationId, policyId, policyUpdatedAt, phase, dueAt, expiredAt };\n  }\n\n  function projectAttendee(row: Row): MeetingAttendee {\n    const operation = \"meet.projectAttendee\";\n    const role = text(row, \"role\");\n    const admission = text(row, \"admission_state\");\n    const known: readonly ParticipantRole[] = [\"host\", \"cohost\", \"presenter\", \"participant\", \"viewer\"];\n    const states: readonly AdmissionState[] = [\n      \"waiting_host\",\n      \"knocking\",\n      \"admitted\",\n      \"denied\",\n      \"expired\",\n      \"withdrawn\",\n      \"removed\",\n      \"ended\",\n    ];\n    const userId = text(row, \"participant_user_id\");\n    const identity = requireText(row, \"identity\", operation);\n    return {\n      id: requireText(row, \"id\", operation),\n      meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n      identity: asParticipantIdentity(identity),\n      // A nameless attendee is a row nobody can read. The identity is a worse\n      // name than a real one and an infinitely better one than a blank.\n      displayName: text(row, \"display_name\") ?? identity,\n      avatarUrl: text(row, \"avatar_url\"),\n      userId: userId === null ? null : asUserId(userId),\n      role: known.includes(role as ParticipantRole) ? (role as ParticipantRole) : \"participant\",\n      admissionState: states.includes(admission as AdmissionState)\n        ? (admission as AdmissionState)\n        : \"admitted\",\n      knockedAt: text(row, \"knocked_at\"),\n      knockExpiresAt: text(row, \"knock_expires_at\"),\n      // The list read selects `metadata->>knock_flag`; a Postgres Changes row carries `metadata`.\n      knockFlag:\n        text(row, \"knock_flag\") ??\n        (typeof row[\"metadata\"] === \"object\" && row[\"metadata\"] !== null\n          ? text(row[\"metadata\"] as Row, \"knock_flag\")\n          : null),\n      isAgent: bool(row, \"is_agent\", false),\n      joinedAt: text(row, \"joined_at\"),\n      leftAt: text(row, \"left_at\"),\n      sessions: projectStays(row[\"sessions\"]),\n    };\n  }\n\n  function requireOrg(organizationId: OrganizationId, operation: string): void {\n    if (typeof organizationId !== \"string\" || organizationId.length === 0) {\n      throw new MeetError(\n        \"misconfigured\",\n        `${operation}: no organization_id`,\n        \"Every meet write carries an explicit organization_id (R5). The package refuses the \" +\n          \"write rather than letting an unscoped row reach the database.\",\n      );\n    }\n  }\n\n\n  /**\n   * S5 (CORE-DESIGN §2.3): the note-taker and intelligence state lives on the RUN\n   * (`meet_sessions.note_taker`), never on the meeting row. Every reader of\n   * `meeting.metadata.note_taker` (record view's wrap-up status, the note-taker line) reads\n   * the meeting's CURRENT run through this one seam — the open run, else the latest. A\n   * reader with no grant on runs (a guest) keeps the row as it is; their state arrives on\n   * the room's `matrx.meet.note_taker` event.\n   */\n  async function withRunNoteTaker(meeting: MeetingRecord): Promise<MeetingRecord> {\n    const response = await db\n      .from<Row>(MEET_TABLES.sessions)\n      .select(\"note_taker,started_at\")\n      .eq(\"meeting_id\", meeting.id)\n      .order(\"started_at\", { ascending: false })\n      .limit(1);\n    const run = response.error === null ? (response.data ?? [])[0] : undefined;\n    const noteTaker = run?.[\"note_taker\"];\n    if (typeof noteTaker !== \"object\" || noteTaker === null || Array.isArray(noteTaker)) {\n      return meeting;\n    }\n    return {\n      ...meeting,\n      metadata: { ...(meeting.metadata ?? {}), note_taker: noteTaker } as MeetingRecord[\"metadata\"],\n    };\n  }\n\n  return {\n    schema: MEET_SCHEMA,\n    tables: MEET_TABLES,\n    projectInvite,\n    projectMeeting,\n    projectSegment,\n    projectNote,\n    projectRecording,\n    projectAttendee,\n    projectInvitee,\n\n    async scheduleMeeting(input) {\n      requireOrg(input.organizationId, \"meet.scheduleMeeting\");\n      const row = await guard<Row>(\"meet.scheduleMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.scheduleMeeting, {\n          p_organization_id: input.organizationId,\n          p_host_user_id: input.hostUserId,\n          p_title: input.title,\n          p_scheduled_for: input.scheduledFor,\n          p_time_zone: input.timeZone,\n          p_duration_minutes: input.durationMinutes ?? null,\n          p_agenda: input.agenda ?? null,\n          p_recurrence_rule: input.recurrenceRule ?? null,\n          p_settings: scheduleSettingsPatch(input.settings ?? {}, input.appPanel, input.observers),\n        }),\n      );\n      return projectMeeting(row);\n    },\n\n    async updateMeeting(meetingId, changes, options = {}) {\n      const row = await guard<Row>(\"meet.updateMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.updateMeeting, {\n          p_meeting_id: meetingId,\n          p_changes: changesPatch(changes),\n          p_expected_version: options.expectedVersion ?? null,\n          p_by_user_id: options.byUserId ?? null,\n        }),\n      );\n      return projectMeeting(row);\n    },\n\n    async cancelMeeting(meetingId, reason, byUserId = null) {\n      const row = await guard<Row>(\"meet.cancelMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.cancelMeeting, {\n          p_meeting_id: meetingId,\n          p_reason: reason,\n          p_by_user_id: byUserId,\n        }),\n      );\n      return projectMeeting(row);\n    },\n\n    async archiveMeeting(meetingId, byUserId = null) {\n      const row = await guard<Row>(\"meet.archiveMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.archiveMeeting, { p_meeting_id: meetingId, p_by_user_id: byUserId }),\n      );\n      return projectMeeting(row);\n    },\n\n    async restoreMeeting(meetingId, byUserId = null) {\n      const row = await guard<Row>(\"meet.restoreMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.restoreMeeting, { p_meeting_id: meetingId, p_by_user_id: byUserId }),\n      );\n      return projectMeeting(row);\n    },\n\n    async setOccurrence(args) {\n      const row = await guard<Row>(\"meet.setOccurrence\", () =>\n        db.rpc<Row>(MEET_RPCS.setOccurrence, {\n          p_meeting_id: args.meetingId,\n          p_original_start: args.originalStart,\n          p_action: args.action,\n          p_new_start: args.newStart ?? null,\n          p_new_duration_minutes: args.newDurationMinutes ?? null,\n          p_reason: args.reason ?? null,\n          p_by_user_id: args.byUserId ?? null,\n        }),\n      );\n      return projectOverride(row);\n    },\n\n    async meetingOccurrences(meetingId, { from, to, limit = 200 }) {\n      const rows = await guard<Row[]>(\"meet.meetingOccurrences\", () =>\n        db.rpc<Row[]>(MEET_RPCS.meetingOccurrences, {\n          p_meeting_id: meetingId,\n          p_from: from,\n          p_to: to,\n          p_limit: limit,\n        }),\n      );\n      return rows.map(projectOccurrence);\n    },\n\n    async occurrencesBetween({ from, to, organizationId = null, limit = 500 }) {\n      const rows = await guard<Row[]>(\"meet.occurrencesBetween\", () =>\n        db.rpc<Row[]>(MEET_RPCS.occurrencesBetween, {\n          p_from: from,\n          p_to: to,\n          p_organization_id: organizationId,\n          p_limit: limit,\n        }),\n      );\n      return rows.map(projectUpcoming);\n    },\n\n    async invitees(meetingId) {\n      const response = await db\n        .from<Row>(MEET_TABLES.invitees)\n        .select(INVITEE_COLUMNS)\n        .eq(\"meeting_id\", meetingId)\n        .is(\"deleted_at\", null)\n        .order(\"created_at\", { ascending: true })\n        .order(\"id\", { ascending: true });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.invitees\");\n      return (response.data ?? []).map(projectInvitee);\n    },\n\n    async addInvitees(meetingId, people, byUserId = null) {\n      const rows = await guard<Row[]>(\"meet.addInvitees\", () =>\n        db.rpc<Row[]>(MEET_RPCS.addInvitees, {\n          p_meeting_id: meetingId,\n          p_invitees: people.map((person) => ({\n            ...(person.userId !== undefined ? { user_id: person.userId } : {}),\n            ...(person.email !== undefined ? { email: person.email } : {}),\n            ...(person.displayName !== undefined ? { display_name: person.displayName } : {}),\n            ...(person.role !== undefined ? { role: person.role } : {}),\n          })),\n          p_by_user_id: byUserId,\n        }),\n      );\n      return rows.map(projectInvitee);\n    },\n\n    async setInviteeRole(inviteeId, role, byUserId = null) {\n      const row = await guard<Row>(\"meet.setInviteeRole\", () =>\n        db.rpc<Row>(MEET_RPCS.setInviteeRole, {\n          p_invitee_id: inviteeId,\n          p_role: role,\n          p_by_user_id: byUserId,\n        }),\n      );\n      return projectInvitee(row);\n    },\n\n    async removeInvitee(inviteeId, byUserId = null) {\n      const row = await guard<Row>(\"meet.removeInvitee\", () =>\n        db.rpc<Row>(MEET_RPCS.removeInvitee, { p_invitee_id: inviteeId, p_by_user_id: byUserId }),\n      );\n      return projectInvitee(row);\n    },\n\n    async respond(meetingId, answer, note = null) {\n      const row = await guard<Row>(\"meet.respond\", () =>\n        db.rpc<Row>(MEET_RPCS.respond, {\n          p_meeting_id: meetingId,\n          p_response: answer,\n          p_note: note,\n          p_by_user_id: null,\n        }),\n      );\n      return projectInvitee(row);\n    },\n\n    async invitationByToken(secret) {\n      const body = await guard<unknown>(\"meet.invitationByToken\", () =>\n        db.rpc<unknown>(MEET_RPCS.invitationByToken, { p_secret: secret }),\n      );\n      return projectRsvpInvitation(body);\n    },\n\n    async respondByToken(secret, answer, note = null) {\n      const body = await guard<unknown>(\"meet.respondByToken\", () =>\n        db.rpc<unknown>(MEET_RPCS.respondByToken, {\n          p_secret: secret,\n          p_response: answer,\n          p_note: note,\n        }),\n      );\n      return projectRsvpInvitation(body);\n    },\n\n    async attendees(meetingId) {\n      const response = await db\n        .from<Row>(MEET_TABLES.participants)\n        .select(ATTENDEE_COLUMNS)\n        .eq(\"meeting_id\", meetingId)\n        .order(\"joined_at\", { ascending: true })\n        .order(\"id\", { ascending: true });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.attendees\");\n      return (response.data ?? []).map(projectAttendee);\n    },\n\n    async createCallInvite(input) {\n      requireOrg(input.organizationId, \"meet.createCallInvite\");\n      const row = await guard<Row>(\"meet.createCallInvite\", () =>\n        db.rpc<Row>(MEET_RPCS.createCallInvite, {\n          p_room_name: input.roomName,\n          p_mode: input.mode,\n          p_caller_user_id: input.callerUserId,\n          p_caller_name: input.callerName,\n          p_caller_avatar_url: input.callerAvatarUrl,\n          p_callee_ids: input.calleeUserIds,\n          p_organization_id: input.organizationId,\n          p_conversation_id: input.conversationId,\n          p_expires_at: input.expiresAt,\n        }),\n      );\n      return projectInvite(row);\n    },\n\n    async settleCallInvite(id, state, declineMessage) {\n      const row = await guard<Row>(\"meet.settleCallInvite\", () =>\n        db.rpc<Row>(MEET_RPCS.settleCallInvite, {\n          p_invite_id: id,\n          p_state: state,\n          p_decline_message: declineMessage,\n        }),\n      );\n      return projectInvite(row);\n    },\n\n    async pendingInvites(userId) {\n      // LOAD MARKER (lazy) — must never run before the page settles; page-load trace, no import.\n      if (typeof window !== \"undefined\") performance.mark(\"load:lazy:meet invites read\");\n      const rows = await guard<Row[]>(\"meet.pendingInvites\", () =>\n        db.rpc<Row[]>(MEET_RPCS.pendingCallInvites, { p_user_id: userId }),\n      );\n      return rows.map(projectInvite);\n    },\n\n    async getOrCreateMeeting(input) {\n      requireOrg(input.organizationId, \"meet.getOrCreateMeeting\");\n      const row = await guard<Row>(\"meet.getOrCreateMeeting\", () =>\n        db.rpc<Row>(MEET_RPCS.getOrCreateMeeting, {\n          p_organization_id: input.organizationId,\n          p_host_user_id: input.hostUserId,\n          p_title: input.title,\n          p_kind: input.kind,\n          p_scheduled_for: input.scheduledFor ?? null,\n          p_scheduled_duration_minutes: input.scheduledDurationMinutes ?? null,\n          p_lobby_enabled: input.lobbyEnabled ?? true,\n          p_recording_policy: input.recordingPolicy ?? \"host-controlled\",\n          p_ai_enabled: input.aiEnabled ?? true,\n          p_slug: input.slug ?? null,\n        }),\n      );\n      return projectMeeting(row);\n    },\n\n    async meetingBySlug(slug) {\n      // A DURABLE LINK RESOLVES BEFORE, DURING, AND AFTER (R3). This RPC is not\n      // filtered by `ended_at is null` on purpose: a link that dies the moment\n      // the meeting ends breaks every \"here are the notes\" follow-up.\n      const [row, linkRun] = await Promise.all([\n        guard<Row>(\"meet.meetingBySlug\", () => db.rpc<Row>(MEET_RPCS.meetingBySlug, { p_slug: slug })),\n        readLinkRun(slug),\n      ]);\n      // AWAITED: spreading the un-awaited Promise dropped every field but `linkRun` (no roomName → the\n      // room page crashed on `meet-room requires part roomName`).\n      const record = await withRunNoteTaker(projectMeeting(row));\n      return linkRun === undefined ? record : { ...record, linkRun };\n    },\n\n    async meeting(id) {\n      const response = await db\n        .from<Row>(MEET_TABLES.meetings)\n        .select(MEETING_COLUMNS)\n        .eq(\"id\", id)\n        .single();\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.meeting\");\n      if (response.data === null) throw invalidMeetResponse(\"meet.meeting\", \"no such meeting\");\n      return withRunNoteTaker(projectMeeting(response.data));\n    },\n\n    async listMeetings({ organizationId = null, limit = 25, before = null }) {\n      let query = db\n        .from<Row>(MEET_TABLES.meetings)\n        .select(MEETING_COLUMNS);\n      if (organizationId !== null) query = query.eq(\"organization_id\", organizationId);\n      query = query\n        .order(\"scheduled_for\", { ascending: false })\n        .order(\"id\", { ascending: false })\n        // ASK FOR ONE MORE THAN THE PAGE, so `hasMore` is a fact rather than a\n        // guess from \"we got a full page\".\n        .limit(limit + 1);\n      if (before !== null) {\n        query = query.or(\n          `scheduled_for.lt.${before.scheduledFor},and(scheduled_for.eq.${before.scheduledFor},id.lt.${before.id})`,\n        );\n      }\n      const response = await query;\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.listMeetings\");\n      const rows = response.data ?? [];\n      return {\n        items: rows.slice(0, limit).map(projectMeeting),\n        hasMore: rows.length > limit,\n      };\n    },\n\n    async decideAdmission({ meetingId, identity, decision, byUserId }) {\n      const fn = decision === \"admit\" ? MEET_RPCS.admit : decision === \"deny\" ? MEET_RPCS.deny : MEET_RPCS.undeny;\n      const row = await guard<Row>(`meet.${decision}`, () =>\n        db.rpc<Row>(fn, {\n          p_meeting_id: meetingId,\n          p_identity: identity,\n          p_by_user_id: byUserId,\n        }),\n      );\n      return projectAttendee(row);\n    },\n\n    async admitAll(meetingId, byUserId) {\n      const response = await db.rpc<Row[]>(MEET_RPCS.admitAll, {\n        p_meeting_id: meetingId,\n        p_by_user_id: byUserId,\n      });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.admitAll\");\n      const rows = Array.isArray(response.data) ? (response.data as Row[]) : [];\n      return rows.map(projectAttendee);\n    },\n\n    async setLock(meetingId, locked, byUserId) {\n      const row = await guard<Row>(\"meet.setLock\", () =>\n        db.rpc<Row>(MEET_RPCS.setLock, {\n          p_meeting_id: meetingId,\n          p_locked: locked,\n          p_by_user_id: byUserId,\n        }),\n      );\n      return projectMeeting(row);\n    },\n\n    async meetingRule(meetingId, key) {\n      const response = await db.rpc<unknown>(MEET_RPCS.meetingRule, { p_meeting_id: meetingId, p_key: key });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.meetingRule\");\n      return response.data;\n    },\n\n    async setMeetingRule(meetingId, key, value) {\n      const response = await db.rpc<Row>(MEET_RPCS.setMeetingRule, { p_meeting_id: meetingId, p_key: key, p_value: value });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.setMeetingRule\");\n      const answer = (response.data ?? {}) as Row;\n      if (answer[\"ok\"] !== true) {\n        throw new MeetError(\n          \"forbidden\",\n          typeof answer[\"detail\"] === \"string\" ? answer[\"detail\"] : \"This meeting's rule was not changed.\",\n          \"Only the meeting's host or a co-host sets its rules; an organization can lock a rule for everyone.\",\n          answer,\n        );\n      }\n      return answer[\"effective_value\"];\n    },\n\n    async transcript(meetingId, limit = 1000) {\n      const response = await db\n        .from<Row>(MEET_TABLES.transcripts)\n        .select(SEGMENT_COLUMNS)\n        .eq(\"meeting_id\", meetingId)\n        .order(\"started_at\", { ascending: true })\n        .order(\"id\", { ascending: true })\n        .limit(limit);\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.transcript\");\n      return (response.data ?? []).map(projectSegment);\n    },\n\n    async notes(meetingId) {\n      const response = await db\n        .from<Row>(MEET_TABLES.notes)\n        .select(NOTE_COLUMNS)\n        .eq(\"meeting_id\", meetingId)\n        .order(\"created_at\", { ascending: true })\n        .order(\"id\", { ascending: true });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.notes\");\n      return (response.data ?? []).map(projectNote);\n    },\n\n    async recordConsent({ meetingId, identity, acknowledgedAt }) {\n      await guardVoid(\"meet.recordConsent\", () =>\n        db.rpc<Row>(MEET_RPCS.recordConsent, {\n          p_meeting_id: meetingId,\n          p_identity: identity,\n          p_acknowledged_at: acknowledgedAt,\n        }),\n      );\n    },\n\n    async recordings(meetingId) {\n      const response = await db\n        .from<Row>(MEET_TABLES.recordings)\n        .select(RECORDING_COLUMNS)\n        .eq(\"meeting_id\", meetingId)\n        // Meet wave 3: an archived recording is off the record as well as the library.\n        .is(\"deleted_at\", null)\n        .order(\"started_at\", { ascending: false });\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.recordings\");\n      return (response.data ?? []).map(projectRecording);\n    },\n\n    async myRecordings({ includeArchived = false, limit = 200 } = {}) {\n      const rows = await guard<Row[]>(\"meet.myRecordings\", () =>\n        db.rpc<Row[]>(MEET_RPCS.myRecordings, { p_include_archived: includeArchived, p_limit: limit }),\n      );\n      return rows.map(projectLibraryRecording);\n    },\n\n    async searchMeetings(query, limit = 60) {\n      if (query.trim().length === 0) return [];\n      const rows = await guard<Row[]>(\"meet.searchMeetings\", () =>\n        db.rpc<Row[]>(MEET_RPCS.search, { p_query: query, p_limit: limit }),\n      );\n      return rows.map(projectSearchHit);\n    },\n\n    async renameRecording(recordingId, title) {\n      const clean = title === null ? null : title.trim().slice(0, 200) || null;\n      const response = await db\n        .from<Row>(MEET_TABLES.recordings)\n        .update({ title: clean })\n        .eq(\"id\", recordingId)\n        .select(\"id\");\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.renameRecording\");\n      if ((response.data ?? []).length === 0) {\n        throw normalizeMeetError(\n          { message: \"permission denied: only the meeting's host or an editor can rename it\", code: \"42501\" },\n          \"meet.renameRecording\",\n        );\n      }\n    },\n\n    async setRecordingArchived(recordingId, archived) {\n      const response = await db\n        .from<Row>(MEET_TABLES.recordings)\n        .update({ deleted_at: archived ? new Date().toISOString() : null })\n        .eq(\"id\", recordingId)\n        .select(\"id\");\n      if (response.error !== null) throw normalizeMeetError(response.error, \"meet.setRecordingArchived\");\n      if ((response.data ?? []).length === 0) {\n        throw normalizeMeetError(\n          { message: \"permission denied: only the meeting's host or an editor can archive it\", code: \"42501\" },\n          \"meet.setRecordingArchived\",\n        );\n      }\n    },\n  };\n}\n\n/** One row of the recordings library (`meet_my_recordings`). */\nexport interface LibraryRecording {\n  readonly id: string;\n  readonly meetingId: MeetingId;\n  readonly meetingTitle: string;\n  readonly meetingSlug: string;\n  /** The reader's strongest role on the meeting. */\n  readonly role: \"host\" | \"cohost\" | \"invitee\" | \"attendee\";\n  readonly state: RecordingState;\n  /** A name a host gave it; null = show the meeting title. */\n  readonly title: string | null;\n  readonly fileId: string | null;\n  readonly startedAt: string | null;\n  readonly endedAt: string | null;\n  readonly durationMs: number | null;\n  readonly sizeBytes: number | null;\n  readonly failureReason: string | null;\n  readonly archivedAt: string | null;\n  readonly organizationId: OrganizationId;\n}\n\nconst LIBRARY_STATES: readonly RecordingState[] = [\n  \"idle\",\n  \"starting\",\n  \"recording\",\n  \"stopping\",\n  \"processing\",\n  \"available\",\n  \"expired\",\n  \"failed\",\n];\n\nexport function projectLibraryRecording(row: Row): LibraryRecording {\n  const operation = \"meet.projectLibraryRecording\";\n  const state = text(row, \"state\");\n  const role = text(row, \"my_role\");\n  return {\n    id: requireText(row, \"recording_id\", operation),\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    meetingTitle: text(row, \"meeting_title\") ?? \"Meeting\",\n    meetingSlug: requireText(row, \"meeting_slug\", operation),\n    role: role === \"host\" || role === \"cohost\" || role === \"invitee\" ? role : \"attendee\",\n    state: LIBRARY_STATES.includes(state as RecordingState) ? (state as RecordingState) : \"failed\",\n    title: text(row, \"recording_title\"),\n    fileId: text(row, \"file_id\"),\n    startedAt: text(row, \"started_at\"),\n    endedAt: text(row, \"ended_at\"),\n    durationMs: num(row, \"duration_ms\"),\n    sizeBytes: num(row, \"size_bytes\"),\n    failureReason: text(row, \"failure_reason\"),\n    archivedAt: text(row, \"deleted_at\"),\n    organizationId: asOrganizationId(requireText(row, \"organization_id\", operation)),\n  };\n}\n\n/** Where a search hit was found. */\nexport type MeetingSearchSource =\n  | \"title\"\n  | \"summary\"\n  | \"decision\"\n  | \"action_item\"\n  | \"note\"\n  | \"transcript\";\n\n/** One hit from `meet_search`. `snippet` marks matched words with ⟦ ⟧. */\nexport interface MeetingSearchHit {\n  readonly meetingId: MeetingId;\n  readonly meetingTitle: string;\n  readonly meetingSlug: string;\n  readonly meetingAt: string | null;\n  readonly source: MeetingSearchSource;\n  /** The note or transcript segment id (the meeting id for a title hit). */\n  readonly refId: string;\n  readonly speaker: string | null;\n  readonly snippet: string;\n  /** When it was said / written. */\n  readonly at: string | null;\n  readonly rank: number;\n}\n\nconst SEARCH_SOURCES: readonly MeetingSearchSource[] = [\n  \"title\",\n  \"summary\",\n  \"decision\",\n  \"action_item\",\n  \"note\",\n  \"transcript\",\n];\n\nexport function projectSearchHit(row: Row): MeetingSearchHit {\n  const operation = \"meet.projectSearchHit\";\n  const source = text(row, \"source\");\n  return {\n    meetingId: asMeetingId(requireText(row, \"meeting_id\", operation)),\n    meetingTitle: text(row, \"meeting_title\") ?? \"Meeting\",\n    meetingSlug: requireText(row, \"meeting_slug\", operation),\n    meetingAt: text(row, \"meeting_at\"),\n    source: SEARCH_SOURCES.includes(source as MeetingSearchSource)\n      ? (source as MeetingSearchSource)\n      : \"note\",\n    refId: requireText(row, \"ref_id\", operation),\n    speaker: text(row, \"speaker\"),\n    snippet: text(row, \"snippet\") ?? \"\",\n    at: text(row, \"said_at\"),\n    rank: num(row, \"rank\") ?? 0,\n  };\n}\n\n/** A snippet split into plain and matched runs, for highlighting without HTML. */\nexport function snippetRuns(snippet: string): readonly { readonly text: string; readonly hit: boolean }[] {\n  const runs: { text: string; hit: boolean }[] = [];\n  const pattern = /⟦([^⟧]*)⟧/g;\n  let last = 0;\n  for (const match of snippet.matchAll(pattern)) {\n    const start = match.index ?? 0;\n    if (start > last) runs.push({ text: snippet.slice(last, start), hit: false });\n    runs.push({ text: match[1] ?? \"\", hit: true });\n    last = start + match[0].length;\n  }\n  if (last < snippet.length) runs.push({ text: snippet.slice(last), hit: false });\n  return runs;\n}\n\n/** `meet_link_state` → the typed run state; anything not understood is \"unknown\", never a guess. */\nexport function projectLinkRun(value: unknown): LinkRunState | undefined {\n  if (typeof value !== \"object\" || value === null) return undefined;\n  const row = value as Record<string, unknown>;\n  const state = row[\"state\"];\n  if (state !== \"open\" && state !== \"not_started\" && state !== \"ended\" && state !== \"cancelled\") return undefined;\n  const reason = row[\"reason\"] === \"ended\" || row[\"reason\"] === \"cancelled\" ? row[\"reason\"] : null;\n  const nextStart = typeof row[\"next_start\"] === \"string\" ? row[\"next_start\"] : null;\n  return { state, reason, nextStart };\n}\n","/**\n * THE APP PANEL SLOT (HR-360 wave 2, Meet register MD-15).\n *\n * A meeting can carry one APP PANEL: a surface the HOST APP registered under a key, opened\n * beside the call on one record (`meet_meetings.metadata.app_panel = {key, record_id}`,\n * written by `meet_schedule_meeting`'s `app_panel` setting). The package knows only the key\n * and the record id; the host app's registered component reads the record through the\n * person's OWN doors, so someone who cannot read the record sees nothing of it.\n *\n * Everyone in the call looks at the same SECTION of the panel: one shared focus per run,\n * kept by the server and carried on the existing collab packet (`collab.focus`,\n * action `focus_set`) — never a second channel.\n */\n\nimport { settingsPatch } from \"./repository\";\nimport type { MeetingRecord, MeetingSettings } from \"./types\";\n\nexport interface MeetingAppPanel {\n  /** The registered surface key, e.g. `hr.review_360`. */\n  readonly key: string;\n  /** The record the panel opens on. */\n  readonly recordId: string;\n}\n\n/** The app panel this meeting carries, or null. Malformed values are never guessed at. */\nexport function appPanelOf(meeting: Pick<MeetingRecord, \"metadata\"> | null | undefined): MeetingAppPanel | null {\n  const raw = meeting?.metadata?.[\"app_panel\"];\n  if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return null;\n  const key = (raw as Record<string, unknown>)[\"key\"];\n  const recordId = (raw as Record<string, unknown>)[\"record_id\"];\n  if (typeof key !== \"string\" || key.length === 0) return null;\n  if (typeof recordId !== \"string\" || recordId.length === 0) return null;\n  return { key, recordId };\n}\n\n/**\n * HR-360 wave 3: the server held capture off because the meeting is about a Confidential record\n * (`metadata.capture_hold = \"confidential_record\"`, stamped by the meet_meetings trigger) and it\n * is still off. The room says so in one short line. Once the organization turns capture back on\n * (knob `meet.confidential_capture`), it is no longer held.\n */\nexport function captureHeldOf(\n  meeting: Pick<MeetingRecord, \"metadata\" | \"aiEnabled\" | \"recordingPolicy\"> | null | undefined,\n): boolean {\n  if (!meeting) return false;\n  return (\n    meeting.metadata?.[\"capture_hold\"] === \"confidential_record\" &&\n    !meeting.aiEnabled &&\n    meeting.recordingPolicy === \"disabled\"\n  );\n}\n\n/** The `p_settings` of `meet_schedule_meeting`, with the panel and the named observers. */\nexport function scheduleSettingsPatch(\n  settings: MeetingSettings,\n  appPanel: MeetingAppPanel | undefined,\n  observers: readonly string[] | undefined,\n): Record<string, unknown> {\n  const patch = settingsPatch(settings);\n  if (appPanel !== undefined) patch[\"app_panel\"] = { key: appPanel.key, record_id: appPanel.recordId };\n  if (observers !== undefined && observers.length > 0) patch[\"observers\"] = [...observers];\n  return patch;\n}\n\n/** The one shared section focus of the meeting's app panel (`collab.focus`). */\nexport interface MeetAppFocus {\n  readonly panel: string;\n  readonly section: string;\n  readonly byName: string;\n  readonly at: string;\n}\n\nexport function focusFromRow(value: unknown): MeetAppFocus | null {\n  if (typeof value !== \"object\" || value === null || Array.isArray(value)) return null;\n  const row = value as Record<string, unknown>;\n  if (typeof row[\"panel\"] !== \"string\") return null;\n  return {\n    panel: row[\"panel\"],\n    section: typeof row[\"section\"] === \"string\" ? row[\"section\"] : \"\",\n    byName: typeof row[\"by_name\"] === \"string\" ? row[\"by_name\"] : \"\",\n    at: typeof row[\"at\"] === \"string\" ? row[\"at\"] : \"\",\n  };\n}\n","/**\n * MEETING ROOM ITEMS — polls, Q&A, the shared whiteboard and breakout rooms (Meet wave 5).\n *\n * The server decides every one of them (`aidream/services/meet/collab.py`,\n * `breakouts.py`): who may create, launch, vote, ask, answer, draw, erase, open rooms or\n * move people — and what each viewer SEES (a draft poll is the host's alone; counts\n * reach everyone only once shared; anonymous votes and questions carry no identity;\n * a dismissed question stays with the hosts). This file only holds what the server\n * said and folds the room's `matrx.meet.collab` packets into it.\n *\n * Two reads, one truth: `GET /v1/meet/collab` once per join (a late joiner sees every\n * poll, question, stroke and the open breakout plan), then packets. Every item is keyed\n * by its row id, so the same item arriving twice is one item.\n */\n\nimport { readRefusalBody } from \"./ai\";\nimport type { MeetApi } from \"./api\";\nimport { MEET_ROUTES, MEETING_PASS_HEADER } from \"./tokens\";\nimport type { ParticipantIdentity } from \"./types\";\nimport { focusFromRow, type MeetAppFocus } from \"./app-panel\";\n\nexport interface MeetPollOption {\n  readonly id: string;\n  readonly text: string;\n  /** Present when this viewer may see counts (a host, or results shared). */\n  readonly votes?: number | undefined;\n  /** Who picked it — hosts only, never for an anonymous poll. */\n  readonly voters?: readonly string[] | undefined;\n}\n\nexport type MeetPollState = \"draft\" | \"live\" | \"closed\";\n\nexport interface MeetPoll {\n  readonly id: string;\n  readonly question: string;\n  readonly options: readonly MeetPollOption[];\n  readonly multiple: boolean;\n  readonly anonymous: boolean;\n  readonly state: MeetPollState;\n  readonly resultsShared: boolean;\n  readonly voterCount: number | null;\n  /** This viewer's own answer — kept locally, since a room packet cannot know it. */\n  readonly myVote: readonly string[];\n  readonly createdByName: string;\n  readonly createdAt: string | null;\n}\n\nexport type MeetQuestionState = \"open\" | \"answered\" | \"dismissed\";\n\nexport interface MeetQuestion {\n  readonly id: string;\n  readonly text: string;\n  readonly askerName: string;\n  readonly anonymous: boolean;\n  readonly state: MeetQuestionState;\n  readonly answer: string | null;\n  readonly answeredByName: string | null;\n  readonly upvotes: number;\n  readonly upvotedByMe: boolean;\n  readonly mine: boolean;\n  readonly createdAt: string | null;\n}\n\nexport interface MeetStroke {\n  readonly id: string;\n  /** Points in the board's own 0..1 space. */\n  readonly points: readonly (readonly [number, number])[];\n  readonly color: string;\n  readonly width: number;\n  readonly tool: \"pen\" | \"highlighter\";\n  readonly by: string;\n  readonly byName: string;\n  /** True while this browser's stroke has not come back from the server. */\n  readonly pending?: boolean | undefined;\n}\n\nexport interface MeetBreakoutRoom {\n  readonly id: string;\n  readonly name: string;\n  readonly identities: readonly string[];\n}\n\nexport interface MeetBreakoutBroadcast {\n  readonly text: string;\n  readonly by: string;\n  readonly at: string;\n}\n\nexport interface MeetBreakoutPlan {\n  readonly id: string;\n  readonly state: \"open\" | \"closed\";\n  readonly rooms: readonly MeetBreakoutRoom[];\n  readonly allowChoose: boolean;\n  readonly minutes: number;\n  readonly openedAt: string | null;\n  readonly endsAt: string | null;\n  /** Set while the host's closing countdown runs: everyone returns to the main meeting at this time. */\n  readonly closingAt: string | null;\n  /** `invite` (Join / Later) or `auto` (a countdown, then moved) — the org's `meet.breakout_move`. */\n  readonly moveMode: \"invite\" | \"auto\";\n  readonly closedAt: string | null;\n  readonly broadcasts: readonly MeetBreakoutBroadcast[];\n}\n\n/** The org's knobs for this meeting — which controls EXIST (absent, never dead). */\nexport interface MeetCollabSettings {\n  readonly pollsEnabled: boolean;\n  readonly pollMaxOptions: number;\n  readonly qaEnabled: boolean;\n  readonly qaAnonymousAllowed: boolean;\n  readonly whiteboardEnabled: boolean;\n  readonly breakoutsEnabled: boolean;\n  readonly breakoutMaxRooms: number;\n  readonly breakoutDefaultMinutes: number;\n  readonly captionTranslationEnabled: boolean;\n  /** Empty = the viewer's own language. */\n  readonly captionTranslationLanguage: string;\n}\n\nexport type CollabPanel = \"polls\" | \"qa\" | \"whiteboard\" | \"breakouts\";\n\nexport interface CollabSnapshot {\n  readonly loaded: boolean;\n  /** Why the state could not be read, in words — or null. */\n  readonly error: string | null;\n  readonly settings: MeetCollabSettings | null;\n  readonly polls: readonly MeetPoll[];\n  readonly questions: readonly MeetQuestion[];\n  readonly strokes: readonly MeetStroke[];\n  readonly breakout: MeetBreakoutPlan | null;\n  /** The newest message a host sent to every breakout room, for the banner. */\n  readonly broadcast: MeetBreakoutBroadcast | null;\n  /** A host moved THIS person (or everyone came back): where to go. `undefined` = nothing asked. */\n  readonly moveRequest: { readonly roomId: string | null; readonly at: number } | null;\n  /** Something asked a panel to open (a poll launched, a question arrived for a host). */\n  readonly panelRequest: { readonly panel: CollabPanel; readonly at: number } | null;\n  /** Caption translations for THIS viewer: line id → text, for `captionLanguage`. */\n  readonly captionLanguage: string | null;\n  readonly captionTranslations: Readonly<Record<string, string>>;\n  readonly captionTranslationError: string | null;\n  /**\n   * HR-360 wave 2 (MD-15): the meeting's app panel's ONE shared section focus for this run,\n   * as the server keeps it (`focus_set`); optional so a snapshot built before 0.11 compiles.\n   */\n  readonly focus?: MeetAppFocus | null;\n}\n\nexport const EMPTY_COLLAB: CollabSnapshot = {\n  loaded: false,\n  error: null,\n  settings: null,\n  polls: [],\n  questions: [],\n  strokes: [],\n  breakout: null,\n  broadcast: null,\n  moveRequest: null,\n  panelRequest: null,\n  captionLanguage: null,\n  captionTranslations: {},\n  captionTranslationError: null,\n  focus: null,\n};\n\ntype Row = Record<string, unknown>;\n\nfunction obj(value: unknown): Row | null {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value) ? (value as Row) : null;\n}\nfunction str(value: unknown): string | null {\n  return typeof value === \"string\" ? value : null;\n}\nfunction num(value: unknown): number | null {\n  return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\nfunction strings(value: unknown): string[] {\n  return Array.isArray(value) ? value.filter((v): v is string => typeof v === \"string\") : [];\n}\n\nexport function pollFromRow(row: Row): MeetPoll | null {\n  const id = str(row[\"id\"]);\n  if (id === null) return null;\n  const options: MeetPollOption[] = [];\n  for (const raw of Array.isArray(row[\"options\"]) ? row[\"options\"] : []) {\n    const option = obj(raw);\n    const optionId = option === null ? null : str(option[\"id\"]);\n    if (option === null || optionId === null) continue;\n    const votes = num(option[\"votes\"]);\n    options.push({\n      id: optionId,\n      text: str(option[\"text\"]) ?? \"\",\n      ...(votes !== null ? { votes } : {}),\n      ...(Array.isArray(option[\"voters\"]) ? { voters: strings(option[\"voters\"]) } : {}),\n    });\n  }\n  const state = str(row[\"state\"]);\n  return {\n    id,\n    question: str(row[\"question\"]) ?? \"\",\n    options,\n    multiple: row[\"multiple\"] === true,\n    anonymous: row[\"anonymous\"] === true,\n    state: state === \"live\" || state === \"closed\" ? state : \"draft\",\n    resultsShared: row[\"results_shared\"] === true,\n    voterCount: num(row[\"voter_count\"]),\n    myVote: strings(row[\"my_vote\"]),\n    createdByName: str(row[\"created_by_name\"]) ?? \"\",\n    createdAt: str(row[\"created_at\"]),\n  };\n}\n\nexport function questionFromRow(row: Row): MeetQuestion | null {\n  const id = str(row[\"id\"]);\n  if (id === null) return null;\n  const state = str(row[\"state\"]);\n  return {\n    id,\n    text: str(row[\"text\"]) ?? \"\",\n    askerName: str(row[\"asker_name\"]) ?? \"\",\n    anonymous: row[\"anonymous\"] === true,\n    state: state === \"answered\" || state === \"dismissed\" ? state : \"open\",\n    answer: str(row[\"answer\"]),\n    answeredByName: str(row[\"answered_by_name\"]),\n    upvotes: num(row[\"upvotes\"]) ?? 0,\n    upvotedByMe: row[\"upvoted_by_me\"] === true,\n    mine: row[\"mine\"] === true,\n    createdAt: str(row[\"created_at\"]),\n  };\n}\n\nexport function strokeFromRow(row: Row): MeetStroke | null {\n  const id = str(row[\"id\"]);\n  if (id === null || !Array.isArray(row[\"points\"])) return null;\n  const points: (readonly [number, number])[] = [];\n  for (const raw of row[\"points\"]) {\n    if (Array.isArray(raw) && typeof raw[0] === \"number\" && typeof raw[1] === \"number\") {\n      points.push([raw[0], raw[1]]);\n    }\n  }\n  return {\n    id,\n    points,\n    color: str(row[\"color\"]) ?? \"#111827\",\n    width: num(row[\"width\"]) ?? 3,\n    tool: row[\"tool\"] === \"highlighter\" ? \"highlighter\" : \"pen\",\n    by: str(row[\"by\"]) ?? \"\",\n    byName: str(row[\"by_name\"]) ?? \"\",\n  };\n}\n\nfunction broadcastFrom(value: unknown): MeetBreakoutBroadcast | null {\n  const row = obj(value);\n  const text = row === null ? null : str(row[\"text\"]);\n  if (row === null || text === null) return null;\n  return { text, by: str(row[\"by\"]) ?? \"\", at: str(row[\"at\"]) ?? \"\" };\n}\n\nexport function planFromRow(row: Row): MeetBreakoutPlan | null {\n  const id = str(row[\"id\"]);\n  if (id === null) return null;\n  const rooms: MeetBreakoutRoom[] = [];\n  for (const raw of Array.isArray(row[\"rooms\"]) ? row[\"rooms\"] : []) {\n    const room = obj(raw);\n    const roomId = room === null ? null : str(room[\"id\"]);\n    if (room === null || roomId === null) continue;\n    rooms.push({ id: roomId, name: str(room[\"name\"]) ?? roomId, identities: strings(room[\"identities\"]) });\n  }\n  return {\n    id,\n    state: row[\"state\"] === \"open\" ? \"open\" : \"closed\",\n    rooms,\n    allowChoose: row[\"allow_choose\"] === true,\n    minutes: num(row[\"minutes\"]) ?? 0,\n    openedAt: str(row[\"opened_at\"]),\n    endsAt: str(row[\"ends_at\"]),\n    closingAt: str(row[\"closing_at\"]),\n    moveMode: row[\"move_mode\"] === \"auto\" ? \"auto\" : \"invite\",\n    closedAt: str(row[\"closed_at\"]),\n    broadcasts: (Array.isArray(row[\"broadcasts\"]) ? row[\"broadcasts\"] : [])\n      .map(broadcastFrom)\n      .filter((b): b is MeetBreakoutBroadcast => b !== null),\n  };\n}\n\nexport function settingsFromRow(row: Row | null): MeetCollabSettings | null {\n  if (row === null) return null;\n  return {\n    pollsEnabled: row[\"polls_enabled\"] === true,\n    pollMaxOptions: num(row[\"poll_max_options\"]) ?? 10,\n    qaEnabled: row[\"qa_enabled\"] === true,\n    qaAnonymousAllowed: row[\"qa_anonymous_allowed\"] === true,\n    whiteboardEnabled: row[\"whiteboard_enabled\"] === true,\n    breakoutsEnabled: row[\"breakouts_enabled\"] === true,\n    breakoutMaxRooms: num(row[\"breakout_max_rooms\"]) ?? 20,\n    breakoutDefaultMinutes: num(row[\"breakout_default_minutes\"]) ?? 15,\n    captionTranslationEnabled: row[\"caption_translation_enabled\"] === true,\n    captionTranslationLanguage: str(row[\"caption_translation_language\"]) ?? \"\",\n  };\n}\n\n/** The server's `GET /collab` body → a loaded snapshot (keeps this viewer's caption state). */\nexport function collabFromState(body: Row, previous: CollabSnapshot): CollabSnapshot {\n  const list = <T>(key: string, parse: (row: Row) => T | null): T[] =>\n    (Array.isArray(body[key]) ? body[key] : [])\n      .map((raw) => {\n        const row = obj(raw);\n        return row === null ? null : parse(row);\n      })\n      .filter((item): item is T => item !== null);\n  const breakoutRow = obj(body[\"breakout\"]);\n  return {\n    ...previous,\n    loaded: true,\n    error: null,\n    settings: settingsFromRow(obj(body[\"settings\"])),\n    polls: list(\"polls\", pollFromRow),\n    questions: list(\"questions\", questionFromRow),\n    strokes: list(\"strokes\", strokeFromRow),\n    breakout: breakoutRow === null ? null : planFromRow(breakoutRow),\n    focus: focusFromRow(body[\"focus\"]),\n  };\n}\n\nfunction upsert<T extends { id: string }>(items: readonly T[], next: T): T[] {\n  const index = items.findIndex((item) => item.id === next.id);\n  if (index === -1) return [...items, next];\n  const copy = items.slice();\n  copy[index] = next;\n  return copy;\n}\n\n/**\n * Fold one server item into the snapshot. `fromRoom` = it came on the room broadcast,\n * which cannot know THIS viewer's vote, upvote or authorship — those are kept from what\n * the viewer's own reads and answers already said.\n */\nexport function withItem(collab: CollabSnapshot, row: Row, fromRoom = false): CollabSnapshot {\n  const kind = str(row[\"kind\"]);\n  if (kind === \"poll\") {\n    const poll = pollFromRow(row);\n    if (poll === null) return collab;\n    // A ROOM packet cannot know this viewer's vote; keep the one we already hold.\n    const known = collab.polls.find((p) => p.id === poll.id);\n    let merged = fromRoom && known !== undefined ? { ...poll, myVote: known.myVote } : poll;\n    // A room copy carries no counts until results are shared; a HOST already holding\n    // counts (from their own read or the hosts' packet) keeps them until newer ones land.\n    if (fromRoom && known !== undefined && !poll.options.some((o) => o.votes !== undefined)) {\n      const counted = new Map(known.options.map((o) => [o.id, o]));\n      merged = {\n        ...merged,\n        voterCount: known.voterCount,\n        options: merged.options.map((o) => {\n          const had = counted.get(o.id);\n          return had === undefined ? o : { ...o, votes: had.votes, voters: had.voters };\n        }),\n      };\n    }\n    return { ...collab, polls: upsert(collab.polls, merged) };\n  }\n  if (kind === \"question\") {\n    const question = questionFromRow(row);\n    if (question === null) return collab;\n    const known = collab.questions.find((q) => q.id === question.id);\n    // `mine` / `upvoted_by_me` are per viewer; a room packet says false for everyone.\n    const merged =\n      fromRoom && known !== undefined\n        ? { ...question, mine: known.mine, upvotedByMe: known.upvotedByMe }\n        : question;\n    return { ...collab, questions: upsert(collab.questions, merged) };\n  }\n  if (kind === \"stroke\") {\n    const stroke = strokeFromRow(row);\n    if (stroke === null) return collab;\n    return { ...collab, strokes: upsert(collab.strokes, stroke) };\n  }\n  if (kind === \"breakout\") {\n    const plan = planFromRow(row);\n    if (plan === null) return collab;\n    return { ...collab, breakout: plan };\n  }\n  return collab;\n}\n\nfunction without(collab: CollabSnapshot, ids: readonly string[]): CollabSnapshot {\n  const gone = new Set(ids);\n  return {\n    ...collab,\n    polls: collab.polls.filter((p) => !gone.has(p.id)),\n    questions: collab.questions.filter((q) => !gone.has(q.id)),\n    strokes: collab.strokes.filter((s) => !gone.has(s.id)),\n  };\n}\n\nexport interface CollabPacketContext {\n  readonly localIdentity: ParticipantIdentity | null;\n  /** Hosts and co-hosts receive a second, fuller packet; they ignore the room copy. */\n  readonly isHost: boolean;\n  readonly now: number;\n}\n\n/**\n * One `matrx.meet.collab` packet → the next snapshot, or `null` when it must be dropped\n * (with the reason in `dropped`). Pure; the room-event dispatcher patches the store.\n */\nexport function applyCollabPacket(\n  collab: CollabSnapshot,\n  payload: Row,\n  context: CollabPacketContext,\n): { next: CollabSnapshot | null; dropped?: string } {\n  const item = obj(payload[\"item\"]);\n  if (item !== null) {\n    const kind = str(item[\"kind\"]);\n    // Every copy is folded — the room's AND the hosts' fuller one. `withItem` keeps a\n    // host's counts when a count-less room copy arrives, so neither copy can blank the\n    // other, and a host still sees an item the server sent the room only (a new question).\n    let next = withItem(collab, item, true);\n    if (kind === \"poll\" && str(item[\"state\"]) === \"live\") {\n      const before = collab.polls.find((p) => p.id === str(item[\"id\"]));\n      if (before === undefined || before.state !== \"live\") {\n        next = { ...next, panelRequest: { panel: \"polls\", at: context.now } };\n      }\n    }\n    if (kind === \"breakout\") {\n      const plan = planFromRow(item);\n      if (plan !== null && plan.state === \"closed\") {\n        next = { ...next, moveRequest: { roomId: null, at: context.now } };\n      }\n    }\n    const move = obj(payload[\"move\"]);\n    if (move !== null && str(move[\"identity\"]) === context.localIdentity) {\n      next = { ...next, moveRequest: { roomId: str(move[\"room_id\"]), at: context.now } };\n    }\n    return { next };\n  }\n  if (payload[\"focus\"] !== undefined) {\n    const focus = focusFromRow(payload[\"focus\"]);\n    return focus === null ? { next: null, dropped: \"a focus packet without a panel\" } : { next: { ...collab, focus } };\n  }\n  if (Array.isArray(payload[\"removed\"])) {\n    return { next: without(collab, strings(payload[\"removed\"])) };\n  }\n  if (Array.isArray(payload[\"hidden\"])) {\n    // A dismissed question leaves everyone's list — but a host keeps it (their packet\n    // carries the dismissed state).\n    return context.isHost ? { next: null, dropped: \"hosts keep dismissed questions\" } : { next: without(collab, strings(payload[\"hidden\"])) };\n  }\n  if (payload[\"cleared\"] === \"whiteboard\") {\n    return { next: { ...collab, strokes: [] } };\n  }\n  const broadcast = broadcastFrom(payload[\"broadcast\"]);\n  if (broadcast !== null) {\n    return { next: { ...collab, broadcast } };\n  }\n  return { next: null, dropped: \"a collab packet with nothing this version understands\" };\n}\n\n/** The breakout room a person is assigned to, or null. */\nexport function assignedRoom(plan: MeetBreakoutPlan | null, identity: string | null): MeetBreakoutRoom | null {\n  if (plan === null || plan.state !== \"open\" || identity === null) return null;\n  return plan.rooms.find((room) => room.identities.includes(identity)) ?? null;\n}\n\n/**\n * Split people into `rooms` rooms, round-robin in the order given — Zoom's \"assign\n * automatically\". Hosts are left out (they visit); pass them in `exclude`.\n */\nexport function autoAssign(\n  identities: readonly string[],\n  rooms: number,\n  exclude: readonly string[] = [],\n): string[][] {\n  const count = Math.max(1, Math.floor(rooms));\n  const out: string[][] = Array.from({ length: count }, () => []);\n  const skip = new Set(exclude);\n  let index = 0;\n  for (const identity of identities) {\n    if (skip.has(identity)) continue;\n    out[index % count]!.push(identity);\n    index += 1;\n  }\n  return out;\n}\n\n/** Milliseconds until the plan's timer ends, or null when it has none. */\nexport function breakoutRemainingMs(plan: MeetBreakoutPlan | null, now: number): number | null {\n  if (plan === null || plan.state !== \"open\") return null;\n  const ends = [plan.endsAt, plan.closingAt]\n    .map((stamp) => (stamp === null ? Number.NaN : Date.parse(stamp)))\n    .filter((time) => !Number.isNaN(time));\n  if (ends.length === 0) return null;\n  return Math.max(0, Math.min(...ends) - now);\n}\n\n/** Meet shows a 30 second countdown before rooms end; the host's Close starts one at once. */\nexport const BREAKOUT_COUNTDOWN_MS = 30_000;\n\n/**\n * The closing countdown to show, in ms — or null when the rooms are not closing. Closing\n * means the host asked (`closingAt`) or the timer is within its last 30 seconds.\n */\nexport function breakoutClosingMs(plan: MeetBreakoutPlan | null, now: number): number | null {\n  if (plan === null || plan.state !== \"open\") return null;\n  const remaining = breakoutRemainingMs(plan, now);\n  if (remaining === null) return null;\n  return plan.closingAt !== null || remaining <= BREAKOUT_COUNTDOWN_MS ? remaining : null;\n}\n\n/** The language translated captions start in: the knob, else the viewer's own. */\nexport function defaultCaptionLanguage(\n  settings: MeetCollabSettings | null,\n  viewerLanguage: string | null | undefined,\n): string {\n  const configured = settings?.captionTranslationLanguage.trim() ?? \"\";\n  if (configured.length > 0) return configured;\n  const own = (viewerLanguage ?? \"\").trim();\n  return own.length > 0 ? own : \"en\";\n}\n\n/** Languages offered in the captions menu (tags the translator understands). */\nexport const CAPTION_LANGUAGES: readonly { readonly tag: string; readonly name: string }[] = [\n  { tag: \"en\", name: \"English\" },\n  { tag: \"es\", name: \"Spanish\" },\n  { tag: \"fr\", name: \"French\" },\n  { tag: \"de\", name: \"German\" },\n  { tag: \"it\", name: \"Italian\" },\n  { tag: \"pt\", name: \"Portuguese\" },\n  { tag: \"nl\", name: \"Dutch\" },\n  { tag: \"pl\", name: \"Polish\" },\n  { tag: \"ru\", name: \"Russian\" },\n  { tag: \"uk\", name: \"Ukrainian\" },\n  { tag: \"tr\", name: \"Turkish\" },\n  { tag: \"ar\", name: \"Arabic\" },\n  { tag: \"he\", name: \"Hebrew\" },\n  { tag: \"fa\", name: \"Persian\" },\n  { tag: \"hi\", name: \"Hindi\" },\n  { tag: \"bn\", name: \"Bengali\" },\n  { tag: \"zh\", name: \"Chinese\" },\n  { tag: \"ja\", name: \"Japanese\" },\n  { tag: \"ko\", name: \"Korean\" },\n  { tag: \"vi\", name: \"Vietnamese\" },\n  { tag: \"th\", name: \"Thai\" },\n  { tag: \"id\", name: \"Indonesian\" },\n  { tag: \"sv\", name: \"Swedish\" },\n];\n\nexport interface MeetingActivities {\n  /** Polls (with results), questions, whiteboard strokes — or null when refused. */\n  readonly collab: CollabSnapshot | null;\n  readonly refusal: { readonly message: string; readonly remedy: string } | null;\n}\n\n/**\n * THE MEETING'S POLLS, Q&A AND WHITEBOARD, AFTER IT (Meet wave 5) — for the record page.\n * The same `GET /v1/meet/collab` the room reads on join; a refusal is returned as data,\n * so the record still renders everything else.\n */\nexport async function loadMeetingActivities(\n  api: MeetApi,\n  meetingId: string,\n  meetingPass: string | null = null,\n): Promise<MeetingActivities> {\n  let response: Response;\n  try {\n    response = await api.request({\n      path: `${MEET_ROUTES.collab}?meeting_id=${encodeURIComponent(meetingId)}`,\n      method: \"GET\",\n      operation: \"meet.loadMeetingActivities\",\n      requireAuth: meetingPass === null,\n      ...(meetingPass !== null ? { headers: { [MEETING_PASS_HEADER]: meetingPass } } : {}),\n    });\n  } catch (error) {\n    return {\n      collab: null,\n      refusal: {\n        message: `Polls, questions and the whiteboard could not be read (${(error as Error).message}).`,\n        remedy: (error as { remedy?: string }).remedy ?? \"Reload the page.\",\n      },\n    };\n  }\n  if (!response.ok) {\n    let body: unknown = null;\n    try {\n      body = await response.json();\n    } catch {\n      body = null;\n    }\n    const said = readRefusalBody(body);\n    return {\n      collab: null,\n      refusal: {\n        message: said?.reason ?? `Polls and questions could not be read (the server answered ${response.status}).`,\n        remedy: said?.remedy || \"Reload the page.\",\n      },\n    };\n  }\n  return { collab: collabFromState((await response.json()) as Row, EMPTY_COLLAB), refusal: null };\n}\n","/**\n * CAPTIONS ARE HINTS; SEGMENTS ARE TRUTH (D16).\n *\n * Two independent streams describe the same speech and they arrive out of order\n * with different identities:\n *\n * 1. **Captions** ride the LiveKit `lk.transcription` text stream, keyed by\n *    `lk.segment_id`, interim-then-final, milliseconds behind the voice. They\n *    exist so a person can READ the room live. Their `sender_identity` is\n *    supplied by the publishing client and LiveKit does not validate it, so\n *    nothing downstream — notes, Q&A, the wrap-up — may ever read them.\n * 2. **Records** are `communication.meet_transcript_segments` rows, written\n *    server-side by the note-taker with a deterministic id (D6) and delivered\n *    here by Postgres Changes. They are the meeting's transcript.\n *\n * The reconciliation below is what keeps the screen from saying everything\n * twice. A record REPLACES the caption it supersedes — matched by the caption\n * id the worker carries into the row, and failing that by speaker + text — and\n * a caption never overwrites a record, however late it lands.\n *\n * Everything here is a pure function over a list so the rules are provable\n * without a store, a socket, or a browser.\n */\n\nimport type { ParticipantIdentity, TranscriptSegment } from \"./types\";\n\n/** Comparable text: case, punctuation and spacing are not differences. */\nexport function normalizeSpoken(text: string): string {\n  return text\n    .toLowerCase()\n    .replace(/[^\\p{L}\\p{N}]+/gu, \" \")\n    .trim();\n}\n\nfunction supersedes(record: TranscriptSegment, caption: TranscriptSegment): boolean {\n  if (caption.source !== \"caption\") return false;\n  if (caption.identity !== record.identity) return false;\n  if (record.captionId !== null && caption.captionId === record.captionId) return true;\n  const left = normalizeSpoken(record.text);\n  const right = normalizeSpoken(caption.text);\n  if (left.length === 0 || right.length === 0) return false;\n  // An interim caption is a PREFIX of what was finally said; a final caption and\n  // its record usually differ only in punctuation. Both are the same utterance.\n  return left === right || left.startsWith(right) || right.startsWith(left);\n}\n\n/**\n * A caption arrived. Interim replaces interim in place; a final never loses to a\n * late interim; a record is never touched.\n */\nexport function mergeCaption(\n  list: readonly TranscriptSegment[],\n  caption: TranscriptSegment,\n): readonly TranscriptSegment[] {\n  const index = list.findIndex(\n    (entry) => entry.captionId !== null && entry.captionId === caption.captionId,\n  );\n  if (index === -1) {\n    // The record for this utterance may already be here (the row can beat the\n    // caption on a slow media path). Do not draw the same sentence twice.\n    if (list.some((entry) => entry.source === \"record\" && supersedes(entry, caption))) {\n      return list;\n    }\n    return [...list, caption];\n  }\n  const existing = list[index];\n  if (existing === undefined) return list;\n  // TRUTH WINS. A caption cannot revert a durable row, and a late interim cannot\n  // revert a final — that is a finished sentence visibly becoming a half-word.\n  if (existing.source === \"record\") return list;\n  if (existing.final && !caption.final) return list;\n  return list.map((entry, position) => (position === index ? caption : entry));\n}\n\n/**\n * A durable row arrived. It replaces the caption it supersedes — in place, so\n * the line does not jump down the panel — or lands as a new line if no caption\n * ever showed it (a surface that joined late, or captions that never came).\n */\nexport function mergeRecord(\n  list: readonly TranscriptSegment[],\n  record: TranscriptSegment,\n): readonly TranscriptSegment[] {\n  const byId = list.findIndex((entry) => entry.source === \"record\" && entry.id === record.id);\n  if (byId !== -1) {\n    const existing = list[byId];\n    if (existing !== undefined && existing.text === record.text && existing.final === record.final) {\n      return list;\n    }\n    return list.map((entry, position) => (position === byId ? record : entry));\n  }\n  const captionIndex = list.findIndex((entry) => supersedes(record, entry));\n  if (captionIndex === -1) return [...list, record];\n  return list.map((entry, position) => (position === captionIndex ? record : entry));\n}\n\n/** The transcript a person reads: chronological, and never an empty line. */\nexport function readableTranscript(\n  list: readonly TranscriptSegment[],\n): readonly TranscriptSegment[] {\n  return [...list]\n    .filter((entry) => entry.text.trim().length > 0)\n    .sort((left, right) => left.startedAt.localeCompare(right.startedAt));\n}\n\n/** Build a caption line from the media plane. */\nexport function captionSegment(args: {\n  captionId: string;\n  meetingId: TranscriptSegment[\"meetingId\"];\n  identity: ParticipantIdentity;\n  speaker: string;\n  text: string;\n  final: boolean;\n  startedAt: string;\n}): TranscriptSegment {\n  return {\n    id: `caption:${args.captionId}`,\n    meetingId: args.meetingId,\n    identity: args.identity,\n    speaker: args.speaker,\n    text: args.text,\n    startedAt: args.startedAt,\n    final: args.final,\n    source: \"caption\",\n    captionId: args.captionId,\n  };\n}\n","/**\n * THE ROOM SNAPSHOT — one immutable object the UI renders and nothing else.\n *\n * Deliberately NOT Redux, NOT a context full of `useState`, and NOT a bag of\n * refs: one store with `getSnapshot`/`subscribe` is exactly what\n * `useSyncExternalStore` wants, which is what makes tearing impossible when a\n * roster event and a speaker event land in the same tick.\n *\n * The rules encoded here:\n *\n * - **The roster is replaced wholesale, never patched.** The driver hands us\n *   the full truth on every media event (see `room-driver.ts`); merging deltas\n *   from six event sources is how a tile for someone who left stays on screen.\n * - **Ephemera EXPIRE.** Reactions and speaking flags are time-boxed in the\n *   snapshot, so a dropped \"stop\" event cannot leave a permanent 🎉 or a\n *   permanently-speaking ring. (Nothing here relies on receiving an end event.)\n * - **An interim transcript line is REPLACED in place by its final.** Appending\n *   both is how a transcript ends up saying everything twice.\n */\n\nimport { displayNameFor, learnName, learnNames, type NameBook } from \"./names\";\nimport { isRecordingInFlight } from \"./recording\";\nimport { DEFAULT_LEAVE_POLICY, type LeavePolicy } from \"./leave\";\nimport { DEFAULT_LIVE_POLICY, type LivePolicy } from \"./live-policy\";\nimport { IDLE_MEDIA, IDLE_MEDIA_REGION, type LocalMediaState, type LocalTrackState, type MediaRegionState } from \"./attendance\";\nimport { ROLE_RANK } from \"./types\";\nimport { nextPhase, reasonOf, type MeetPhase, type PhaseEvent } from \"./phase\";\nimport type { ObserversVisibleTo } from \"./types\";\nimport type { NoteTakerRefusal } from \"./note-taker\";\nimport { EMPTY_COLLAB, type CollabSnapshot } from \"./collab\";\nimport { mergeCaption, mergeRecord } from \"./transcript\";\nimport type {\n  AdmissionState,\n  ConnectionQuality,\n  LobbyEntry,\n  MeetParticipant,\n  MeetingNote,\n  MeetingRecord,\n  ParticipantIdentity,\n  ParticipantRole,\n  ParticipantStanding,\n  RecordingSource,\n  RecordingState,\n  StageLayout,\n  TranscriptSegment,\n  UserId,\n  WrapUpAnnouncement,\n  RoomName,\n  CallInvite,\n} from \"./types\";\n\nexport interface RoomChatMessage {\n  readonly id: string;\n  readonly identity: ParticipantIdentity;\n  readonly displayName: string;\n  readonly text: string;\n  readonly at: string;\n  /**\n   * Set for a PRIVATE message: the one identity it was addressed to (from the\n   * sender's side) or this participant (from the receiver's). Private messages\n   * travel the data plane only and are never saved (Meet wave 2).\n   */\n  readonly to?: ParticipantIdentity | null | undefined;\n  /** True once the server has SAVED it — a message everyone sees, late joiners too. */\n  readonly saved?: boolean | undefined;\n  /** A send the server refused, with its sentence. The message stays visible, marked. */\n  readonly failed?: string | undefined;\n}\n\n/**\n * A HOST ACTED ON *ME* (Meet wave 2) — the server's own `matrx.meet.moderation`\n * packet, addressed to this participant. Rendered once, dismissible, in words.\n */\nexport interface ModerationNotice {\n  readonly kind: \"muted\" | \"ask-unmute\" | \"removed\" | \"role\" | \"locked\" | \"capability\";\n  readonly text: string;\n  readonly at: number;\n}\n\n/** What this participant chose for their own media. Remembered per browser. */\nexport interface MediaEffects {\n  readonly noiseSuppression: boolean;\n  readonly background: \"none\" | \"blur\" | \"image\";\n  readonly backgroundImage: string | null;\n}\n\nexport const DEFAULT_EFFECTS: MediaEffects = {\n  noiseSuppression: true,\n  background: \"none\",\n  backgroundImage: null,\n};\n\nexport interface RoomReaction {\n  readonly id: string;\n  readonly identity: ParticipantIdentity;\n  readonly emoji: string;\n  readonly at: number;\n}\n\n/**\n * 🚨 WHAT THE SERVER GRANTED THIS JOINER, straight off the token response\n * (MRI-A11). It is placed in the snapshot the instant the token lands — before\n * the LiveKit roster exists at all — so a host's controls are correct on the\n * first frame of the room rather than one roster event later. The roster entry\n * for the local participant carries the SAME decision as a LiveKit attribute;\n * the two agree because one server statement produced both, and the UI reads\n * whichever has arrived.\n */\nexport interface MeetGrants {\n  readonly role: ParticipantRole;\n  /** Where this joiner stands with the meeting (server-minted, beside the role). */\n  readonly standing?: ParticipantStanding | null;\n  readonly canRecord: boolean;\n  readonly canPublish: boolean;\n  readonly canSubscribe: boolean;\n  /** HR-360 wave 2 (MD-16): who sees the \"Observing\" line in People (knob). */\n  readonly observersVisibleTo?: ObserversVisibleTo | undefined;\n}\n\n/** No token yet grants nothing. Never \"assume host until told otherwise\". */\nexport const NO_GRANTS: MeetGrants = {\n  role: \"participant\",\n  standing: null,\n  canRecord: false,\n  canPublish: false,\n  canSubscribe: false,\n};\n\n/**\n * S4 — THIS PERSON'S WAIT, as the server's state read (`GET /v1/meet/state`) last said it\n * (CORE-DESIGN §2.6). Set while the phase is a waiting one (`waiting:*`, `denied`,\n * `knock_expired`); the waiting screens read it, never a broadcast. `admission` is the row's own word: `waiting_host` · `knocking` · `denied` ·\n * `expired` · `withdrawn` · `ended` (`admitted` is never held here — it is a join).\n */\nexport interface MeetWaiting {\n  readonly admission: AdmissionState;\n  /** Is anyone who may admit in the room? null until the first read. */\n  readonly admittersPresent: boolean | null;\n  /** May a denied person ask again (`reknock_after_deny`)? */\n  readonly reknockAllowed: boolean;\n  readonly knockExpiresAt: string | null;\n  /** While a denial's cooldown runs: the epoch-ms moment the person may ask again; else null. */\n  readonly reknockAt?: number | null;\n  /** How often the core reads while waiting (`waiting_poll_seconds`). */\n  readonly pollSeconds: number;\n  /** The run's `live_version` at the last read. */\n  readonly liveVersion: number;\n}\n\n/** The core's `connection` region (CORE-DESIGN §3.2) — never a phase. */\nexport interface LocalNetwork {\n  readonly path: \"direct\" | \"restricted\" | \"unknown\";\n  readonly quality: \"good\" | \"poor\" | \"unknown\";\n  readonly videoPaused: boolean;\n}\n\nexport const UNKNOWN_LOCAL_NETWORK: LocalNetwork = { path: \"unknown\", quality: \"unknown\", videoPaused: false };\n\nexport type ConnectionRegion = \"stable\" | \"signal_reconnecting\" | \"reconnecting\" | \"offline\" | \"server_unreachable\";\n\n/**\n * The core's `share` region (CORE-DESIGN §3.2/§3.3 SA). A refused share is a situation the person\n * is in — a notice (`share-unavailable`), never a phase.\n */\nexport interface ShareRegion {\n  readonly state: \"none\" | \"picking\" | \"presenting\" | \"refused\" | \"ended\";\n  /**\n   * Why a share was refused (this browser cannot share, the system blocks it, or it failed) or, for\n   * `ended`, why the server took it down: someone else presented instead, or the host's rule no longer lets this person share.\n   */\n  readonly reason: \"unsupported\" | \"blocked\" | \"failed\" | \"replaced\" | \"not_allowed\" | null;\n  /** `ended` / `replaced`: who presents now. */\n  readonly by?: string;\n  /** The fix, in the core's words (system setting, administrator policy, …), or null. */\n  readonly remedy: string | null;\n  readonly at: number;\n  /** While presenting: whether the share carries sound (`share-audio`). Absent = not known. */\n  readonly audio?: boolean;\n}\n\nexport const NO_SHARE: ShareRegion = { state: \"none\", reason: null, remedy: null, at: 0 };\n\nexport interface MeetSnapshot {\n  /**\n   * WHERE THIS TAB IS — the contract's `data-meet-phase` value, verbatim (CORE-DESIGN §3.1).\n   * Written ONLY by `store.dispatch(event)` through the phase machine (`core/phase.ts`);\n   * `patch` cannot touch it.\n   */\n  readonly phase: MeetPhase;\n  /** `data-meet-reason` for a refused / terminal phase; null otherwise. */\n  readonly reason: string | null;\n  /** A notice that came WITH the phase (`sent-to-waiting`), or null. */\n  readonly phaseNotice: string | null;\n  /** The room this tab last joined (or is joining) — a different meeting mounting resets. */\n  readonly roomName: RoomName | null;\n  /** The `connection` region: reconnecting is here, never a phase. */\n  readonly connection: ConnectionRegion;\n  /**\n   * Whether the reconnect banner shows: the region is honest at once, the banner only after the\n   * drop outlasts `reconnect_banner_delay_ms` (the connection supervisor sets it, §3.3 CS).\n   */\n  readonly connectionBanner: boolean;\n  /**\n   * P1 connection-network — THIS tab's own path, as the core judged it from its WebRTC stats\n   * (`network-health.ts`): `restricted` = relayed or TCP-only (`net-udp-blocked`), `quality` =\n   * the self-assessment (`net-quality-self`), `videoPaused` = the camera was paused by the\n   * network to keep the audio (`net-video-auto-off`). The room engine is the one writer.\n   */\n  readonly localNetwork: LocalNetwork;\n  /** The `share` region. */\n  readonly share: ShareRegion;\n  /**\n   * The 1:1 call this tab is placing or answering (CORE-DESIGN §3.6) — the core `calls` slice.\n   * The ringing phases (`ringing_out` / `ringing_in` / `call_*`) describe it; null = no call.\n   */\n  readonly call: { readonly invite: CallInvite; readonly direction: \"outgoing\" | \"incoming\" } | null;\n  /** S4: this person's wait (see `MeetWaiting`); null outside the waiting room. */\n  readonly waiting: MeetWaiting | null;\n  readonly meeting: MeetingRecord | null;\n  readonly localIdentity: ParticipantIdentity | null;\n  /**\n   * S7: this person is already in this meeting on another tab or device, and the pre-join offers\n   * the meeting's choice — `rule` is the `second_device` knob (`ask_switch_or_join` · Meet: Switch\n   * here / Join here too; `ask_transfer_or_add` · Teams: Transfer / Add). Null otherwise.\n   */\n  readonly secondDevice: { readonly rule: string } | null;\n  /** The server's word on what THIS joiner may do. See `MeetGrants`. */\n  readonly grants: MeetGrants;\n  readonly participants: readonly MeetParticipant[];\n  readonly activeSpeakers: readonly ParticipantIdentity[];\n  readonly pinned: ParticipantIdentity | null;\n  readonly layout: StageLayout;\n  readonly lobby: readonly LobbyEntry[];\n  readonly locked: boolean;\n  /**\n   * 🚨 THE DURABLE `meet_recordings.state`, not a client's hope. Through 0.4.7\n   * this only ever held what THIS browser optimistically patched — `starting`\n   * on the click, `stopping` on the stop — so the indicator read \"Starting\n   * recording…\" for the whole meeting while a perfectly healthy egress ran, and\n   * \"Stopping recording…\" forever after (MRI-C8). The server's transitions\n   * arrive on two transports now: the `meet_recordings` row for a member, and\n   * the room's replicated state for a guest, who has no database.\n   */\n  readonly recording: RecordingState;\n  readonly recordingStartedBy: UserId | null;\n  /**\n   * WHICH transport last spoke, so the two cannot undo each other (D16). The\n   * database wins: `\"record\"` is never overwritten by `\"room\"` or `\"local\"`.\n   */\n  readonly recordingSource: RecordingSource;\n  /**\n   * WHICH recording this state is about. It is what tells a LATE packet for a\n   * finished recording apart from the FIRST packet of the next one — without\n   * it, \"the database wins\" either blocks a second recording forever or lets a\n   * stale packet drag a finished one back to `recording`.\n   */\n  readonly recordingId: string | null;\n  readonly chat: readonly RoomChatMessage[];\n  /** Whether the SAVED chat has been read for this meeting (late joiners see history). */\n  readonly chatLoaded: boolean;\n  /** Why the saved chat could not be read on join, in words — or null. */\n  readonly chatHistoryError: string | null;\n  readonly reactions: readonly RoomReaction[];\n  /**\n   * The participant a HOST spotlighted for everyone, from the room's metadata\n   * (server-set, delivered on join). A local pin outranks it on this screen only.\n   */\n  readonly spotlight: ParticipantIdentity | null;\n  /**\n   * S8 REPLICATED ROOM STATE (CORE-DESIGN §2.6 RS), from the room's metadata — the server's\n   * truth, delivered on join and after every reconnect: who holds the run's host powers\n   * (`actingHost`), who is presenting, and how many people wait to be let in.\n   */\n  readonly actingHost: ParticipantIdentity | null;\n  readonly presenter: ParticipantIdentity | null;\n  readonly waitingCount: number;\n  /** S8: what the host's Leave offers in this meeting (from the token's `leave_policy`). */\n  readonly leavePolicy: LeavePolicy;\n  /** The meeting's rules as they are RIGHT NOW (chat mode, attendee lock, time limit), read live while in the call. */\n  readonly livePolicy: LivePolicy;\n  /** host-reclaim: this person is the meeting's owner and may take the host powers back (Zoom rules). */\n  readonly canReclaim: boolean;\n  /** rec-consent-gate: this person agreed to the recording that is running. */\n  readonly recordingConsentGiven: boolean;\n  /** When this run started (epoch ms), so every screen counts a time limit down together. */\n  readonly sessionStartedAt: number | null;\n  /** True from the moment a host muted THIS microphone until the person turns it on themselves. */\n  readonly mutedByHost: boolean;\n  /** The last thing a host did to THIS participant, in words. Dismissible. */\n  readonly moderationNotice: ModerationNotice | null;\n  /**\n   * The server's answer to the last host action THIS participant took (\"Muted 3\n   * people\", or the refusal). One place, so whichever surface acted — a tile's\n   * menu, the People panel, More options — the sentence survives the menu closing.\n   */\n  readonly actionNotice: { readonly text: string; readonly failed: boolean; readonly at: number } | null;\n  /**\n   * \"Message privately\" asked for from ANY per-person menu — a tile's, the\n   * People panel's — and answered by the one `ControlBar` that owns the chat\n   * panel (0.7.8). Through 0.7.7 only the People panel could open a private\n   * chat, so the Board's tile menu (and the Room's) had no such item while the\n   * People panel did: two menus for one person that disagreed.\n   */\n  readonly privateChatRequest: { readonly to: ParticipantIdentity; readonly at: number } | null;\n  readonly effects: MediaEffects;\n  /**\n   * Captions AND durable rows, reconciled into one list (D16). A record\n   * replaces the caption it supersedes; a caption never overwrites a record.\n   */\n  readonly transcript: readonly TranscriptSegment[];\n  readonly notes: readonly MeetingNote[];\n  /**\n   * 🚨 IDENTITY → THE BEST NAME ANYTHING HAS EVER KNOWN (MRI-A16). Learned from\n   * every source that has one — the roster, a durable segment, a durable\n   * attendance row, a chat message — and never unlearned, so a caption that\n   * lands after somebody leaves still says who spoke. It exists because the\n   * host and the guest rendered DIFFERENT names for the same speaker in the\n   * same second, one of them a raw LiveKit token (MRI-C8). See `core/names.ts`.\n   */\n  readonly names: NameBook;\n  /**\n   * The wrap-up pass ANNOUNCED itself (MRI-A12). `null` means it has not been\n   * announced in this room — which is not the same as \"no summary exists\", and\n   * no surface may render it as such.\n   */\n  readonly wrapUp: WrapUpAnnouncement | null;\n  /**\n   * The server's last refusal to dispatch the note-taker, in ITS words (D7).\n   * Rendered verbatim; never replaced by a spinner or a house sentence.\n   */\n  readonly noteTakerRefusal: NoteTakerRefusal | null;\n  /** `captions-toggle`: THIS viewer wants captions. Local to the viewer; never sent to the room. */\n  readonly captionsOn: boolean;\n  /** Why asking for captions failed, in the server's words (`captions-unavailable`). */\n  readonly captionsRefusal: NoteTakerRefusal | null;\n  /** `captions_start_timeout_seconds` from the token's knobs; the \"Starting captions\" ceiling. */\n  readonly captionsStartTimeoutSeconds: number;\n  /**\n   * What the LOCAL participant is actually publishing, and why not when it is\n   * not. Attendance never depends on it (see `attendance.ts`): a refused\n   * microphone is a state with a remedy, not a failed join.\n   */\n  readonly media: LocalMediaState;\n  /**\n   * S6c — the media supervisor's regions: permission per kind, autoplay (`audio_output`), the\n   * last device change and an offered new device. Written only by `media-supervisor.ts`.\n   */\n  readonly mediaRegion: MediaRegionState;\n  /** The last failure, with its remedy. Never null-and-hoping. */\n  readonly failure: {\n    readonly message: string;\n    readonly remedy: string;\n    /** The join gate's reason code, when the server named one (CORE-DESIGN §2.5). */\n    readonly reason?: string | null;\n    /**\n     * When a refusal lifts by itself (a denial's cooldown): the epoch-ms moment the person may\n     * ask again. Absent for every refusal that does not lift (CORE-DESIGN §11 `wr-denied-reknock`).\n     */\n    readonly retryAt?: number | null;\n    /**\n     * `join` = the person never got into the call this time (`net-cannot-connect`): a network or\n     * server failure on the way IN is \"can't connect\", not \"lost your connection\".\n     */\n    readonly stage?: \"join\";\n  } | null;\n  /**\n   * Meet wave 5: polls, Q&A, the shared whiteboard and the breakout plan — what the\n   * server said, per viewer (`core/collab.ts`). Read once per join, then packets.\n   */\n  readonly collab: CollabSnapshot;\n  /** The breakout room THIS participant is in, or null for the main room. */\n  readonly breakoutRoomId: string | null;\n}\n\nconst EMPTY: MeetSnapshot = {\n  phase: \"resolving\",\n  reason: null,\n  phaseNotice: null,\n  roomName: null,\n  connection: \"stable\",\n  connectionBanner: false,\n  localNetwork: UNKNOWN_LOCAL_NETWORK,\n  share: NO_SHARE,\n  call: null,\n  waiting: null,\n  meeting: null,\n  localIdentity: null,\n  secondDevice: null,\n  grants: NO_GRANTS,\n  participants: [],\n  activeSpeakers: [],\n  pinned: null,\n  layout: \"grid\",\n  lobby: [],\n  locked: false,\n  recording: \"idle\",\n  recordingStartedBy: null,\n  recordingSource: \"local\",\n  recordingId: null,\n  chat: [],\n  chatLoaded: false,\n  chatHistoryError: null,\n  reactions: [],\n  spotlight: null,\n  actingHost: null,\n  presenter: null,\n  waitingCount: 0,\n  leavePolicy: DEFAULT_LEAVE_POLICY,\n  livePolicy: DEFAULT_LIVE_POLICY,\n  canReclaim: false,\n  recordingConsentGiven: false,\n  sessionStartedAt: null,\n  mutedByHost: false,\n  moderationNotice: null,\n  actionNotice: null,\n  privateChatRequest: null,\n  effects: DEFAULT_EFFECTS,\n  transcript: [],\n  notes: [],\n  names: {},\n  wrapUp: null,\n  noteTakerRefusal: null,\n  captionsOn: false,\n  captionsRefusal: null,\n  captionsStartTimeoutSeconds: 20,\n  media: IDLE_MEDIA,\n  mediaRegion: IDLE_MEDIA_REGION,\n  failure: null,\n  collab: EMPTY_COLLAB,\n  breakoutRoomId: null,\n};\n\n/**\n * 🚨 THE ONE ANSWER TO \"WHAT ROLE DOES THIS CLIENT'S USER HOLD\" (MRI-A11).\n *\n * Two SERVER-minted carriers, one decision: the `/meet/token` response (in the\n * store from the moment the token lands, before any roster exists) and the\n * local participant's roster entry (whose role comes from the\n * `matrx.participant.role` LiveKit attribute). The stronger wins. Every host\n * power in this package — the UI that renders it AND the code that performs it\n * — asks THIS function, so a control can never render from one source and then\n * be refused by another. That split is exactly how a \"host control\" becomes a\n * button that throws.\n */\nexport function effectiveRole(snapshot: MeetSnapshot): ParticipantRole {\n  const me = snapshot.participants.find(\n    (participant) => participant.identity === snapshot.localIdentity,\n  );\n  const fromRoster = me?.role ?? \"participant\";\n  const fromToken = snapshot.grants.role;\n  return ROLE_RANK[fromRoster] >= ROLE_RANK[fromToken] ? fromRoster : fromToken;\n}\n\n/** This person's standing: the token's word, else what the roster carries for them. */\nexport function effectiveStanding(snapshot: MeetSnapshot): ParticipantStanding | null {\n  if (snapshot.grants.standing != null) return snapshot.grants.standing;\n  const me = snapshot.participants.find((p) => p.identity === snapshot.localIdentity);\n  return me?.standing ?? null;\n}\n\n/** Reactions live this long. A dropped end event cannot outlive it. */\nexport const REACTION_TTL_MS = 5_000;\n/** In-room chat is EPHEMERAL by design (R3) — this is the visible backlog. */\nconst CHAT_LIMIT = 200;\n\n/** What `patch` accepts: the snapshot minus the machine-owned fields. */\nexport type MeetPatch = Partial<Omit<MeetSnapshot, \"phase\" | \"reason\" | \"phaseNotice\">>;\n\nexport interface MeetStore {\n  snapshot(): MeetSnapshot;\n  subscribe(listener: () => void): () => void;\n  /** Everything EXCEPT the phase. The phase moves only through `dispatch`. */\n  patch(next: MeetPatch): void;\n  /**\n   * THE ONE WRITER OF THE PHASE (CORE-DESIGN §3.1). Applies `event` through the machine's table;\n   * returns false — and changes nothing — when the table does not allow it from the current\n   * phase. `reason` overrides the phase's own reason (an exit's `removed`, `displaced`, …).\n   */\n  dispatch(event: PhaseEvent, detail?: { readonly reason?: string | null; readonly notice?: string | null }): boolean;\n  setParticipants(participants: readonly MeetParticipant[]): void;\n  setSpeaking(identities: readonly ParticipantIdentity[]): void;\n  setQuality(identity: ParticipantIdentity, quality: ConnectionQuality): void;\n  addChat(message: RoomChatMessage): void;\n  /** The saved chat, read once per join. Merged with anything that arrived live. */\n  loadChat(messages: readonly RoomChatMessage[]): void;\n  /** Replace a pending message (by id) with what the server saved, or mark it failed. */\n  settleChat(localId: string, next: RoomChatMessage | { failed: string }): void;\n  addReaction(reaction: RoomReaction): void;\n  /** Drops reactions past their TTL. Called by the UI's animation frame. */\n  expireReactions(now: number): void;\n  /**\n   * The recording reached a state, and WHO says so. `\"local\"` is this browser's\n   * optimistic `starting`/`stopping`; `\"room\"` is the server's packet on the\n   * media plane; `\"record\"` is the durable row. Precedence is D16's: the\n   * database's word stands until the database changes it.\n   */\n  setRecording(\n    state: RecordingState,\n    by: UserId | null,\n    source: RecordingSource,\n    recordingId?: string | null,\n  ): void;\n  upsertLobby(entry: LobbyEntry): void;\n  setAdmission(identity: ParticipantIdentity, state: AdmissionState, by: UserId | null): void;\n  /**\n   * Teach the name book. Every source that knows a name calls this, and only\n   * a REAL name is learned — an identity handed back as its own name is not one.\n   */\n  learn(entries: readonly { identity: ParticipantIdentity; displayName?: string | null }[]): void;\n  /** A live caption from the media plane. A HINT (D16). */\n  ingestCaption(segment: TranscriptSegment): void;\n  /** A durable `meet_transcript_segments` row. THE TRANSCRIPT (D16). */\n  ingestRecord(segment: TranscriptSegment): void;\n  /** Durable notes are re-written in place — a re-run rewrites the same ids. */\n  upsertNote(note: MeetingNote): void;\n  /** The wrap-up pass finished. Announced on the media plane only (MRI-A12). */\n  announceWrapUp(announcement: WrapUpAnnouncement): void;\n  /** Record what a local track ACTUALLY did — published, or refused and why. */\n  setLocalTrack(kind: \"microphone\" | \"camera\", state: LocalTrackState): void;\n  reset(): void;\n}\n\nexport function createMeetStore(initial: Partial<MeetSnapshot> = {}): MeetStore {\n  let state: MeetSnapshot = { ...EMPTY, ...initial };\n  const listeners = new Set<() => void>();\n\n  function commit(next: MeetSnapshot): void {\n    if (next === state) return;\n    state = next;\n    for (const listener of listeners) listener();\n  }\n\n  return {\n    snapshot: () => state,\n    subscribe(listener) {\n      listeners.add(listener);\n      return () => listeners.delete(listener);\n    },\n    patch(next) {\n      if (\"phase\" in next || \"reason\" in next || \"phaseNotice\" in next) {\n        // The type forbids it; this catches a cast. The phase has ONE writer.\n        throw new TypeError(\"meet store: the phase moves only through store.dispatch(event)\");\n      }\n      commit({ ...state, ...next });\n    },\n    dispatch(event, detail) {\n      const to = nextPhase(state.phase, event);\n      if (to === null) return false;\n      const reason = detail?.reason !== undefined ? detail.reason : reasonOf(to);\n      const phaseNotice = detail?.notice ?? null;\n      if (to === state.phase && reason === state.reason && phaseNotice === state.phaseNotice) return true;\n      commit({ ...state, phase: to, reason, phaseNotice });\n      return true;\n    },\n    setParticipants(participants) {\n      // The roster TEACHES the book first — a participant whose token carried a\n      // real name is where most names come from — and every roster entry is then\n      // RESOLVED back through it, so a participant the roster cannot name still\n      // gets the best name a durable row or a caption ever taught (MRI-A18).\n      const names = learnNames(state.names, participants);\n      const quality = new Map(state.participants.map((p) => [p.identity, p.quality]));\n      commit({\n        ...state,\n        names,\n        participants: participants.map((participant) => ({\n          ...participant,\n          // 🚨 THE ONE ROSTER RESOLUTION. Every surface that renders a person —\n          // the tile, the People row, the header summary, every Pin/Mute label —\n          // reads `participant.displayName`, so this is the single place a raw\n          // identity could reach a screen, and it is the place that asks the\n          // name book. `roster-names.test.ts` fails if a token ever gets past it.\n          displayName: displayNameFor(names, participant.identity, participant.displayName),\n          quality:\n            participant.quality === \"unknown\"\n              ? quality.get(participant.identity) ?? \"unknown\"\n              : participant.quality,\n        })),\n      });\n    },\n    setSpeaking(identities) {\n      const speaking = new Set(identities);\n      commit({\n        ...state,\n        activeSpeakers: identities,\n        participants: state.participants.map((participant) =>\n          participant.speaking === speaking.has(participant.identity)\n            ? participant\n            : { ...participant, speaking: speaking.has(participant.identity) },\n        ),\n      });\n    },\n    setQuality(identity, quality) {\n      commit({\n        ...state,\n        participants: state.participants.map((participant) =>\n          participant.identity === identity ? { ...participant, quality } : participant,\n        ),\n      });\n    },\n    addChat(message) {\n      if (state.chat.some((existing) => existing.id === message.id)) return;\n      const chat = [...state.chat, message];\n      // A chat message carries its sender's name — another source, same book.\n      const names = learnName(state.names, message.identity, message.displayName);\n      commit({ ...state, chat: chat.slice(-CHAT_LIMIT), names });\n    },\n    loadChat(messages) {\n      const known = new Set(state.chat.map((message) => message.id));\n      const merged = [...messages.filter((message) => !known.has(message.id)), ...state.chat].sort(\n        (a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : 0),\n      );\n      const names = learnNames(\n        state.names,\n        messages.map((message) => ({ identity: message.identity, displayName: message.displayName })),\n      );\n      commit({ ...state, chat: merged.slice(-CHAT_LIMIT), chatLoaded: true, chatHistoryError: null, names });\n    },\n    settleChat(localId, next) {\n      const index = state.chat.findIndex((message) => message.id === localId);\n      if (index === -1) return;\n      const current = state.chat[index] as RoomChatMessage;\n      let replacement: RoomChatMessage;\n      if (\"failed\" in next && typeof next.failed === \"string\" && !(\"id\" in next)) {\n        replacement = { ...current, failed: next.failed };\n      } else {\n        replacement = next as RoomChatMessage;\n      }\n      // The saved copy may ALREADY be here (the room packet beat the response):\n      // then the pending one simply goes.\n      const duplicate =\n        replacement.id !== localId && state.chat.some((message) => message.id === replacement.id);\n      const chat = duplicate\n        ? state.chat.filter((message) => message.id !== localId)\n        : state.chat.map((message, position) => (position === index ? replacement : message));\n      commit({ ...state, chat });\n    },\n    addReaction(reaction) {\n      commit({ ...state, reactions: [...state.reactions, reaction] });\n    },\n    expireReactions(now) {\n      const live = state.reactions.filter((reaction) => now - reaction.at < REACTION_TTL_MS);\n      if (live.length === state.reactions.length) return;\n      commit({ ...state, reactions: live });\n    },\n    setRecording(next, by, source, recordingId = null) {\n      // 🚨 THE DATABASE WINS (D16). A member receives every transition TWICE —\n      // the `meet_recordings` row over Postgres Changes and the\n      // room's replicated state — and whichever is slower\n      // must not be able to drag the indicator backwards.\n      //\n      // The rule is about ONE recording, not about the meeting: a meeting can\n      // be recorded again, and the second recording's first word is not a\n      // contradiction of the first one's ending. So the durable state stands\n      // against anything that is about the SAME recording, and against a\n      // sourceless update while a recording is still in flight.\n      // `record` always wins. The other two are refused when they would\n      // contradict the durable word rather than continue past it:\n      //\n      // * `local` is this browser acting NOW — a host pressing Start again on a\n      //   meeting whose last recording is over. It is refused only while a\n      //   recording is genuinely in flight, where a stale optimistic patch\n      //   could drag a live indicator backwards.\n      // * `room` carries the recording's id, so a LATE packet about the\n      //   recording that just finished is told apart from the FIRST packet of\n      //   the next one. Same recording: refused. Different recording: refused\n      //   only while the durable one is still in flight.\n      if (state.recordingSource === \"record\" && source !== \"record\") {\n        const aboutTheSameRecording =\n          source === \"room\" &&\n          (recordingId === null ||\n            state.recordingId === null ||\n            recordingId === state.recordingId);\n        if (aboutTheSameRecording || isRecordingInFlight(state.recording)) return;\n      }\n      if (\n        state.recording === next &&\n        state.recordingStartedBy === by &&\n        state.recordingSource === source &&\n        state.recordingId === (recordingId ?? state.recordingId)\n      ) {\n        // Identity-stable: an unchanged state must not wake every subscriber.\n        return;\n      }\n      commit({\n        ...state,\n        recording: next,\n        recordingStartedBy: by,\n        recordingSource: source,\n        recordingId: recordingId ?? state.recordingId,\n      });\n    },\n    upsertLobby(entry) {\n      const index = state.lobby.findIndex((existing) => existing.identity === entry.identity);\n      const lobby =\n        index === -1\n          ? [...state.lobby, entry]\n          : state.lobby.map((existing, position) => (position === index ? entry : existing));\n      commit({ ...state, lobby });\n    },\n    setAdmission(identity, admissionState, by) {\n      commit({\n        ...state,\n        lobby: state.lobby.map((entry) =>\n          entry.identity === identity\n            ? {\n                ...entry,\n                state: admissionState,\n                decidedAt: new Date().toISOString(),\n                decidedBy: by,\n              }\n            : entry,\n        ),\n      });\n    },\n    learn(entries) {\n      const names = learnNames(state.names, entries);\n      // Identity-stable: learning nothing must not wake every subscriber, and\n      // this is called on every roster event and every durable row.\n      if (names === state.names) return;\n      commit({ ...state, names });\n    },\n    ingestCaption(segment) {\n      // A caption's roster lookup is a source of names like any other.\n      const names = learnName(state.names, segment.identity, segment.speaker);\n      const transcript = mergeCaption(state.transcript, segment);\n      if (transcript === state.transcript && names === state.names) return;\n      commit({ ...state, transcript, names });\n    },\n    ingestRecord(segment) {\n      // 🚨 THE DURABLE ROW'S `speaker` IS THE BEST NAME THERE IS: the note-taker\n      // wrote it from `meet_participants`, which is where \"Ada Lovelace\" lived\n      // while the guest's screen was printing `guest:c8-spk-1`.\n      const names = learnName(state.names, segment.identity, segment.speaker);\n      const transcript = mergeRecord(state.transcript, segment);\n      if (transcript === state.transcript && names === state.names) return;\n      commit({ ...state, transcript, names });\n    },\n    upsertNote(note) {\n      const index = state.notes.findIndex((existing) => existing.id === note.id);\n      if (index === -1) {\n        commit({ ...state, notes: [...state.notes, note] });\n        return;\n      }\n      const existing = state.notes[index];\n      // Identity-stable: an unchanged note must not wake `useSyncExternalStore`.\n      // 🚨 `source` is part of \"unchanged\" and that is load-bearing, not\n      // cosmetic: when the room copy and the database copy carry the same words,\n      // dropping the second arrival would leave the note marked `\"room\"` forever\n      // — and the precedence rule below would then let a LATER stale packet\n      // overwrite a row the database had already confirmed.\n      if (\n        existing !== undefined &&\n        existing.text === note.text &&\n        existing.kind === note.kind &&\n        existing.supersededBy === note.supersededBy &&\n        existing.source === note.source\n      ) {\n        return;\n      }\n      // 🚨 THE DATABASE WINS (D16, MRI-A12). The identical row arrives on two\n      // transports — a `meet_notes` row over Postgres Changes and a\n      // `matrx.meet.note` packet on the media plane — and whichever is slower\n      // must not be able to undo the other. A `\"room\"` copy never overwrites a\n      // `\"record\"` one; a `\"record\"` copy always overwrites a `\"room\"` one.\n      // Without this, a re-run that rewrote a note could flip a member's screen\n      // back to the superseded wording purely on arrival order.\n      if (existing !== undefined && existing.source === \"record\" && note.source === \"room\") {\n        return;\n      }\n      commit({\n        ...state,\n        notes: state.notes.map((entry, position) => (position === index ? note : entry)),\n      });\n    },\n    announceWrapUp(announcement) {\n      const current = state.wrapUp;\n      if (current !== null && current.at === announcement.at) return;\n      commit({ ...state, wrapUp: announcement });\n    },\n    setLocalTrack(kind, next) {\n      const current = state.media[kind];\n      // Identity-stable: an unchanged track must not wake `useSyncExternalStore`.\n      if (\n        current.enabled === next.enabled &&\n        current.unavailable?.code === next.unavailable?.code &&\n        current.unavailable?.reason === next.unavailable?.reason &&\n        current.unavailable?.message === next.unavailable?.message\n      ) {\n        return;\n      }\n      commit({\n        ...state,\n        media: { ...state.media, [kind]: next },\n        // The person turned their own microphone on again: the host's mute is over.\n        ...(kind === \"microphone\" && next.enabled && state.mutedByHost ? { mutedByHost: false } : {}),\n      });\n    },\n    reset() {\n      // The phase goes back through THE MACHINE like every other move (`teardown`: the engine has\n      // already closed its connection); everything else returns to empty. A person's own media\n      // choices outlive a room: they are theirs, per browser.\n      const phase = nextPhase(state.phase, { type: \"reset\", teardown: true }) ?? EMPTY.phase;\n      commit({ ...EMPTY, effects: state.effects, phase, reason: reasonOf(phase), phaseNotice: null });\n    },\n  };\n}\n","/**\n * MEETINGS — the lobby, the host powers, and the durable link.\n *\n * A meeting is a room plus scheduling, lobby and host metadata (D3). Everything\n * here is about the moments OUTSIDE the media session, which is exactly why it\n * cannot ride LiveKit's data plane: a guest waiting in the lobby is not in the\n * LiveKit room yet, by construction. The lobby therefore lives on the meet-room\n * realtime channel.\n *\n * 🚨 THE THREE THINGS THAT MAKE GUEST JOIN SAFE (D6)\n *\n * 1. **The link is an identity, not a session.** A durable slug resolves before,\n *    during, and after the scheduled time, and a recurring meeting keeps ONE\n *    link. Nothing here mints a per-occurrence URL.\n * 2. **A guest's capability is the TOKEN, and nothing else.** They are scoped to\n *    exactly one room. There is no guest row this client writes that could grant\n *    anything, and no client-side \"is this person allowed\" branch.\n * 3. **Admission is a SERVER decision, recorded.** `admit` is an RPC; the\n *    broadcast that tells the knocker is a NOTIFICATION of that decision, never\n *    the decision itself. Two hosts clicking admit is the ordinary case, and the\n *    RPC is what makes it idempotent.\n *\n * Host powers are checked against the role the SERVER minted into the token\n * (see `room.ts`), and the UI hides what an actor cannot do rather than\n * rendering a dead button (no dead ends).\n */\n\nimport { isWaitingPhase, type ExitServerWord } from \"./phase\";\nimport type { ChannelHandle, RealtimeManager } from \"@ai-matrx/data/realtime\";\nimport { MEET_EVENTS, meetingTopic, roomTopic } from \"./channels\";\nimport type { MeetWaiting } from \"./store\";\nimport type { MeetApi } from \"./api\";\nimport { MeetError } from \"./errors\";\nimport { readRefusalBody } from \"./ai\";\nimport type { MeetRepository } from \"./repository\";\nimport { effectiveRole, type MeetStore } from \"./store\";\nimport { MEET_ROUTES, MEETING_PASS_HEADER } from \"./tokens\";\nimport { livePolicyFrom, mayAdmitNow, samePolicy } from \"./live-policy\";\nimport {\n  asParticipantIdentity,\n  isHostRole,\n  isGuest,\n  WAITING_ADMISSION_STATES,\n  type AdmissionState,\n  ROLE_RANK,\n  type LobbyEntry,\n  type MeetIdentity,\n  type MeetParticipant,\n  type MeetingAttendee,\n  type MeetingId,\n  type MeetingRecord,\n  type ParticipantIdentity,\n  type ParticipantRole,\n  type RecordingState,\n  type RoomName,\n  type UserId,\n} from \"./types\";\n\nexport interface MeetingSessionOptions {\n  manager: RealtimeManager;\n  repository: MeetRepository;\n  store: MeetStore;\n  identity: MeetIdentity;\n  /**\n   * The ONE org-aware aidream client (MRI-A16) — `endForEveryone` is a SERVER\n   * decision (MRI-A6), and every request it makes carries the organization.\n   */\n  api: MeetApi;\n  onDiagnostic?: ((event: { level: \"info\" | \"warn\" | \"error\"; message: string; remedy?: string }) => void) | undefined;\n  /**\n   * 🚨 THE HOST ADMITTED *US*. Called exactly once per admission verdict that\n   * names this participant, and only for `admitted`.\n   *\n   * Admission is not a UI state change: a lobby token is minted with\n   * `canPublish: false` and `canSubscribe: false`, so the waiting room can only\n   * become a room by minting a NEW token. Before this existed the waiting room\n   * said \"you will join automatically once you are admitted\" and then waited\n   * forever — a sentence on screen that was not true. The provider wires this\n   * to `engine.rejoin()`.\n   */\n  onAdmitted?: (() => void) | undefined;\n  /**\n   * S4: the meeting pass this device holds (`x-meet-pass`) — what the state read and\n   * `/leave` are authorized by. Null when no pass is held yet.\n   */\n  resolvePass?: (() => string | null) | undefined;\n  /** S4: mint again (Ask to join again / Rejoin from the waiting screens). */\n  rejoin?: (() => Promise<void>) | undefined;\n}\n\nexport interface MeetingSession {\n  /** Subscribe to the room's out-of-band plane. Hosts see knocks; guests see verdicts. */\n  watch(roomName: RoomName): void;\n  /**\n   * Subscribe to the MEETING RECORD's durable feed — transcript segments, notes,\n   * and the meeting row itself (which is where the note-taker's state lives).\n   * Reconnecting IS re-reading: the backfill door re-reads all three, because\n   * realtime has no replay and a socket blip would otherwise leave a transcript\n   * permanently missing the minute nobody noticed.\n   */\n  watchMeeting(meetingId: MeetingId): void;\n  admit(entry: LobbyEntry, admitted: boolean): Promise<void>;\n  /** S4: lift a denial so the person may knock again (`meet_undeny`). */\n  undeny(entry: LobbyEntry): Promise<void>;\n  admitAll(): Promise<void>;\n  /**\n   * 🚨 S4 — THE WAIT READS SERVER TRUTH (CORE-DESIGN §2.6). While this tab waits, the state\n   * read (`GET /v1/meet/state`) runs every `waiting_poll_seconds`, on every\n   * `mx.state.changed` hint, on `online` and on visibility return. Admitted → a fresh mint\n   * (`rejoin`); denied / expired / ended are what the row says, never a broadcast's guess.\n   */\n  startWaiting(): void;\n  stopWaiting(): void;\n  /** One state read now (idempotent while one is in flight). */\n  readState(): Promise<void>;\n  /** One read of the meeting's rules now (chat mode, attendee lock, time limit); resolves once they are on the store. */\n  readLivePolicy(): Promise<void>;\n  /** rec-consent-gate: tell the SERVER this person agreed to being recorded (a row fact; it gives publish back). */\n  acknowledgeConsent(): Promise<void>;\n  /**\n   * §3.4 ER: what the server recorded for THIS connection's exit, and the run's phase. null =\n   * the read failed (offline / unreachable); undefined = no meeting or no pass to ask with.\n   */\n  readExit(connection: string, pass?: string | null): Promise<ExitServerWord | null | undefined>;\n  /** Stop waiting: the row becomes `withdrawn` (`POST /v1/meet/leave {intent: \"withdraw\"}`). */\n  withdraw(): Promise<void>;\n  /** Ask again after a denial or an expired knock (only offered when allowed). */\n  askAgain(): Promise<void>;\n  /**\n   * S8: the HOST's leave intents through `POST /v1/meet/leave` — end the meeting for everyone,\n   * or hand the run's host powers to `assignTo` (a person key) before leaving. The server\n   * decides from the pass whether this person holds the run's host powers.\n   */\n  hostLeave(intent: \"end_for_all\" | { readonly assignTo: string }): Promise<void>;\n  setLock(locked: boolean): Promise<MeetingRecord>;\n  /** `wr-policy-who-waits`: one rule of the meeting on screen (null when unreadable). */\n  meetingRule(key: string): Promise<unknown>;\n  /** A host changes one rule for this meeting; waiting people are told to read again. */\n  setMeetingRule(key: string, value: string | number | boolean): Promise<unknown>;\n  /** End it for everyone, through the server (MRI-A6). */\n  endForEveryone(): Promise<EndMeetingResult>;\n  dispose(): void;\n}\n\n/** Can `actor` moderate `target`? A host outranks a co-host outranks everyone. */\nexport function canModerateParticipant(\n  actor: MeetParticipant | undefined,\n  target: MeetParticipant | undefined,\n): boolean {\n  if (actor === undefined || target === undefined) return false;\n  if (actor.role === \"participant\") return false;\n  if (actor.identity === target.identity) return false;\n  // A co-host cannot remove the host. Without this rank check, \"host controls\"\n  // is a mutual-eviction button.\n  return ROLE_RANK[actor.role] > ROLE_RANK[target.role];\n}\n\nexport function roleOf(\n  participants: readonly MeetParticipant[],\n  identity: ParticipantIdentity | null,\n): ParticipantRole {\n  if (identity === null) return \"participant\";\n  return participants.find((p) => p.identity === identity)?.role ?? \"participant\";\n}\n\n/**\n * What ending a meeting produced. `served: false` is the honest answer from a\n * server that has not landed `POST /v1/meet/end` yet (MRI-A6) — the control is\n * real, the refusal is a sentence, and nothing pretends the meeting ended.\n */\nexport interface EndMeetingResult {\n  readonly endedAt: string | null;\n  readonly served: boolean;\n}\n\n/** The sentence a server without MRI-A6 earns. Pinned so every surface says it. */\nexport const END_MEETING_NOT_SERVED =\n  \"Ending a meeting is not available on this server yet\";\n\n/**\n * One durable `meet_participants` row as a lobby entry, or `null` when it is\n * not one. A row that has been decided is not a knocker; the panel shows people\n * who are WAITING, and `store.upsertLobby` keyed by identity is what lets the\n * table and the broadcast be two copies of one person rather than two rows.\n */\nfunction lobbyEntryFrom(attendee: MeetingAttendee, now: number = Date.now()): LobbyEntry | null {\n  if (!WAITING_ADMISSION_STATES.includes(attendee.admissionState)) return null;\n  // A knock past its expiry IS expired (the server CASes it on the knocker's next read).\n  const expires = attendee.knockExpiresAt ? Date.parse(attendee.knockExpiresAt) : Number.NaN;\n  if (!Number.isNaN(expires) && expires <= now) return null;\n  return {\n    identity: attendee.identity,\n    displayName: attendee.displayName,\n    avatarUrl: attendee.avatarUrl,\n    userId: attendee.userId,\n    state: \"knocking\",\n    knockedAt: attendee.knockedAt ?? attendee.joinedAt ?? new Date().toISOString(),\n    knockExpiresAt: attendee.knockExpiresAt ?? null,\n    decidedAt: null,\n    decidedBy: null,\n    flag: attendee.knockFlag ?? null,\n  };\n}\n\n/**\n * A DENIED row as a lobby entry, so the host can lift the denial (`meet_undeny`) — the only door\n * that lets a refused person knock again under the `until_lifted` rule. Null for every other row.\n */\nfunction deniedEntryFrom(attendee: MeetingAttendee): LobbyEntry | null {\n  if (attendee.admissionState !== \"denied\") return null;\n  return {\n    identity: attendee.identity,\n    displayName: attendee.displayName,\n    avatarUrl: attendee.avatarUrl,\n    userId: attendee.userId,\n    state: \"denied\",\n    knockedAt: attendee.knockedAt ?? attendee.joinedAt ?? new Date().toISOString(),\n    knockExpiresAt: null,\n    decidedAt: null,\n    decidedBy: null,\n  };\n}\n\n/** One row → the door's list: a knocker waits, a denied person can be let back in; the rest clear. */\nfunction applyDoorRow(store: MeetStore, attendee: MeetingAttendee): void {\n  const entry = lobbyEntryFrom(attendee) ?? deniedEntryFrom(attendee);\n  if (entry !== null) {\n    store.upsertLobby(entry);\n    return;\n  }\n  // 🚨 A DECIDED ROW MUST CLEAR THE DOOR. Admitting a guest from another tab writes `admitted`\n  // here, and ignoring the row would leave this host's panel offering to admit somebody who is\n  // already in the meeting — a ghost knocker who can never be dismissed.\n  store.setAdmission(attendee.identity, decidedState(attendee.admissionState), null);\n}\n\n/** The row's word for a person no longer waiting, as the host's lobby list records it. */\nfunction decidedState(state: AdmissionState): AdmissionState {\n  return WAITING_ADMISSION_STATES.includes(state) ? \"expired\" : state;\n}\n\n/** The server's state read, as this package reads it. */\ninterface StateRead {\n  readonly admission_state?: string | null;\n  readonly admitters_present?: boolean;\n  readonly reknock_allowed?: boolean;\n  readonly reknock_in_seconds?: number | null;\n  readonly knock_expires_at?: string | null;\n  readonly session_phase?: string;\n  readonly meeting_phase?: string;\n  readonly live_version?: number;\n  readonly poll_seconds?: number;\n  readonly exit_reason?: string | null;\n  readonly live_policy?: Record<string, unknown>;\n  readonly consent_given?: boolean;\n  readonly session_started_at?: string | null;\n}\n\n/** How often a person in the call re-reads the meeting's rules. */\nexport const LIVE_POLICY_POLL_MS = 3000;\n\nexport function createMeetingSession(options: MeetingSessionOptions): MeetingSession {\n  const { manager, repository, store, identity } = options;\n  let channel: ChannelHandle | null = null;\n  let meetingChannel: ChannelHandle | null = null;\n\n  /**\n   * The meeting row, for anyone who may be in it. A member or a person the\n   * meeting was shared with reads it under RLS; a signed-in person from ANOTHER\n   * organization who followed the link cannot, and gets the same row through\n   * the link door (`meet_meeting_by_slug`) a guest uses — the server lets them\n   * in by the link, so the screen must not fail them for holding it.\n   */\n  async function readMeeting(meetingId: MeetingId): Promise<MeetingRecord> {\n    try {\n      return await repository.meeting(meetingId);\n    } catch (error) {\n      const slug = store.snapshot().meeting?.slug;\n      if (slug === undefined) throw error;\n      return repository.meetingBySlug(slug);\n    }\n  }\n\n  function requireHostUser(operation: string): UserId {\n    // THE SAME PREDICATE THE UI RENDERS FROM (MRI-A11). Reading only the roster\n    // here — while the control renders from the token grant — is how a host\n    // control becomes a button that throws the moment it is used.\n    if (identity.userId === null || !isHostRole(effectiveRole(store.snapshot()))) {\n      throw new MeetError(\n        \"forbidden\",\n        `${operation}: this participant is not a host`,\n        \"Host powers come from the server-minted token metadata and are enforced by the RPC. \" +\n          \"Hide the control rather than rendering a button that will be refused.\",\n      );\n    }\n    return identity.userId;\n  }\n\n  /**\n   * The door's own rule, mirrored (`communication._meet_may_admit`): a host or co-host, or — when no\n   * host or co-host is in the room — a signed-in member, as far as the meeting's `headless_powers`\n   * lets (meeting-without-host). The RPC enforces it; this only keeps a refused button from throwing.\n   */\n  function requireAdmitterUser(operation: string): UserId {\n    const snapshot = store.snapshot();\n    if (identity.userId === null || !mayAdmitNow(effectiveRole(snapshot), snapshot.participants, snapshot.livePolicy)) {\n      throw new MeetError(\n        \"forbidden\",\n        `${operation}: this participant may not let people in`,\n        \"Only a host or co-host admits people, unless the meeting has no host in it and lets members admit.\",\n      );\n    }\n    return identity.userId;\n  }\n\n  function requireMeeting(operation: string): MeetingRecord {\n    const meeting = store.snapshot().meeting;\n    if (meeting === null) {\n      throw new MeetError(\n        \"misconfigured\",\n        `${operation}: no meeting is loaded`,\n        \"Ad-hoc call rooms have no meeting record and therefore no lobby or lock. Use \" +\n          \"joinMeeting()/scheduleMeeting() when you need those powers.\",\n      );\n    }\n    return meeting;\n  }\n\n  // ── S4: the waiting supervisor ─────────────────────────────────────────\n  let polling = false;\n  let pollTimer: ReturnType<typeof setTimeout> | null = null;\n  let reading: Promise<void> | null = null;\n  let admittedOnce = false;\n  let unlisten: (() => void) | null = null;\n\n  function report(level: \"info\" | \"warn\" | \"error\", message: string, remedy?: string): void {\n    options.onDiagnostic?.(remedy === undefined ? { level, message } : { level, message, remedy });\n  }\n\n  function pollMs(): number {\n    const seconds = store.snapshot().waiting?.pollSeconds ?? 3;\n    return Math.max(1, Math.min(60, seconds)) * 1000;\n  }\n\n  function schedule(ms: number): void {\n    if (pollTimer !== null) clearTimeout(pollTimer);\n    if (!polling) return;\n    pollTimer = setTimeout(() => {\n      pollTimer = null;\n      void readState().finally(() => schedule(pollMs()));\n    }, ms);\n  }\n\n  function listen(): void {\n    if (unlisten !== null || typeof window === \"undefined\") return;\n    const nudge = (): void => {\n      if (typeof document !== \"undefined\" && document.visibilityState === \"hidden\") return;\n      void readState();\n    };\n    // Closing the tab while waiting withdraws the knock (beacon: no headers, pass in the body).\n    const goodbye = (): void => {\n      const meeting = store.snapshot().meeting;\n      const pass = options.resolvePass?.() ?? null;\n      const waiting = store.snapshot().waiting;\n      if (meeting === null || pass === null || waiting === null) return;\n      if (!WAITING_ADMISSION_STATES.includes(waiting.admission)) return;\n      try {\n        navigator.sendBeacon?.(\n          options.api.url(MEET_ROUTES.leave),\n          new Blob([JSON.stringify({ meeting_id: meeting.id, intent: \"withdraw\", meeting_pass: pass })], {\n            type: \"application/json\",\n          }),\n        );\n      } catch {\n        // Best effort: an unanswered knock still lapses on its own (knock_timeout_minutes).\n      }\n    };\n    window.addEventListener(\"online\", nudge);\n    window.addEventListener(\"pagehide\", goodbye);\n    document.addEventListener(\"visibilitychange\", nudge);\n    unlisten = () => {\n      window.removeEventListener(\"online\", nudge);\n      window.removeEventListener(\"pagehide\", goodbye);\n      document.removeEventListener(\"visibilitychange\", nudge);\n    };\n  }\n\n  function stopWaiting(): void {\n    polling = false;\n    if (pollTimer !== null) clearTimeout(pollTimer);\n    pollTimer = null;\n    unlisten?.();\n    unlisten = null;\n  }\n\n  function patchWaiting(next: Partial<MeetWaiting>): void {\n    const current = store.snapshot().waiting;\n    const base: MeetWaiting = current ?? {\n      admission: \"knocking\",\n      admittersPresent: null,\n      reknockAllowed: true,\n      knockExpiresAt: null,\n      pollSeconds: 3,\n      liveVersion: 0,\n    };\n    store.patch({ waiting: { ...base, ...next } });\n  }\n\n  function apply(read: StateRead): void {\n    const snapshot = store.snapshot();\n    if (!isWaitingPhase(snapshot.phase)) return;\n    const admission = (read.admission_state ?? null) as AdmissionState | null;\n    const ended =\n      admission === \"ended\" || read.session_phase === \"ended\" || read.meeting_phase === \"ended\";\n    if (admission === \"admitted\" && !ended) {\n      if (admittedOnce) return;\n      admittedOnce = true;\n      stopWaiting();\n      // ADMISSION IS A JOIN: a fresh mint with the grants the server now gives.\n      options.onAdmitted?.();\n      return;\n    }\n    if (ended) {\n      stopWaiting();\n      patchWaiting({ admission: \"ended\" });\n      const meeting = snapshot.meeting;\n      if (read.meeting_phase === \"ended\" && meeting !== null && meeting.endedAt === null) {\n        store.patch({ meeting: { ...meeting, endedAt: new Date().toISOString() } });\n      }\n      store.dispatch({ type: \"admission\", admission: \"ended\" }, { reason: \"ended\" });\n      return;\n    }\n    if (admission === null) return;\n    patchWaiting({\n      admission,\n      admittersPresent: read.admitters_present ?? null,\n      reknockAllowed: read.reknock_allowed ?? true,\n      reknockAt: typeof read.reknock_in_seconds === \"number\" && read.reknock_in_seconds > 0 ? Date.now() + read.reknock_in_seconds * 1000 : null,\n      knockExpiresAt: read.knock_expires_at ?? null,\n      pollSeconds: read.poll_seconds ?? snapshot.waiting?.pollSeconds ?? 3,\n      liveVersion: read.live_version ?? 0,\n    });\n    // THE SERVER'S WORD MOVES THE PHASE (§3.1): one machine event, never a patch.\n    store.dispatch({ type: \"admission\", admission });\n    // A decision that is not \"yes\" ends the wait; the screen offers what the rules allow.\n    if (admission === \"denied\" || admission === \"expired\" || admission === \"withdrawn\" || admission === \"removed\") {\n      stopWaiting();\n    }\n  }\n\n  // ── P1: the rules, live, while in the call ─────────────────────────────\n  let policyTimer: ReturnType<typeof setInterval> | null = null;\n  let policyReading = false;\n  let policyInFlight: Promise<void> | null = null;\n\n  async function readLivePolicy(): Promise<void> {\n    const meeting = store.snapshot().meeting;\n    const pass = options.resolvePass?.() ?? null;\n    if (meeting === null || pass === null) return;\n    // A read already in flight may have been asked BEFORE the host changed a rule (it was sent,\n    // then the rule moved, then its answer landed): the caller needs a read that starts now, so\n    // wait for that one and then run a fresh one.\n    if (policyReading) {\n      await (policyInFlight ?? undefined);\n      return readLivePolicy();\n    }\n    policyReading = true;\n    let done: () => void = () => undefined;\n    policyInFlight = new Promise<void>((resolve) => (done = resolve));\n    try {\n      const response = await options.api.request({\n        path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,\n        method: \"GET\",\n        requireAuth: false,\n        operation: \"meet.state(policy)\",\n        headers: { [MEETING_PASS_HEADER]: pass },\n      });\n      if (!response.ok) return;\n      const read = (await response.json()) as StateRead;\n      const next = livePolicyFrom(read.live_policy);\n      const started = read.session_started_at ? Date.parse(read.session_started_at) : NaN;\n      const snapshot = store.snapshot();\n      const startedAt = Number.isFinite(started) ? started : snapshot.sessionStartedAt;\n      if (!samePolicy(snapshot.livePolicy, next) || startedAt !== snapshot.sessionStartedAt) {\n        store.patch({ livePolicy: next, sessionStartedAt: startedAt });\n      }\n      // The server's row is the consent, not this screen's memory (reload, second tab, rejoin).\n      if (read.consent_given === true && !store.snapshot().recordingConsentGiven) {\n        store.patch({ recordingConsentGiven: true });\n      }\n    } catch {\n      // Offline: the next tick asks again; the rules on screen stay as they were.\n    } finally {\n      policyReading = false;\n      policyInFlight = null;\n      done();\n    }\n  }\n\n  function syncLivePolicyTimer(): void {\n    const inCall = store.snapshot().phase === \"in_call\";\n    if (inCall && policyTimer === null) {\n      void readLivePolicy();\n      policyTimer = setInterval(() => void readLivePolicy(), LIVE_POLICY_POLL_MS);\n    } else if (!inCall && policyTimer !== null) {\n      clearInterval(policyTimer);\n      policyTimer = null;\n    }\n  }\n  const unsubscribePolicy = store.subscribe(syncLivePolicyTimer);\n\n  async function readState(): Promise<void> {\n    if (reading !== null) return reading;\n    const meeting = store.snapshot().meeting;\n    const pass = options.resolvePass?.() ?? null;\n    if (meeting === null || pass === null) return;\n    reading = (async () => {\n      try {\n        const response = await options.api.request({\n          path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,\n          method: \"GET\",\n          requireAuth: false,\n          operation: \"meet.state\",\n          headers: { [MEETING_PASS_HEADER]: pass },\n        });\n        if (!response.ok) {\n          let body: unknown = null;\n          try {\n            body = await response.json();\n          } catch {\n            body = null;\n          }\n          const refusal = readRefusalBody(body);\n          report(\n            \"warn\",\n            refusal?.reason ?? `meet.state: the server answered ${response.status}`,\n            refusal?.remedy ?? \"The waiting room keeps asking; nothing on this screen changes until the server answers.\",\n          );\n          return;\n        }\n        apply((await response.json()) as StateRead);\n      } catch (error) {\n        // Offline or the server is unreachable: the next tick (or `online`) asks again.\n        report(\"info\", `meet.state: ${String(error)}`, \"Waiting continues; the state is read again shortly.\");\n      } finally {\n        reading = null;\n      }\n    })();\n    return reading;\n  }\n\n  async function postLeave(\n    intent: \"withdraw\" | \"leave\" | \"end_for_all\" | \"assign_and_leave\",\n    extra: Record<string, unknown> = {},\n  ): Promise<void> {\n    const meeting = requireMeeting(`meet.${intent}`);\n    const pass = options.resolvePass?.() ?? null;\n    const response = await options.api.request({\n      path: MEET_ROUTES.leave,\n      method: \"POST\",\n      requireAuth: false,\n      operation: `meet.${intent}`,\n      body: { meeting_id: meeting.id, intent, ...extra },\n      ...(pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}),\n    });\n    if (!response.ok) {\n      let body: unknown = null;\n      try {\n        body = await response.json();\n      } catch {\n        body = null;\n      }\n      const refusal = readRefusalBody(body);\n      throw new MeetError(\n        \"transport\",\n        refusal?.reason ?? `meet.${intent}: the server answered ${response.status}`,\n        refusal?.remedy ??\n          (intent === \"withdraw\" ? \"You are still in the waiting room. Try again.\" : \"Nothing was changed. Try again.\"),\n      );\n    }\n  }\n\n  /** After a member-client admission write the CLIENT sends the hint (CORE-DESIGN §2.4). */\n  function hint(): void {\n    channel?.send(MEET_EVENTS.stateChanged, { v: null });\n  }\n\n  /**\n   * After a member-client admission DOOR the SERVER republishes the room's replicated state\n   * (the waiting count everyone's People badge shows) — only the server writes room state\n   * (CORE-DESIGN §2.4, §2.6 RS). Truth first, then the hint. A failed tell is reported, never\n   * thrown: the decision stands, and the count catches up on the next server write.\n   */\n  async function tellServerAdmissionChanged(operation: string): Promise<void> {\n    const meeting = store.snapshot().meeting;\n    if (meeting === null) return;\n    const pass = options.resolvePass?.() ?? null;\n    try {\n      const response = await options.api.request({\n        path: MEET_ROUTES.admissionChanged,\n        method: \"POST\",\n        requireAuth: false,\n        operation,\n        body: { meeting_id: meeting.id },\n        ...(pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}),\n      });\n      if (!response.ok) {\n        report(\n          \"warn\",\n          `${operation}: the server answered ${response.status} when told about the admission change`,\n          \"The decision was saved. The waiting count in the room may lag until the next change.\",\n        );\n      }\n    } catch (error) {\n      report(\n        \"warn\",\n        `${operation}: ${String(error)}`,\n        \"The decision was saved. The waiting count in the room may lag until the next change.\",\n      );\n    }\n  }\n\n  /** The host's second carrier: on a hint, re-read who is at the door. */\n  async function refreshQueue(): Promise<void> {\n    const meeting = store.snapshot().meeting;\n    if (meeting === null || isGuest(identity) || !isHostRole(effectiveRole(store.snapshot()))) return;\n    try {\n      const attendees = await repository.attendees(meeting.id);\n      store.learn(attendees);\n      for (const attendee of attendees) applyDoorRow(store, attendee);\n    } catch {\n      // Postgres Changes on the same rows is the other carrier; a miss here costs nothing.\n    }\n  }\n\n  return {\n    watch(roomName) {\n      channel?.close();\n      channel = manager.open({\n        topic: roomTopic(roomName),\n        broadcast: [\n          {\n            // 🚨 PAYLOAD-FREE. Every receiver reads again; a spoofed hint only causes a read.\n            event: MEET_EVENTS.stateChanged,\n            onMessage: () => {\n              if (isWaitingPhase(store.snapshot().phase)) void readState();\n              void refreshQueue();\n            },\n          },\n        ],\n        // THE BACKFILL DOOR. A socket blip must not lose a decision: re-read the meeting\n        // row, and a waiting tab re-reads its own state.\n        onBackfill: async () => {\n          const meeting = store.snapshot().meeting;\n          if (meeting === null) return;\n          const fresh = isGuest(identity)\n            ? await repository.meetingBySlug(meeting.slug)\n            : await readMeeting(meeting.id);\n          store.patch({ meeting: fresh, locked: fresh.locked });\n          if (isWaitingPhase(store.snapshot().phase)) void readState();\n        },\n      });\n    },\n\n    watchMeeting(meetingId) {\n      meetingChannel?.close();\n      meetingChannel = null;\n      if (isGuest(identity)) {\n        options.onDiagnostic?.({\n          level: \"info\",\n          message: \"Guest notes and captions arrive through the live meeting room; saved history is not available without a session.\",\n          remedy: \"Sign in with access to this meeting to reload saved notes and transcript history.\",\n        });\n        return;\n      }\n      meetingChannel = manager.open({\n        topic: meetingTopic(meetingId),\n        postgresChanges: [\n          {\n            event: \"*\",\n            schema: repository.schema,\n            table: repository.tables.transcripts,\n            filter: `meeting_id=eq.${meetingId}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: ({ row }) => {\n              // D16: THE ROW IS THE TRANSCRIPT. It replaces the caption that\n              // showed the same words a moment earlier.\n              if (row !== null) store.ingestRecord(repository.projectSegment(row));\n            },\n          },\n          {\n            event: \"*\",\n            schema: repository.schema,\n            table: repository.tables.notes,\n            filter: `meeting_id=eq.${meetingId}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: ({ row }) => {\n              // Upsert, not append: a re-run of the wrap-up rewrites the SAME\n              // row ids by design, and appending would show every note twice.\n              if (row !== null) store.upsertNote(repository.projectNote(row));\n            },\n          },\n          {\n            // 🚨 THE LOBBY IS A TABLE, NOT ONLY A CHANNEL (MRI-A16). A guest\n            // knocks by writing `admission_state='knocking'` AND broadcasting;\n            // through 0.4.7 the host's People panel rendered only the broadcast,\n            // so a knocker whose packet landed before this browser opened the\n            // channel — a host who joined second, reloaded, or slept a laptop —\n            // was INVISIBLE while the guest sat in the waiting room forever. A\n            // host can read this table; a guest cannot, and gets no lobby list\n            // at all, which is correct.\n            event: \"*\",\n            schema: repository.schema,\n            table: repository.tables.participants,\n            filter: `meeting_id=eq.${meetingId}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: ({ row }) => {\n              if (row === null) return;\n              const attendee = repository.projectAttendee(row);\n              store.learn([attendee]);\n              // The durable row is the verdict, wherever it was made (see `applyDoorRow`).\n              applyDoorRow(store, attendee);\n            },\n          },\n          {\n            event: \"*\",\n            schema: repository.schema,\n            table: repository.tables.recordings,\n            filter: `meeting_id=eq.${meetingId}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: ({ row }) => {\n              // 🚨 THE INDICATOR RENDERS THE DURABLE STATE, not this browser's\n              // hope. Through 0.4.7 nothing subscribed here, so the only\n              // transitions the store ever saw were the optimistic `starting`\n              // and `stopping` THIS client patched — and the indicator sat on\n              // \"Starting recording…\" for a whole meeting while a healthy\n              // egress ran, then \"Stopping recording…\" forever (MRI-C8).\n              if (row === null) return;\n              const recording = repository.projectRecording(row);\n              store.setRecording(recording.state, recording.startedBy, \"record\", recording.id);\n            },\n          },\n          {\n            event: \"*\",\n            schema: repository.schema,\n            table: repository.tables.meetings,\n            filter: `id=eq.${meetingId}`,\n            rowId: (row) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined),\n            onChange: ({ row }) => {\n              // The note-taker's state lives on this row's metadata (D9/MRI-A2),\n              // so this subscription is what keeps each server-recorded state\n              // current on screen without a reload.\n              if (row === null) return;\n              const meeting = repository.projectMeeting(row);\n              store.patch({ meeting, locked: meeting.locked });\n            },\n          },\n        ],\n        // THE BACKFILL DOOR. Realtime has no replay: everything that happened\n        // while the socket was down is gone. Re-reading all three is what keeps\n        // a recovered surface from looking healthy and being wrong.\n        onBackfill: async () => {\n          const [meeting, transcript, notes, recordings, attendees] = await Promise.all([\n            readMeeting(meetingId),\n            repository.transcript(meetingId),\n            repository.notes(meetingId),\n            repository.recordings(meetingId),\n            repository.attendees(meetingId),\n          ]);\n          store.patch({ meeting, locked: meeting.locked });\n          for (const segment of transcript) store.ingestRecord(segment);\n          for (const note of notes) store.upsertNote(note);\n          // A socket blip must not leave the indicator saying something the\n          // database stopped agreeing with ten minutes ago. `recordings` is\n          // newest first.\n          const latest = recordings[0];\n          if (latest !== undefined) {\n            store.setRecording(latest.state, latest.startedBy, \"record\", latest.id);\n          }\n          // Everyone the durable rows know a name for, and every knocker still\n          // waiting. A host who reloads must not lose a person at the door.\n          store.learn(attendees);\n          // The same rule on the backfill door: a host who reloads must not find people at the\n          // door who were admitted while they were gone, and finds the people they declined.\n          for (const attendee of attendees) applyDoorRow(store, attendee);\n        },\n      });\n      // The FIRST read is the same read: a surface that joins a meeting already\n      // in progress must see what was already said.\n      meetingChannel.requestBackfill(\"manual\");\n    },\n\n    async admit(entry, admitted) {\n      const by = requireAdmitterUser(\"meet.admit\");\n      const meeting = requireMeeting(\"meet.admit\");\n      // THE RPC IS THE DECISION, and it returns the row as it now stands — that row (not\n      // this click) is what the panel shows. Two hosts deciding at once is the ordinary\n      // case: the second sees the first's verdict.\n      const row = await repository.decideAdmission({\n        meetingId: meeting.id,\n        identity: entry.identity,\n        decision: admitted ? \"admit\" : \"deny\",\n        byUserId: by,\n      });\n      store.upsertLobby({\n        ...entry,\n        state: decidedState(row.admissionState),\n        decidedAt: new Date().toISOString(),\n        decidedBy: by,\n      });\n      await tellServerAdmissionChanged(\"meet.admit\");\n      hint();\n    },\n\n    async undeny(entry) {\n      const by = requireAdmitterUser(\"meet.undeny\");\n      const meeting = requireMeeting(\"meet.undeny\");\n      const row = await repository.decideAdmission({\n        meetingId: meeting.id,\n        identity: entry.identity,\n        decision: \"undeny\",\n        byUserId: by,\n      });\n      store.upsertLobby({ ...entry, state: decidedState(row.admissionState), decidedAt: new Date().toISOString(), decidedBy: by });\n      await tellServerAdmissionChanged(\"meet.undeny\");\n      hint();\n    },\n\n    async admitAll() {\n      const by = requireAdmitterUser(\"meet.admitAll\");\n      const meeting = requireMeeting(\"meet.admitAll\");\n      const rows = await repository.admitAll(meeting.id, by);\n      for (const row of rows) {\n        store.setAdmission(row.identity, row.admissionState, by);\n      }\n      await tellServerAdmissionChanged(\"meet.admitAll\");\n      hint();\n    },\n\n    startWaiting() {\n      if (polling) return;\n      polling = true;\n      admittedOnce = false;\n      listen();\n      schedule(0);\n    },\n\n    stopWaiting,\n    readState,\n    readLivePolicy,\n\n    async acknowledgeConsent() {\n      const meeting = requireMeeting(\"meet.consent\");\n      const pass = options.resolvePass?.() ?? null;\n      const response = await options.api.request({\n        path: MEET_ROUTES.consent,\n        method: \"POST\",\n        requireAuth: false,\n        operation: \"meet.consent\",\n        body: { meeting_id: meeting.id },\n        ...(pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}),\n      });\n      if (!response.ok) {\n        throw new MeetError(\"transport\", `meet.consent: the server answered ${response.status}`, \"Your agreement was not saved. Try again.\");\n      }\n    },\n\n    async readExit(connection, held) {\n      const meeting = store.snapshot().meeting;\n      const pass = held ?? options.resolvePass?.() ?? null;\n      if (meeting === null || pass === null) return undefined;\n      try {\n        const response = await options.api.request({\n          path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}&connection=${encodeURIComponent(connection)}`,\n          method: \"GET\",\n          requireAuth: false,\n          operation: \"meet.state(exit)\",\n          headers: { [MEETING_PASS_HEADER]: pass },\n        });\n        if (!response.ok) return null;\n        const read = (await response.json()) as StateRead;\n        return {\n          exitReason: read.exit_reason ?? null,\n          sessionPhase: read.session_phase ?? null,\n          meetingPhase: read.meeting_phase ?? null,\n        };\n      } catch {\n        return null;\n      }\n    },\n\n    async withdraw() {\n      stopWaiting();\n      await postLeave(\"withdraw\");\n      patchWaiting({ admission: \"withdrawn\" });\n      store.dispatch({ type: \"admission\", admission: \"withdrawn\" });\n      hint();\n    },\n\n    async hostLeave(intent) {\n      if (intent === \"end_for_all\") await postLeave(\"end_for_all\");\n      else await postLeave(\"assign_and_leave\", { assign_to: intent.assignTo });\n    },\n\n    async askAgain() {\n      // A new mint IS the new knock (the server upserts the person row per the re-knock rule).\n      await options.rejoin?.();\n    },\n\n    async meetingRule(key) {\n      const meeting = requireMeeting(\"meet.meetingRule\");\n      return repository.meetingRule(meeting.id, key);\n    },\n\n    async setMeetingRule(key, value) {\n      requireHostUser(\"meet.setMeetingRule\");\n      const meeting = requireMeeting(\"meet.setMeetingRule\");\n      const effective = await repository.setMeetingRule(meeting.id, key, value);\n      hint();\n      return effective;\n    },\n\n    async setLock(locked) {\n      const by = requireHostUser(\"meet.setLock\");\n      const meeting = requireMeeting(\"meet.setLock\");\n      const updated = await repository.setLock(meeting.id, locked, by);\n      store.patch({ meeting: updated, locked: updated.locked });\n      // The lock is the meeting row (members see it through Postgres Changes); waiting people\n      // are told to read again.\n      hint();\n      return updated;\n    },\n\n    /**\n     * END IT FOR EVERYONE — a SERVER decision, not a row this client updates.\n     *\n     * 0.2.1 called the `meet_end_meeting` RPC directly, which ended the meeting\n     * in the database while LiveKit kept the room open and the note-taker kept\n     * writing into an ended meeting. `POST /v1/meet/end` re-checks the host,\n     * closes the room, and triggers the wrap-up — one decision, one place\n     * (MRI-A6).\n     *\n     * 🚨 A SERVER THAT HAS NOT LANDED THAT ROUTE ANSWERS 404, and that is\n     * reported as a sentence, never as a dead control and never as a success.\n     */\n    async endForEveryone() {\n      requireHostUser(\"meet.endForEveryone\");\n      const meeting = requireMeeting(\"meet.endForEveryone\");\n      const response = await options.api.request({\n        path: MEET_ROUTES.meetingEnd,\n        method: \"POST\",\n        requireAuth: true,\n        operation: \"meet.endForEveryone\",\n        body: {\n          meeting_id: meeting.id,\n          organization_id: identity.organizationId,\n        },\n      });\n      if (response.status === 404) {\n        return { endedAt: null, served: false };\n      }\n      if (!response.ok) {\n        let body: unknown = null;\n        try {\n          body = await response.json();\n        } catch {\n          body = null;\n        }\n        const refusal = readRefusalBody(body);\n        throw new MeetError(\n          response.status === 403 ? \"forbidden\" : \"transport\",\n          refusal?.reason ?? `meet.endForEveryone: the server answered ${response.status}`,\n          refusal?.remedy !== undefined && refusal.remedy.length > 0\n            ? refusal.remedy\n            : \"The meeting is still running. Only a host may end it, and the server \" +\n              \"re-checks that — being a host on this screen is not the decision.\",\n        );\n      }\n      let payload: unknown = null;\n      try {\n        payload = await response.json();\n      } catch {\n        payload = null;\n      }\n      const row =\n        typeof payload === \"object\" && payload !== null\n          ? (payload as Record<string, unknown>)\n          : {};\n      const endedAt =\n        typeof row[\"ended_at\"] === \"string\" ? row[\"ended_at\"] : new Date().toISOString();\n      const current = store.snapshot().meeting;\n      if (current !== null) store.patch({ meeting: { ...current, endedAt } });\n      return { endedAt, served: true };\n    },\n\n    dispose() {\n      stopWaiting();\n      unsubscribePolicy();\n      if (policyTimer !== null) clearInterval(policyTimer);\n      policyTimer = null;\n      channel?.close();\n      channel = null;\n      meetingChannel?.close();\n      meetingChannel = null;\n    },\n  };\n}\n\n/**\n * A durable public slug. Lowercase, hyphenated, and deliberately readable —\n * people read these aloud on phone calls. The alphabet excludes the four\n * characters that get misheard (0/O, 1/l).\n */\nconst SLUG_ALPHABET = \"abcdefghijkmnpqrstuvwxyz23456789\";\n\nexport function meetingSlug(random: () => number = Math.random): string {\n  const group = (length: number): string =>\n    Array.from({ length }, () => {\n      const index = Math.floor(random() * SLUG_ALPHABET.length);\n      return SLUG_ALPHABET[index] ?? \"a\";\n    }).join(\"\");\n  return `${group(3)}-${group(4)}-${group(3)}`;\n}\n\n/** The link a host copies. ONE shape, so every surface produces the same URL. */\nexport function meetingLink(baseUrl: string, slug: string): string {\n  return `${baseUrl.replace(/\\/+$/, \"\")}/meet/${slug}`;\n}\n","/**\n * WHO IS ACTING — read from the session, never from a prop (DD-240).\n *\n * THE CLASS THIS CLOSES. Through 0.5.x `<MeetProvider userId>` took the acting\n * user's id from the host, and every host had the same one source for it: a\n * copy held in its own client state (matrx-frontend's Redux `selectUserId`).\n * That copy is written once, when the app boots, and nothing rewrites it when\n * the domain-wide auth cookie rotates to a different account, when the person\n * signs out in another tab, or when a refresh returns a different subject. The\n * package then went on issuing user-scoped reads on behalf of somebody the\n * session is no longer:\n *\n *   `communication.meet_pending_call_invites(p_user_id => <the stale copy>)`\n *   → 42501 at HTTP 403, \"meet: the acting user (4cf62e4e…) is not the\n *     authenticated user\"\n *\n * Measured on production 2026-09-14 (register DD-238/DD-240): the two rows came\n * from tabs 8.8 h and 32.9 h old, and the id in the argument named a DIFFERENT\n * account from the one the error sink recorded for the same row. The database\n * was right both times. The defect was that a user id can be handed in at all.\n *\n * So there is ONE source now, and it is the client's own session. The same\n * client that mints the JWT on every PostgREST request answers \"who is this?\",\n * so the id in the argument and the id in the token cannot disagree — not\n * because they are kept in step, but because they are the same fact read once.\n *\n * WHAT THIS MODULE IS. A tiny observable over `client.auth`: the current acting\n * user id, a subscription that fires when it changes, and a `resolving` state\n * that is honest about the moment before the first `getSession()` answers.\n *\n *  - It is `resolving` until the first read lands. Nothing user-scoped is\n *    issued in that window, which is what a page-load race used to spend\n *    issuing reads as a user the tab could not prove it was.\n *  - `snapshot()` returns THE SAME REFERENCE until the acting user moves\n *    (FEATURE.md rule 7b — a `useSyncExternalStore` source that returns a fresh\n *    object per call is \"Maximum update depth exceeded\", not a warning).\n *  - It NEVER refuses anything on its own authority. It reports who the session\n *    says you are; the database remains the only thing that decides what that\n *    is allowed to read.\n *  - A client with no `auth` at all is a real, named failure with a remedy —\n *    never a silent fall back to \"nobody\" (FEATURE.md rule 7).\n *\n * THE CLIENT BOUNDARY STAYS SHALLOW (0.2.1, `repository.ts`'s header). The\n * public prop type is still `MessagingSupabaseClient`, which does not describe\n * `auth` at all — so this module narrows to its own minimal `AuthLike` in ONE\n * place, exactly as `createMeetRepository` narrows to `SupabaseLike`. A real\n * `SupabaseClient` satisfying `AuthLike` is proven at compile time in\n * `supabase-shape.test.ts`.\n */\n\nimport {\n  createSessionIdentity as createDataSessionIdentity,\n  type SessionIdentity as DataSessionIdentity,\n  type SessionIdentityDiagnostic,\n  type SessionIdentitySnapshot as DataSessionIdentitySnapshot,\n  type SessionIdentityWords,\n} from \"@ai-matrx/auth/session-identity\";\nimport type { MessagingSupabaseClient } from \"@ai-matrx/messaging\";\nimport { asUserId, type UserId } from \"./types\";\n\n// The session reader itself has ONE home, `@ai-matrx/auth/session-identity` (architecture step\n// 11); meet supplies its words and its branded `UserId`.\nexport { authOf, SERVER_SESSION_IDENTITY } from \"@ai-matrx/auth/session-identity\";\nexport type { AuthLike, AuthSessionLike, AuthSubscriptionLike } from \"@ai-matrx/auth/session-identity\";\n\nexport type SessionIdentitySnapshot = DataSessionIdentitySnapshot<UserId>;\nexport type SessionIdentity = DataSessionIdentity<UserId>;\n\nexport interface SessionIdentityOptions {\n  readonly client: MessagingSupabaseClient;\n  readonly onDiagnostic?: ((event: SessionIdentityDiagnostic) => void) | undefined;\n}\n\n/** What meet says about its session. */\nexport const MEET_SESSION_WORDS: SessionIdentityWords = {\n  product: \"Meet\",\n  noAuthSourceRemedy:\n    \"Pass your app's browser Supabase client to <MeetProvider client={...}> — the same \" +\n    \"client it signs in with. Meet reads the acting user from that client's session; \" +\n    \"there is no prop for a user id, on purpose.\",\n  unreadableRemedy:\n    \"Calls and meetings stay unavailable on this device until the session can be read. \" +\n    \"Reload the page; if it persists, sign in again.\",\n};\n\n/** The acting user of `client`'s session, in meet's words. */\nexport function createMeetSessionIdentity(options: SessionIdentityOptions): SessionIdentity {\n  return createDataSessionIdentity<UserId>({\n    client: options.client,\n    words: MEET_SESSION_WORDS,\n    toUserId: asUserId,\n    onDiagnostic: options.onDiagnostic,\n  });\n}\n","/**\n * CG — WHAT THIS BROWSER CAN DO, probed before anything else (CORE-DESIGN §11 `browser-unsupported`,\n * `share-unsupported-mobile`). Pure over an injected scope so the rules are the tests; the web\n * reading is `detectCapabilities()` with no argument. Never touches LiveKit.\n */\n\nexport type UnsupportedReason = \"no_webrtc\";\n\nexport interface MeetCapabilities {\n  /** False only when a call cannot run here at all (no WebRTC: an in-app webview, an old browser). */\n  readonly canJoin: boolean;\n  readonly reason: UnsupportedReason | null;\n  /** The in-app browser this looks like (Instagram, Facebook, LinkedIn…), or null. */\n  readonly inAppBrowser: string | null;\n  /** A phone or tablet: no screen sharing from the browser there. */\n  readonly mobile: boolean;\n  /** `getDisplayMedia` exists AND this is not a phone/tablet. */\n  readonly canShareScreen: boolean;\n}\n\ninterface ScopeLike {\n  readonly RTCPeerConnection?: unknown;\n  readonly webkitRTCPeerConnection?: unknown;\n  readonly navigator?: {\n    readonly userAgent?: string;\n    readonly maxTouchPoints?: number;\n    readonly mediaDevices?: { readonly getDisplayMedia?: unknown };\n  };\n}\n\nconst IN_APP: readonly [RegExp, string][] = [\n  [/Instagram/i, \"Instagram\"],\n  [/FBAN|FBAV|FB_IAB/i, \"Facebook\"],\n  [/LinkedInApp/i, \"LinkedIn\"],\n  [/MicroMessenger/i, \"WeChat\"],\n  [/Snapchat/i, \"Snapchat\"],\n  [/\\bLine\\//i, \"LINE\"],\n  [/Twitter|TwitterAndroid/i, \"X\"],\n  [/TikTok|musical_ly|BytedanceWebview/i, \"TikTok\"],\n];\n\nexport function isMobileUserAgent(userAgent: string, maxTouchPoints = 0): boolean {\n  if (/iPhone|iPod|Android|Mobile|iPad/i.test(userAgent)) return true;\n  // iPadOS reports a Mac user agent; touch points give it away.\n  return /Macintosh/.test(userAgent) && maxTouchPoints > 1;\n}\n\nexport function detectCapabilities(scope: ScopeLike | null = typeof globalThis === \"undefined\" ? null : (globalThis as ScopeLike)): MeetCapabilities {\n  // Outside a browser (a server render, a test with no scope) nothing is known to be missing.\n  if (scope === null || scope.navigator === undefined) {\n    return { canJoin: true, reason: null, inAppBrowser: null, mobile: false, canShareScreen: false };\n  }\n  const ua = scope.navigator.userAgent ?? \"\";\n  const webrtc = typeof scope.RTCPeerConnection === \"function\" || typeof scope.webkitRTCPeerConnection === \"function\";\n  const mobile = isMobileUserAgent(ua, scope.navigator.maxTouchPoints ?? 0);\n  const inAppBrowser = IN_APP.find(([pattern]) => pattern.test(ua))?.[1] ?? null;\n  return {\n    canJoin: webrtc,\n    reason: webrtc ? null : \"no_webrtc\",\n    inAppBrowser,\n    mobile,\n    canShareScreen: !mobile && typeof scope.navigator.mediaDevices?.getDisplayMedia === \"function\",\n  };\n}\n\n/** The words for a browser that cannot join: what to open instead. Short lines (layout, not prose). */\nexport function unsupportedWords(capabilities: MeetCapabilities): { readonly title: string; readonly body: string } {\n  if (capabilities.inAppBrowser !== null) {\n    return {\n      title: `${capabilities.inAppBrowser}'s browser can't join calls`,\n      body: \"Open this link in Chrome, Safari, Edge or Firefox\",\n    };\n  }\n  return { title: \"Meet is not compatible with your browser yet\", body: \"Open this link in Chrome, Safari, Edge or Firefox\" };\n}\n","/**\n * MS — THE MEDIA SUPERVISOR (CORE-DESIGN §3.3, step S6c).\n *\n * Owns the media regions of §3.2 that are about THIS person's devices and speakers:\n *\n * - **Permission per kind.** The browser's error alone cannot tell a person's Block from an\n *   operating-system refusal or a stale device id (`NotAllowedError` is all three in Chrome), so\n *   every refusal is classified against the Permissions API: `denied` there is the person's (or\n *   the site's) Block; a refusal while the browser says `granted` is the operating system. A kind\n *   whose permission is `denied` reads `unavailable:denied` even when nothing tried to open it —\n *   a camera the browser will not hand over is not \"off by choice\".\n * - **Live device switching.** LiveKit falls back to the default for a lost MICROPHONE by itself\n *   but MUTES a lost camera (client-sdk-js #2035). On every device change the supervisor checks\n *   the devices in use against the devices present: a vanished camera moves to the next camera;\n *   a vanished microphone is reported with the device LiveKit moved to; nothing left of a kind is\n *   `unavailable:none`. Each is a notice — never a silent switch. A NEW device is offered, never\n *   taken (a person mid-sentence does not want their mic to jump to a headset being charged).\n * - **Autoplay.** `audio_output` = `blocked` while the browser holds remote audio until a gesture;\n *   `enableAudio()` runs inside the person's click; the check is repeated when the tab comes back.\n *\n * 🚨 NOTHING HERE CHANGES THE CALL PHASE (§3.1 invariant). Every outcome is region state.\n * 🚨 NO BROWSER GLOBAL IS TOUCHED HERE: the browser half is the `MediaPlatform` port (§3.5) —\n * `webMediaPlatform()` below is the web adapter; a React Native host passes its own.\n */\n\nimport type {\n  DevicePreview,\n  DeviceUnavailableReason,\n  LocalTrackState,\n  MediaRegionState,\n  MediaUnavailable,\n  PermissionReading,\n} from \"./attendance\";\nimport { listMediaDevices, type MediaDevicesLike } from \"@ai-matrx/browser-audio/core\";\n\nimport { unavailableFrom } from \"./attendance\";\nimport { normalizeDeviceError, type MeetError } from \"./errors\";\nimport type { MeetRoomDriver } from \"./room-driver\";\nimport type { MeetStore } from \"./store\";\n\nexport type MediaKind = \"microphone\" | \"camera\";\nexport type BrowserFamily = \"chrome\" | \"edge\" | \"firefox\" | \"safari\" | \"other\";\nexport type OsFamily = \"mac\" | \"windows\" | \"ios\" | \"android\" | \"linux\" | \"other\";\n\nexport interface PlatformDevice {\n  readonly deviceId: string;\n  readonly kind: string;\n  readonly label: string;\n}\n\n/** The slice of §3.5's `MeetPlatform` the media supervisor needs. */\nexport interface MediaPlatform {\n  readonly browser: BrowserFamily;\n  readonly os: OsFamily;\n  /** The Permissions API reading, or `unknown` where the browser has none for this kind. */\n  queryPermission(kind: MediaKind): Promise<PermissionReading>;\n  /** Call `onChange` whenever the permission for `kind` changes. Returns the unsubscribe. */\n  watchPermission(kind: MediaKind, onChange: (reading: PermissionReading) => void): () => void;\n  listDevices(): Promise<readonly PlatformDevice[]>;\n  /** The tab became visible again (autoplay is re-checked then). Returns the unsubscribe. */\n  onVisible(callback: () => void): () => void;\n}\n\n/* ------------------------------------------------------------ classification */\n\n/**\n * The region reason for a refused device, from the error AND the permission store.\n * Pure — the rules are the tests.\n */\nexport function classifyDeviceFailure(\n  error: { readonly code: string; readonly message: string },\n  permission: PermissionReading,\n): DeviceUnavailableReason {\n  if (permission === \"denied\") return \"denied\";\n  switch (error.code) {\n    case \"permission-denied\":\n      // Chrome names an OS refusal (\"Permission denied by system\"); everywhere else a refusal\n      // while the browser itself says `granted` can only be the operating system.\n      if (/by system/i.test(error.message) || permission === \"granted\") return \"blocked_os\";\n      return \"denied\";\n    case \"device-not-found\":\n      return \"none\";\n    case \"device-in-use\":\n      return \"busy\";\n    case \"insecure-context\":\n      return \"blocked_site\";\n    default:\n      return \"failed\";\n  }\n}\n\n/** The contract notice code for an unusable device (HARNESS-CONTRACT §4). */\nexport function deviceNoticeCode(kind: MediaKind, reason: DeviceUnavailableReason): \"mic-blocked\" | \"camera-blocked\" | \"device-lost\" {\n  if (reason === \"denied\" || reason === \"blocked_site\" || reason === \"blocked_os\") {\n    return kind === \"microphone\" ? \"mic-blocked\" : \"camera-blocked\";\n  }\n  return \"device-lost\";\n}\n\n/**\n * The region reason this track is in, or null when the device is usable (on, or off by choice).\n * A kind the browser's permission store denies is `denied` even when nothing tried to open it.\n */\nexport function deviceUnavailableReason(track: LocalTrackState, permission: PermissionReading): DeviceUnavailableReason | null {\n  if (track.enabled) return null;\n  if (permission === \"denied\") return \"denied\";\n  const refused = track.unavailable;\n  if (refused === null) return null;\n  return refused.reason ?? classifyDeviceFailure({ code: refused.code, message: refused.message }, permission);\n}\n\n/** The short chip text — the skin's words may differ; the reason is the fact. */\nexport function deviceChipLabel(kind: MediaKind, reason: DeviceUnavailableReason): string {\n  const what = kind === \"microphone\" ? \"Mic\" : \"Camera\";\n  switch (reason) {\n    case \"denied\":\n    case \"blocked_site\":\n    case \"blocked_os\":\n      return `${what} blocked`;\n    case \"none\":\n      return kind === \"microphone\" ? \"No microphone found\" : \"No camera found\";\n    case \"busy\":\n      return `${what} in use by another app`;\n    case \"revoked\":\n      return `${what} access was turned off`;\n    default:\n      return `${what} didn't start`;\n  }\n}\n\n/**\n * THE REAL REMEDY, per browser and operating system: the steps a person actually follows. Short\n * lines (interface text is layout); the last step is always the Try again the screen offers.\n */\nexport function deviceFixSteps(\n  kind: MediaKind,\n  reason: DeviceUnavailableReason,\n  where: { readonly browser: BrowserFamily; readonly os: OsFamily },\n): readonly string[] {\n  const device = kind === \"microphone\" ? \"Microphone\" : \"Camera\";\n  const lower = device.toLowerCase();\n  switch (reason) {\n    case \"denied\":\n    case \"revoked\":\n    case \"blocked_site\":\n      switch (where.browser) {\n        case \"firefox\":\n          return [`Click the crossed-out ${lower} icon in the address bar`, \"Clear the Blocked setting\", \"Press Try again and choose Allow\"];\n        case \"safari\":\n          return where.os === \"ios\"\n            ? [`Settings › Apps › Safari › ${device}`, \"Choose Allow\", \"Return here and press Try again\"]\n            : [\"Safari › Settings for This Website\", `Set ${device} to Allow`, \"Press Try again\"];\n        default:\n          return [\"Click the site settings icon in the address bar\", `Set ${device} to Allow`, \"Press Try again\"];\n      }\n    case \"blocked_os\": {\n      const app = where.browser === \"chrome\" ? \"Google Chrome\" : where.browser === \"edge\" ? \"Microsoft Edge\" : where.browser === \"firefox\" ? \"Firefox\" : \"your browser\";\n      if (where.os === \"mac\") return [`System Settings › Privacy & Security › ${device}`, `Turn on ${app}`, \"Reopen the browser if asked, then Try again\"];\n      if (where.os === \"windows\") return [`Settings › Privacy & security › ${device}`, `Turn on ${device} access for apps`, \"Press Try again\"];\n      return [`Allow ${lower} access for ${app} in your system settings`, \"Press Try again\"];\n    }\n    case \"busy\":\n      return [`Close other apps using the ${lower} (Zoom, Teams, another tab)`, \"Press Try again\"];\n    case \"none\":\n      return [`Connect a ${lower}`, \"Press Try again\"];\n    default:\n      return [`Pick another ${lower} in Settings`, \"Press Try again\"];\n  }\n}\n\n/* ------------------------------------------------------------ the web adapter */\n\nexport function detectBrowser(userAgent: string): BrowserFamily {\n  if (/Edg\\//.test(userAgent)) return \"edge\";\n  if (/Firefox\\//.test(userAgent)) return \"firefox\";\n  if (/Chrome\\/|Chromium\\/|CriOS\\//.test(userAgent)) return \"chrome\";\n  if (/Safari\\//.test(userAgent)) return \"safari\";\n  return \"other\";\n}\n\nexport function detectOs(userAgent: string, maxTouchPoints = 0): OsFamily {\n  if (/iPhone|iPad|iPod/.test(userAgent)) return \"ios\";\n  // iPadOS reports a Mac user agent; touch points give it away (catalog `mobile-ipad-detect`).\n  if (/Macintosh/.test(userAgent)) return maxTouchPoints > 1 ? \"ios\" : \"mac\";\n  if (/Android/.test(userAgent)) return \"android\";\n  if (/Windows/.test(userAgent)) return \"windows\";\n  if (/Linux|CrOS/.test(userAgent)) return \"linux\";\n  return \"other\";\n}\n\ninterface PermissionStatusLike {\n  state: string;\n  onchange: (() => void) | null;\n}\n\n/** The browser adapter, or null outside a browser (SSR, a test, React Native without one). */\nexport function webMediaPlatform(): MediaPlatform | null {\n  const scope = globalThis as unknown as {\n    navigator?: {\n      userAgent?: string;\n      maxTouchPoints?: number;\n      permissions?: { query(descriptor: { name: string }): Promise<PermissionStatusLike> };\n      mediaDevices?: MediaDevicesLike;\n    };\n    document?: { visibilityState?: string; addEventListener(t: string, f: () => void): void; removeEventListener(t: string, f: () => void): void };\n  };\n  const nav = scope.navigator;\n  if (nav === undefined) return null;\n  const ua = nav.userAgent ?? \"\";\n  const reading = (state: string | undefined): PermissionReading =>\n    state === \"granted\" || state === \"denied\" || state === \"prompt\" ? state : \"unknown\";\n  const query = async (kind: MediaKind): Promise<PermissionStatusLike | null> => {\n    try {\n      return (await nav.permissions?.query({ name: kind })) ?? null;\n    } catch {\n      // Firefox before 2024 and older Safari have no camera/microphone descriptor.\n      return null;\n    }\n  };\n  return {\n    browser: detectBrowser(ua),\n    os: detectOs(ua, nav.maxTouchPoints ?? 0),\n    async queryPermission(kind) {\n      return reading((await query(kind))?.state);\n    },\n    watchPermission(kind, onChange) {\n      let status: PermissionStatusLike | null = null;\n      let stopped = false;\n      void query(kind).then((found) => {\n        if (stopped || found === null) return;\n        status = found;\n        found.onchange = () => onChange(reading(found.state));\n      });\n      return () => {\n        stopped = true;\n        if (status !== null) status.onchange = null;\n      };\n    },\n    async listDevices() {\n      try {\n        if (nav.mediaDevices === undefined) return [];\n        // The one device listing (browser-audio); flattened back to the platform's flat list.\n        const list = await listMediaDevices({ mediaDevices: nav.mediaDevices });\n        return [...list.audioInputs, ...list.audioOutputs, ...list.videoInputs];\n      } catch {\n        return [];\n      }\n    },\n    onVisible(callback) {\n      const doc = scope.document;\n      if (doc === undefined) return () => undefined;\n      const handler = (): void => {\n        if (doc.visibilityState === \"visible\") callback();\n      };\n      doc.addEventListener(\"visibilitychange\", handler);\n      return () => doc.removeEventListener(\"visibilitychange\", handler);\n    },\n  };\n}\n\n/* ------------------------------------------------------------ the supervisor */\n\nexport interface MediaSupervisorOptions {\n  readonly store: MeetStore;\n  readonly platform: MediaPlatform | null;\n  /** The live room's driver, or null between rooms. */\n  readonly driver: () => MeetRoomDriver | null;\n  readonly report: (level: \"info\" | \"warn\" | \"error\", message: string, remedy?: string) => void;\n}\n\nexport interface MediaSupervisor {\n  /** Begin watching permissions and visibility (idempotent). */\n  start(): void;\n  stop(): void;\n  /** The `MediaUnavailable` for a refused device: the browser's words + the region reason. */\n  unavailable(error: unknown, kind: MediaKind, operation: string): Promise<MediaUnavailable>;\n  /** Driver handlers (wired by the engine). */\n  onAudioPlayback(canPlay: boolean): void;\n  onDevicesChanged(): void;\n  onDeviceError(error: unknown, kind: \"audioinput\" | \"videoinput\" | null): void;\n  /** The engine connected a room: remember which devices are in use now. */\n  onConnected(): void;\n  /** The room is gone: autoplay and device notices belong to the room. */\n  onDisconnected(): void;\n  /** \"Enable sound\" — call from inside the person's click. */\n  enableAudio(): Promise<void>;\n  /**\n   * The pre-join preview's outcome for one kind: `prompting` when it asks the browser, `on` / `off`\n   * when it settles or is turned off, or the error it was refused with (classified here, against\n   * the permission store, exactly as an in-room refusal is).\n   */\n  preview(kind: MediaKind, outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }): Promise<void>;\n  /** Use the offered new device. */\n  acceptOffer(): Promise<void>;\n  dismissOffer(): void;\n  dismissNotice(): void;\n  /** Undo on a \"switched\" notice: go back to the device that went away, when it is available again. */\n  undoNotice(): Promise<void>;\n}\n\nconst INPUT_KIND: Record<MediaKind, \"audioinput\" | \"videoinput\"> = { microphone: \"audioinput\", camera: \"videoinput\" };\n\n/** A browser's pseudo-devices: they follow the system choice and are never a \"new device\". */\nfunction isAlias(deviceId: string): boolean {\n  return deviceId === \"default\" || deviceId === \"communications\" || deviceId === \"\";\n}\n\nexport function createMediaSupervisor(options: MediaSupervisorOptions): MediaSupervisor {\n  const { store, platform } = options;\n  let unsubscribers: (() => void)[] = [];\n  let started = false;\n  let noticeId = 0;\n  /** The devices present at the last look, per input kind (ids → label). */\n  let known: Record<\"audioinput\" | \"videoinput\", Map<string, string>> | null = null;\n  /** The device in use per kind at the last look (to name what went away). */\n  let inUse: Record<\"audioinput\" | \"videoinput\", string | null> = { audioinput: null, videoinput: null };\n\n  function region(): MediaRegionState {\n    return store.snapshot().mediaRegion;\n  }\n  function setRegion(next: Partial<MediaRegionState>): void {\n    const current = region();\n    const merged = { ...current, ...next };\n    if (\n      merged.audioOutput === current.audioOutput &&\n      merged.notice === current.notice &&\n      merged.offer === current.offer &&\n      merged.preview === current.preview &&\n      merged.permission.microphone === current.permission.microphone &&\n      merged.permission.camera === current.permission.camera\n    ) {\n      return;\n    }\n    store.patch({ mediaRegion: merged });\n  }\n\n  function setPermission(kind: MediaKind, reading: PermissionReading): void {\n    const current = region().permission;\n    if (current[kind] === reading) return;\n    setRegion({ permission: { ...current, [kind]: reading } });\n    // Allowed again while the device sits refused: say what is true now (the person presses\n    // Try again — LiveKit itself resumes a REVOKED track on re-grant).\n    const track = store.snapshot().media[kind];\n    if (reading === \"granted\" && !track.enabled && track.unavailable?.reason === \"denied\") {\n      store.setLocalTrack(kind, {\n        enabled: false,\n        unavailable: { ...track.unavailable, reason: \"failed\", remedy: \"Access is allowed now. Press Try again.\" },\n      });\n    }\n  }\n\n  async function snapshotDevices(): Promise<Record<\"audioinput\" | \"videoinput\", Map<string, string>>> {\n    const list = platform === null ? [] : await platform.listDevices();\n    const out = { audioinput: new Map<string, string>(), videoinput: new Map<string, string>() };\n    for (const device of list) {\n      if (device.kind === \"audioinput\" || device.kind === \"videoinput\") out[device.kind].set(device.deviceId, device.label);\n    }\n    return out;\n  }\n\n  function readInUse(): void {\n    const driver = options.driver();\n    if (driver === null) return;\n    const active = driver.activeDevices();\n    inUse = { audioinput: active.audioinput, videoinput: active.videoinput };\n  }\n\n  async function handleDevicesChanged(): Promise<void> {\n    if (platform === null) return;\n    const before = known;\n    const now = await snapshotDevices();\n    known = now;\n    const driver = options.driver();\n    if (driver === null || before === null) {\n      readInUse();\n      return;\n    }\n    for (const kind of [\"microphone\", \"camera\"] as const) {\n      const deviceKind = INPUT_KIND[kind];\n      const previous = inUse[deviceKind];\n      const track = store.snapshot().media[kind];\n      // An alias (\"default\") is the device the system points it at: it is gone when it left the list or now names a different device.\n      const aliasLabel = previous !== null && isAlias(previous) ? before[deviceKind].get(previous) : undefined;\n      const aliasGone =\n        previous !== null && aliasLabel !== undefined && aliasLabel !== \"\" && (!now[deviceKind].has(previous) || now[deviceKind].get(previous) !== aliasLabel);\n      const gone = aliasGone || (previous !== null && !isAlias(previous) && before[deviceKind].has(previous) && !now[deviceKind].has(previous));\n      if (gone) {\n        const from = before[deviceKind].get(previous) ?? \"\";\n        const remaining = [...now[deviceKind].entries()].filter(([id]) => !isAlias(id));\n        if (remaining.length === 0) {\n          // Nothing of this kind is left: the device is unusable, not \"off\".\n          store.setLocalTrack(kind, {\n            enabled: false,\n            unavailable: {\n              code: \"device-not-found\",\n              message: `meet.${kind}: the ${kind} was disconnected and no other is connected`,\n              remedy: `Connect a ${kind === \"microphone\" ? \"microphone\" : \"camera\"}, then press Try again.`,\n              reason: \"none\",\n            },\n          });\n          setRegion({ notice: { id: ++noticeId, kind, outcome: \"lost\", from, to: null } });\n          continue;\n        }\n        if (kind === \"camera\") {\n          // LiveKit mutes a lost camera (#2035): the supervisor moves it, keeping on/off as it was.\n          const [nextId, nextLabel] = remaining[0]!;\n          try {\n            await driver.switchDevice(\"videoinput\", nextId);\n            if (track.enabled || track.unavailable !== null) {\n              await driver.setCameraEnabled(true);\n              store.setLocalTrack(\"camera\", { enabled: true, unavailable: null });\n            }\n            setRegion({ notice: { id: ++noticeId, kind, outcome: \"switched\", from, fromId: previous!, to: nextLabel } });\n          } catch (error) {\n            const refused = await unavailable(error, \"camera\", \"meet.camera(fallback)\");\n            store.setLocalTrack(\"camera\", { enabled: false, unavailable: refused });\n            setRegion({ notice: { id: ++noticeId, kind, outcome: \"lost\", from, to: null } });\n          }\n        } else {\n          // LiveKit restarts the microphone on the default device when it can; when the default went with it,\n          // the supervisor moves it to what is left, keeping on/off as it was (device-unplugged-midcall).\n          const active = driver.activeDevices().audioinput;\n          let to = (active !== null && !aliasGone ? now.audioinput.get(active) : undefined) ?? now.audioinput.get(\"default\");\n          if (to === undefined || aliasGone) {\n            const [nextId, nextLabel] = remaining[0]!;\n            try {\n              await driver.switchDevice(\"audioinput\", nextId);\n              if (track.enabled || track.unavailable !== null) {\n                await driver.setMicrophoneEnabled(true);\n                store.setLocalTrack(\"microphone\", { enabled: true, unavailable: null });\n              }\n              to = nextLabel;\n            } catch (error) {\n              const refused = await unavailable(error, \"microphone\", \"meet.microphone(fallback)\");\n              store.setLocalTrack(\"microphone\", { enabled: false, unavailable: refused });\n              setRegion({ notice: { id: ++noticeId, kind, outcome: \"lost\", from, to: null } });\n              continue;\n            }\n          }\n          setRegion({ notice: { id: ++noticeId, kind, outcome: \"switched\", from, fromId: previous!, to } });\n        }\n        continue;\n      }\n      // A NEW device appeared: offer it, never switch silently.\n      const added = [...now[deviceKind].entries()].find(([id]) => !isAlias(id) && !before[deviceKind].has(id));\n      if (added !== undefined && added[0] !== driver.activeDevices()[deviceKind]) {\n        setRegion({ offer: { kind, deviceId: added[0], label: added[1] } });\n      }\n    }\n    readInUse();\n  }\n\n  async function unavailable(error: unknown, kind: MediaKind, operation: string): Promise<MediaUnavailable> {\n    const normalized = normalizeDeviceError(error, operation);\n    const permission = platform === null ? \"unknown\" : await platform.queryPermission(kind);\n    if (permission !== \"unknown\") setPermission(kind, permission);\n    return unavailableFrom(normalized, classifyDeviceFailure(normalized, permission));\n  }\n\n  const api: MediaSupervisor = {\n    start() {\n      if (started || platform === null) return;\n      started = true;\n      for (const kind of [\"microphone\", \"camera\"] as const) {\n        void platform.queryPermission(kind).then((reading) => setPermission(kind, reading));\n        unsubscribers.push(platform.watchPermission(kind, (reading) => setPermission(kind, reading)));\n      }\n      unsubscribers.push(\n        platform.onVisible(() => {\n          // Safari re-suspends audio after a background stint (LiveKit #1751): try again on\n          // return. If the browser still refuses, the Enable sound offer simply stays.\n          const driver = options.driver();\n          if (driver?.startAudio === undefined || region().audioOutput !== \"blocked\") return;\n          driver.startAudio().catch(() => undefined);\n        }),\n      );\n    },\n    stop() {\n      for (const off of unsubscribers) off();\n      unsubscribers = [];\n      started = false;\n    },\n    unavailable,\n    async preview(kind, outcome) {\n      // Reading the permission store before the room exists is what lets the pre-join say\n      // \"blocked\" (not \"didn't start\") — start() is idempotent.\n      api.start();\n      let next: DevicePreview;\n      if (typeof outcome === \"string\") next = { state: outcome, unavailable: null };\n      else next = { state: \"unavailable\", unavailable: await unavailable(outcome.error, kind, `meet.${kind}Preview`) };\n      const current = region().preview;\n      const was = current[kind];\n      if (was.state === next.state && was.unavailable?.reason === next.unavailable?.reason && was.unavailable?.message === next.unavailable?.message) return;\n      setRegion({ preview: { ...region().preview, [kind]: next } });\n    },\n    onAudioPlayback(canPlay) {\n      setRegion({ audioOutput: canPlay ? \"ok\" : \"blocked\" });\n    },\n    onDevicesChanged() {\n      void handleDevicesChanged().catch((error: unknown) => {\n        options.report(\"warn\", `meet: device change could not be handled: ${String(error)}`, \"Pick the device in Settings.\");\n      });\n    },\n    onDeviceError(error, deviceKind) {\n      if (deviceKind === null) return;\n      const kind: MediaKind = deviceKind === \"audioinput\" ? \"microphone\" : \"camera\";\n      void unavailable(error, kind, `meet.${kind}`).then((refused) => {\n        const track = store.snapshot().media[kind];\n        if (track.enabled) return; // the SDK recovered on its own\n        store.setLocalTrack(kind, { enabled: false, unavailable: refused });\n      });\n    },\n    onConnected() {\n      void snapshotDevices().then((now) => {\n        known = now;\n        readInUse();\n      });\n    },\n    onDisconnected() {\n      known = null;\n      inUse = { audioinput: null, videoinput: null };\n      setRegion({ audioOutput: \"ok\", notice: null, offer: null });\n    },\n    async enableAudio() {\n      const driver = options.driver();\n      if (driver?.startAudio === undefined) return;\n      try {\n        await driver.startAudio();\n        setRegion({ audioOutput: \"ok\" });\n      } catch (error) {\n        options.report(\"warn\", `meet: sound could not be enabled: ${String(error)}`, \"Click Enable sound again, or check the tab is not muted.\");\n      }\n    },\n    async acceptOffer() {\n      const offer = region().offer;\n      const driver = options.driver();\n      setRegion({ offer: null });\n      if (offer === null || driver === null) return;\n      try {\n        await driver.switchDevice(INPUT_KIND[offer.kind], offer.deviceId);\n        readInUse();\n      } catch (error) {\n        const refused = await unavailable(error, offer.kind, \"meet.switchDevice\");\n        options.report(\"warn\", refused.message, refused.remedy);\n      }\n    },\n    dismissOffer() {\n      setRegion({ offer: null });\n    },\n    dismissNotice() {\n      setRegion({ notice: null });\n    },\n    async undoNotice() {\n      const notice = region().notice;\n      setRegion({ notice: null });\n      const driver = options.driver();\n      if (notice === null || notice.outcome !== \"switched\" || notice.fromId === undefined || driver === null) return;\n      const list = await snapshotDevices();\n      if (!list[INPUT_KIND[notice.kind]].has(notice.fromId)) return;\n      try {\n        await driver.switchDevice(INPUT_KIND[notice.kind], notice.fromId);\n        readInUse();\n      } catch (error) {\n        const refused = await unavailable(error, notice.kind, \"meet.undoDeviceSwitch\");\n        store.setLocalTrack(notice.kind, { enabled: false, unavailable: refused });\n      }\n    },\n  };\n  return api;\n}\n\n","/**\n * THE PLATFORM'S OWN VOICE IN THE ROOM — and the ONLY live feed a guest has.\n *\n * 🚨 **Why this file exists.** Everything durable a meeting produces — a live\n * note, a decision, an action item, the note-taker's state, the ending — lands\n * in `communication.meet_*`, and a signed-in member learns about it over\n * Postgres Changes. A GUEST cannot: `anon` holds no SELECT grant on\n * `meet_notes`, `meet_transcript_segments` or `meet_participants`, and MRI-A10\n * settled that widening it is forbidden, because those are org-scoped tables and\n * a meeting link is not org membership. A guest's authority is the ROOM TOKEN.\n * So the platform publishes the same rows into the room, where the token is the\n * authorization, and this file turns those packets into exactly the same store\n * calls the database path makes.\n *\n * Three rules hold it together:\n *\n * 1. **Same row, same projection, same reducer.** A `matrx.meet.note` packet\n *    carries a `meet_notes` row and is projected by `projectNote` — the very\n *    function the Postgres Changes handler uses — then handed to\n *    `store.upsertNote`. A guest and a member therefore converge on one code\n *    path rather than on two implementations that agree until they don't.\n * 2. **Keyed by the row id, so both copies are one thing.** A member receives\n *    every note TWICE. They render once because the id is the row's id on both\n *    transports, and where the two could disagree the database wins\n *    (`store.upsertNote`'s precedence rule, D16).\n * 3. **`matrx.meet.*` is the server's namespace and nothing else's.** LiveKit\n *    does not validate a data packet's sender, so any participant could publish\n *    any bytes under any topic. What makes these trustworthy is that publishing\n *    them requires a `roomAdmin` grant, which only the server's own control\n *    token carries — a participant token cannot claim it. The in-room control\n *    plane participants DO publish (hand, reaction, chat) lives under `mx.*`\n *    and is handled separately, precisely so the two can never be confused.\n */\n\nimport { applyCollabPacket } from \"./collab\";\nimport { projectNote } from \"./repository\";\nimport { effectiveRole, type MeetStore, type RoomChatMessage } from \"./store\";\nimport {\n  asMeetingId,\n  asParticipantIdentity,\n  ROLE_RANK,\n  type JsonObject,\n  type MeetingRecord,\n  type ParticipantRole,\n  type RecordingState,\n  type UserId,\n  type WrapUpAnnouncement,\n} from \"./types\";\n\n/** Pinned against `RecordingState`; an unknown word is dropped, never shown. */\nconst RECORDING_STATES: readonly RecordingState[] = [\n  \"idle\",\n  \"starting\",\n  \"recording\",\n  \"stopping\",\n  \"processing\",\n  \"available\",\n  \"expired\",\n  \"failed\",\n];\n\n/**\n * The server's namespace. Pinned against `aidream/services/meet/livekit.py`'s\n * `ROOM_EVENT_PREFIX` — a rename on either side must break a named test here.\n */\nexport const ROOM_EVENT_PREFIX = \"matrx.meet.\";\n\nexport const ROOM_EVENTS = {\n  /** One durable `meet_notes` row was written. Payload `{ note: <row> }`. */\n  note: \"matrx.meet.note\",\n  /** `meet_meetings.metadata.note_taker` changed. Payload `{ meeting_id, note_taker }`. */\n  noteTaker: \"matrx.meet.note_taker\",\n  /** A wrap-up pass finished. Payload `{ meeting_id, note_ids, segment_count }`. */\n  wrapUp: \"matrx.meet.wrap_up\",\n  /** The meeting ended for everyone. Payload `{ meeting_id, ended_at, trigger }`. */\n  ended: \"matrx.meet.ended\",\n  /**\n   * A chat message to everyone was SAVED (Meet wave 2). Payload\n   * `{ message: { id, meeting_id, sender_identity, sender_name, body, created_at } }`.\n   */\n  chat: \"matrx.meet.chat\",\n  /**\n   * A host or co-host acted (Meet wave 2). Payload `{ meeting_id, kind, … }`:\n   * `muted {source, by}` · `ask-unmute {by}` · `removed {by}` — addressed to the\n   * person concerned; `role {identity, role}` — to everyone.\n   */\n  moderation: \"matrx.meet.moderation\",\n  /**\n   * A meeting ROOM ITEM changed (Meet wave 5): a poll, a Q&A question, a whiteboard\n   * stroke or the breakout plan. Payload `{ meeting_id, item }` · `{ removed: [ids] }` ·\n   * `{ hidden: [ids] }` · `{ cleared: \"whiteboard\" }` · `{ broadcast }` · `{ item, move }`.\n   * A host's fuller copy of a poll or question carries `audience: \"hosts\"`.\n   */\n  collab: \"matrx.meet.collab\",\n} as const;\n\nexport type RoomEventTopic = (typeof ROOM_EVENTS)[keyof typeof ROOM_EVENTS];\n\nexport function isRoomEventTopic(topic: string): boolean {\n  return topic.startsWith(ROOM_EVENT_PREFIX);\n}\n\ntype Payload = Record<string, unknown>;\n\nfunction object(value: unknown): Payload | null {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value)\n    ? (value as Payload)\n    : null;\n}\n\nfunction text(value: unknown): string | null {\n  return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/**\n * What happened to one packet. Returned rather than logged from inside, so the\n * room engine can report a drop with its own diagnostic channel and a test can\n * assert on it — a packet that is silently ignored is indistinguishable from\n * one that never arrived, which is the failure this whole item is about.\n */\nexport interface RoomEventOutcome {\n  readonly handled: boolean;\n  /** Present when `handled` is false. Says what was wrong, in a sentence. */\n  readonly ignored?: string;\n}\n\nconst HANDLED: RoomEventOutcome = { handled: true };\n\nfunction ignored(reason: string): RoomEventOutcome {\n  return { handled: false, ignored: reason };\n}\n\nexport interface ApplyRoomEventArgs {\n  readonly store: MeetStore;\n  readonly topic: string;\n  /** The packet's already-parsed JSON body. */\n  readonly payload: unknown;\n  readonly now?: (() => number) | undefined;\n}\n\n/**\n * Apply one `matrx.meet.*` packet to the store. Never throws.\n *\n * A malformed packet is DROPPED with a reason, never partially applied: half a\n * note on a guest's screen is worse than no note, because the guest cannot tell\n * which half they are missing.\n */\nexport function applyRoomEvent(args: ApplyRoomEventArgs): RoomEventOutcome {\n  const { store, topic } = args;\n  if (!isRoomEventTopic(topic)) {\n    return ignored(`${topic} is not a Meet room event`);\n  }\n  const payload = object(args.payload);\n  if (payload === null) {\n    return ignored(`${topic} carried no object payload`);\n  }\n  const now = args.now ?? (() => Date.now());\n\n  switch (topic) {\n    case ROOM_EVENTS.note:\n      return applyNote(store, payload);\n    case ROOM_EVENTS.noteTaker:\n      return applyNoteTaker(store, payload);\n    case ROOM_EVENTS.wrapUp:\n      return applyWrapUp(store, payload, now);\n    case ROOM_EVENTS.ended:\n      return applyEnded(store, payload);\n    case ROOM_EVENTS.chat:\n      return applyChat(store, payload);\n    case ROOM_EVENTS.moderation:\n      return applyModeration(store, payload, now);\n    case ROOM_EVENTS.collab:\n      return applyCollab(store, payload, now);\n    default:\n      // A NEWER SERVER, not a bug. Ignoring an unknown event under our own\n      // prefix is what lets the platform ship a new one without breaking every\n      // client that has not been redeployed.\n      return ignored(`${topic} is not known to this version of @ai-matrx/meet`);\n  }\n}\n\nfunction applyCollab(store: MeetStore, payload: Payload, now: () => number): RoomEventOutcome {\n  const snapshot = store.snapshot();\n  const meeting = snapshot.meeting;\n  if (meeting !== null && text(payload[\"meeting_id\"]) !== null && payload[\"meeting_id\"] !== meeting.id) {\n    return ignored(\"a collab event for a different meeting than this room is showing\");\n  }\n  const result = applyCollabPacket(snapshot.collab, payload, {\n    localIdentity: snapshot.localIdentity,\n    isHost: ROLE_RANK[effectiveRole(snapshot)] >= ROLE_RANK.cohost,\n    now: now(),\n  });\n  if (result.next === null) return ignored(result.dropped ?? \"a collab packet that changed nothing\");\n  store.patch({ collab: result.next });\n  return HANDLED;\n}\n\nfunction applyNote(store: MeetStore, payload: Payload): RoomEventOutcome {\n  const row = object(payload[\"note\"]);\n  if (row === null) return ignored(\"a note event with no `note` row\");\n  if (text(row[\"id\"]) === null || text(row[\"meeting_id\"]) === null) {\n    // Without the row id there is no dedupe key, and appending a note that can\n    // never be matched to its database copy is exactly the double-render bug.\n    return ignored(\"a note row with no id or meeting_id\");\n  }\n  const meeting = store.snapshot().meeting;\n  if (meeting !== null && row[\"meeting_id\"] !== meeting.id) {\n    return ignored(\"a note for a different meeting than this room is showing\");\n  }\n  try {\n    // THE SAME PROJECTION THE DATABASE PATH USES — one definition of what a\n    // note row means — re-stamped as the room copy so the store's precedence\n    // rule can keep the database's word on top.\n    store.upsertNote({ ...projectNote(row), source: \"room\" });\n  } catch (error) {\n    return ignored(`a note row this client could not read: ${String(error)}`);\n  }\n  return HANDLED;\n}\n\nfunction applyNoteTaker(store: MeetStore, payload: Payload): RoomEventOutcome {\n  const noteTaker = object(payload[\"note_taker\"]);\n  if (noteTaker === null) return ignored(\"a note-taker event with no state\");\n  const meeting = store.snapshot().meeting;\n  if (meeting === null) {\n    // An ad-hoc call room has no meeting record to hang the state on, and\n    // there is no note-taker in one. Stated, not silent.\n    return ignored(\"a note-taker state with no meeting record to attach it to\");\n  }\n  const meetingId = text(payload[\"meeting_id\"]);\n  if (meetingId !== null && meetingId !== meeting.id) {\n    return ignored(\"a note-taker state for a different meeting\");\n  }\n  // MERGED, NOT REPLACED. The packet carries only the `note_taker` object — the\n  // two keys a surface renders — because the rest of the row names people and\n  // organizations a guest is not authorized to learn. Everything else on the\n  // meeting record stays exactly as the join backfill left it.\n  const next: MeetingRecord = {\n    ...meeting,\n    metadata: { ...meeting.metadata, note_taker: noteTaker as JsonObject },\n  };\n  store.patch({ meeting: next });\n  return HANDLED;\n}\n\nfunction applyWrapUp(\n  store: MeetStore,\n  payload: Payload,\n  now: () => number,\n): RoomEventOutcome {\n  const meetingId = text(payload[\"meeting_id\"]);\n  if (meetingId === null) return ignored(\"a wrap-up event with no meeting id\");\n  const meeting = store.snapshot().meeting;\n  if (meeting !== null && meetingId !== meeting.id) {\n    return ignored(\"a wrap-up for a different meeting\");\n  }\n  const rawIds = payload[\"note_ids\"];\n  const noteIds = Array.isArray(rawIds)\n    ? rawIds.filter((value): value is string => typeof value === \"string\")\n    : [];\n  const segmentCount = payload[\"segment_count\"];\n  const announcement: WrapUpAnnouncement = {\n    meetingId: asMeetingId(meetingId),\n    noteIds,\n    segmentCount: typeof segmentCount === \"number\" ? segmentCount : 0,\n    at: new Date(now()).toISOString(),\n  };\n  store.announceWrapUp(announcement);\n  return HANDLED;\n}\n\n/**\n * S8: a recording's state arrives as REPLICATED ROOM STATE (the room's metadata, written only by\n * aidream's `room_state.publish_room_state`), which LiveKit delivers on join and after every\n * reconnect — never a one-shot packet a late joiner misses. Called by the engine's room-metadata\n * handler with the metadata's `recording` object and `meeting_id`.\n */\nexport function applyRecordingState(store: MeetStore, payload: Payload): RoomEventOutcome {\n  const row = object(payload[\"recording\"]);\n  if (row === null) return ignored(\"room state carries no recording\");\n  const meetingId = text(payload[\"meeting_id\"]);\n  const meeting = store.snapshot().meeting;\n  if (meeting !== null && meetingId !== null && meetingId !== meeting.id) {\n    return ignored(\"a recording state for a different meeting than this room is showing\");\n  }\n  const state = text(row[\"state\"]);\n  if (state === null || !RECORDING_STATES.includes(state as RecordingState)) {\n    // An UNKNOWN state is dropped rather than rendered: a recording indicator\n    // that says a word nobody defined is worse than one that says nothing.\n    return ignored(`a recording state this version does not know: ${String(row[\"state\"])}`);\n  }\n  const by = text(row[\"started_by\"]);\n  // `\"room\"` — the durable row outranks this the moment a member's\n  // subscription delivers it (D16, `store.setRecording`).\n  store.setRecording(\n    state as RecordingState,\n    by === null ? null : (by as UserId),\n    \"room\",\n    text(row[\"id\"]),\n  );\n  return HANDLED;\n}\n\nfunction applyEnded(store: MeetStore, payload: Payload): RoomEventOutcome {\n  const meetingId = text(payload[\"meeting_id\"]);\n  const meeting = store.snapshot().meeting;\n  if (meeting === null) return ignored(\"an ended event with no meeting record\");\n  if (meetingId !== null && meetingId !== meeting.id) {\n    return ignored(\"an ended event for a different meeting\");\n  }\n  // 🚨 THE LAST THING A GUEST HEARS. Ending a meeting deletes the LiveKit room,\n  // so the server publishes this in the moment BEFORE the delete — and a client\n  // that ignored it would keep saying the meeting is live while everyone is\n  // disconnected. The `left` phase that follows says nothing about WHY.\n  const endedAt = text(payload[\"ended_at\"]) ?? new Date().toISOString();\n  if (meeting.endedAt === endedAt) return HANDLED;\n  store.patch({ meeting: { ...meeting, endedAt } });\n  return HANDLED;\n}\n\n/** One saved chat row as the room sees it. Shared with the history read. */\nexport function chatFromRow(row: Payload): RoomChatMessage | null {\n  const id = text(row[\"id\"]);\n  const identity = text(row[\"sender_identity\"]);\n  const body = text(row[\"body\"]);\n  if (id === null || identity === null || body === null) return null;\n  return {\n    id,\n    identity: asParticipantIdentity(identity),\n    displayName: text(row[\"sender_name\"]) ?? \"Participant\",\n    text: body,\n    at: text(row[\"created_at\"]) ?? new Date().toISOString(),\n    // `false` only from a server whose chat table has not landed: the room heard\n    // it, nobody will see it later — and the line says so.\n    saved: row[\"saved\"] !== false,\n  };\n}\n\nfunction applyChat(store: MeetStore, payload: Payload): RoomEventOutcome {\n  const row = object(payload[\"message\"]);\n  if (row === null) return ignored(\"a chat event with no `message` row\");\n  const meeting = store.snapshot().meeting;\n  if (meeting !== null && text(row[\"meeting_id\"]) !== null && row[\"meeting_id\"] !== meeting.id) {\n    return ignored(\"a chat message for a different meeting\");\n  }\n  const message = chatFromRow(row);\n  if (message === null) return ignored(\"a chat row with no id, sender or body\");\n  store.addChat(message);\n  return HANDLED;\n}\n\n/** Sentences for what a host did to THIS participant. */\nfunction moderationText(kind: string, payload: Payload): string | null {\n  const by = text(payload[\"by\"]) ?? \"The host\";\n  switch (kind) {\n    case \"muted\": {\n      // Meet names the person who did it (\"<name> muted you\"); the role word only stands in when the server sent no name.\n      const source = text(payload[\"source\"]) ?? \"microphone\";\n      return source === \"microphone\"\n        ? `${by} muted you.`\n        : source === \"camera\"\n          ? `${by} turned off your camera.`\n          : `${by} stopped your screen share.`;\n    }\n    case \"ask-unmute\":\n      return `${by} is asking you to unmute.`;\n    case \"removed\":\n      return `${by} removed you from this meeting.`;\n    default:\n      return null;\n  }\n}\n\nfunction applyModeration(store: MeetStore, payload: Payload, now: () => number): RoomEventOutcome {\n  const snapshot = store.snapshot();\n  const meetingId = text(payload[\"meeting_id\"]);\n  if (snapshot.meeting !== null && meetingId !== null && meetingId !== snapshot.meeting.id) {\n    return ignored(\"a moderation event for a different meeting\");\n  }\n  const kind = text(payload[\"kind\"]);\n  switch (kind) {\n    case \"role\": {\n      const identity = text(payload[\"identity\"]);\n      const role = text(payload[\"role\"]);\n      if (identity === null || role === null || !ROLES.includes(role as ParticipantRole)) {\n        return ignored(\"a role event with no identity or an unknown role\");\n      }\n      // THE SERVER CHANGED ITS OWN DECISION. The token's role was minted at join;\n      // a co-host made or unmade, or a host handed over, must re-grant or\n      // UN-grant this screen's powers now — `effectiveRole` takes the stronger of\n      // token and roster, so a demotion that left the token alone would leave the\n      // old host holding host controls the server refuses.\n      if (identity === snapshot.localIdentity) {\n        store.patch({\n          grants: { ...snapshot.grants, role: role as ParticipantRole },\n          moderationNotice: {\n            kind: \"role\",\n            text:\n              role === \"host\"\n                ? \"You are now the host.\"\n                : role === \"cohost\"\n                  ? \"You are now a co-host.\"\n                  : role === \"presenter\"\n                    ? \"You are now a presenter.\"\n                    : snapshot.grants.role === \"presenter\"\n                      ? \"You are now a participant: you can no longer present.\"\n                      : \"You are no longer a co-host.\",\n            at: now(),\n          },\n        });\n      }\n      return HANDLED;\n    }\n    case \"share-ended\": {\n      // share-takeover / share-who-can: the SERVER took this person's share down and says why.\n      const reason = text(payload[\"reason\"]) === \"not_allowed\" ? \"not_allowed\" : \"replaced\";\n      const by = text(payload[\"by\"]);\n      store.patch({\n        share: { state: \"ended\", reason, remedy: null, at: now(), ...(by !== null ? { by } : {}) },\n      });\n      return HANDLED;\n    }\n    case \"muted\":\n    case \"ask-unmute\":\n    case \"removed\": {\n      const sentence = moderationText(kind, payload);\n      if (sentence === null) return ignored(\"a moderation event with no sentence\");\n      store.patch({\n        moderationNotice: { kind, text: sentence, at: now() },\n        ...(kind === \"muted\" && (text(payload[\"source\"]) ?? \"microphone\") === \"microphone\" ? { mutedByHost: true } : {}),\n      });\n      return HANDLED;\n    }\n    default:\n      return ignored(`a moderation kind this version does not know: ${String(kind)}`);\n  }\n}\n\nconst ROLES: readonly ParticipantRole[] = [\"host\", \"cohost\", \"presenter\", \"participant\", \"viewer\"];\n","/**\n * THE NOTE-TAKER, AS A SURFACE MUST RENDER IT.\n *\n * 🚨 **THE PACKAGE NEVER GUESSES WHAT THE AGENT IS DOING.** Two facts decide\n * everything here and both come from outside this client: the meeting row's\n * `metadata.note_taker` (written by the server with a CAS, MRI-A2/D9) and\n * whether the agent participant is actually in the LiveKit room. A spinner —\n * \"starting…\" held open by a client-side timer — is the exact lie this file\n * exists to prevent: it survives a worker that never came, a dispatch nobody\n * claimed, and a job that died on a release.\n *\n * 🚨 **A REFUSAL IS RENDERED VERBATIM.** `/agent/start` answers a 503 whose body\n * carries `reason` and `remedy` written by the readiness gate (D7) — \"no worker\n * is registered under matrx-note-taker\", \"every worker is at capacity\",\n * \"the fleet is draining\". Those sentences are the truth about the system and\n * they reach the screen unedited. This package adds no sentence of its own on\n * top of one the server already wrote.\n *\n * The agent's identity is DETERMINISTIC — `agent:note_taker:<meeting_id>` (D9) —\n * which is what makes \"is it in the room\" answerable without a round trip, and\n * what makes a second note-taker impossible to mistake for the first.\n */\n\nimport type { JsonObject, MeetParticipant, MeetingRecord, NoteTakerState } from \"./types\";\n\n/** The one spelling of the agent's participant identity (D9). */\nexport const NOTE_TAKER_IDENTITY_PREFIX = \"agent:note_taker:\";\n\nexport function noteTakerIdentity(meetingId: string): string {\n  return `${NOTE_TAKER_IDENTITY_PREFIX}${meetingId}`;\n}\n\n/**\n * The participant attribute the note-taker sets on itself so EVERY client —\n * including one that cannot read the token metadata — knows a notice is owed\n * (D10).\n */\nexport const CONSENT_NOTICE_ATTRIBUTE = \"matrx.agent.consent_notice\";\n\n/** Where the state lives on the meeting row. One spelling, one file. */\nexport const NOTE_TAKER_METADATA_KEY = \"note_taker\";\n\nconst STATES: readonly NoteTakerState[] = [\n  \"absent\",\n  \"joining\",\n  \"transcribing\",\n  \"handoff_pending\",\n  \"ended\",\n];\n\n/** The server's refusal, as it wrote it. Never paraphrased. */\nexport interface NoteTakerRefusal {\n  readonly reason: string;\n  readonly remedy: string;\n  readonly status: number;\n}\n\nexport interface NoteTakerStatus {\n  readonly state: NoteTakerState;\n  /** The server's own words for why it is in this state, when it gave any. */\n  readonly detail: string | null;\n  /** True when the agent participant is in the room RIGHT NOW. */\n  readonly present: boolean;\n  /** The last dispatch refusal, rendered verbatim. */\n  readonly refusal: NoteTakerRefusal | null;\n}\n\nfunction readState(value: unknown): NoteTakerState | null {\n  // The server's `dispatching` (summoned, not yet in the room) reads as `joining` on screen.\n  if (value === \"dispatching\") return \"joining\";\n  return typeof value === \"string\" && STATES.includes(value as NoteTakerState)\n    ? (value as NoteTakerState)\n    : null;\n}\n\n/** Is this participant the note-taker (or any agent that owes a notice, D10)? */\nexport function isNoteTaker(participant: MeetParticipant): boolean {\n  return (\n    participant.identity.startsWith(NOTE_TAKER_IDENTITY_PREFIX) ||\n    participant.attributes[CONSENT_NOTICE_ATTRIBUTE] !== undefined ||\n    participant.isAgent\n  );\n}\n\n/** The agent participant in the room, if any. */\nexport function noteTakerParticipant(\n  participants: readonly MeetParticipant[],\n): MeetParticipant | null {\n  return participants.find(isNoteTaker) ?? null;\n}\n\n/** The exact deterministic actor whose room presence can corroborate the row. */\nfunction exactNoteTakerParticipant(\n  meeting: MeetingRecord | null,\n  participants: readonly MeetParticipant[],\n): MeetParticipant | null {\n  if (meeting === null) return null;\n  const identity = noteTakerIdentity(meeting.id);\n  return participants.find((participant) => participant.identity === identity) ?? null;\n}\n\n/**\n * THE STATE, from the two facts that decide it.\n *\n * The durable row is the authority for work. Exact room presence corroborates\n * only a durable `transcribing` state; an arbitrary agent, a consent marker,\n * or a stale note-taker participant never proves speech capture.\n */\nexport function noteTakerStatus(args: {\n  meeting: MeetingRecord | null;\n  participants: readonly MeetParticipant[];\n  refusal?: NoteTakerRefusal | null;\n}): NoteTakerStatus {\n  const present = exactNoteTakerParticipant(args.meeting, args.participants) !== null;\n  const raw = args.meeting?.metadata?.[NOTE_TAKER_METADATA_KEY];\n  const row: JsonObject =\n    typeof raw === \"object\" && raw !== null && !Array.isArray(raw) ? raw : {};\n  const recorded = readState(row[\"state\"]);\n  const detail = typeof row[\"reason\"] === \"string\" && row[\"reason\"].length > 0\n    ? row[\"reason\"]\n    : null;\n  const refusal = args.refusal ?? null;\n\n  if (recorded === null) {\n    return { state: \"absent\", detail, present, refusal };\n  }\n  if (recorded === \"transcribing\" && !present) {\n    return { state: \"handoff_pending\", detail, present, refusal };\n  }\n  return { state: recorded, detail, present, refusal };\n}\n\n/**\n * THE SENTENCE FOR EACH STATE. One place, so the room, the panel and any future\n * surface say the same true thing — and so a state can never render as a bare\n * enum name.\n */\nexport function noteTakerLabel(status: NoteTakerStatus): string {\n  switch (status.state) {\n    case \"joining\":\n      return \"The note-taker is joining this meeting\";\n    case \"transcribing\":\n      return \"The note-taker is connected and listening for speech\";\n    case \"handoff_pending\":\n      return \"The note-taker's transcription is interrupted; reconnection is pending\";\n    case \"ended\":\n      return \"The note-taker has stopped\";\n    case \"absent\":\n    default:\n      return status.present\n        ? \"A meeting assistant is connected. Transcription is not confirmed\"\n        : \"No note-taker is in this meeting\";\n  }\n}\n","/**\n * THE MEDIA SEAM — the ONE interface the room engine talks to.\n *\n * D1/D2: LiveKit Cloud is the media infrastructure, hardcoded. This interface\n * is NOT a provider abstraction and is not here so a second SFU can be swapped\n * in — it exists for two reasons that are both about correctness:\n *\n * 1. **The engine must be provable without a browser.** Everything expensive in\n *    a calling product (ring timeouts, reconnection, admission, escalation,\n *    speaker tracking) is logic, and logic proven only through a real SFU is\n *    logic that is never proven. `testing/fake-driver.ts` drives every one of\n *    those paths in a node test.\n * 2. **The SDK stays out of the initial chunk.** `livekit-client` is reached\n *    only through a dynamic `import()` inside the default driver, so importing\n *    this package during SSR — or on a page with a call BUTTON but no call —\n *    costs nothing and touches no browser API.\n *\n * The default implementation ships (`createLiveKitDriver`) and is what\n * `<MeetProvider>` uses when a host injects nothing (THE ALL-INCLUSIVE LAW).\n */\n\nimport type { NetworkReading } from \"./network-health\";\nimport type { ConnectionQuality } from \"./types\";\n\n/** A participant as the media layer sees them, before roles or profiles. */\nexport interface DriverParticipant {\n  readonly identity: string;\n  readonly name: string;\n  /** Opaque JSON string the token minted for this participant. */\n  readonly metadata: string | null;\n  /**\n   * The participant's LiveKit attributes. Unlike `metadata` these are set by\n   * the participant itself at run time, which is how the note-taker announces\n   * that a consent notice is owed (D10).\n   */\n  readonly attributes: Readonly<Record<string, string>>;\n  readonly isLocal: boolean;\n  readonly micEnabled: boolean;\n  readonly cameraEnabled: boolean;\n  readonly screenSharing: boolean;\n}\n\nexport type DriverConnectionState =\n  | \"connecting\"\n  | \"connected\"\n  /** Only the signal connection is being re-established; media may still flow. */\n  | \"signal_reconnecting\"\n  | \"reconnecting\"\n  | \"disconnected\";\n\nexport type DriverTrackKind = \"camera\" | \"microphone\" | \"screen\";\n\n/**\n * ONE LIVE CAPTION off the `lk.transcription` text stream.\n *\n * `speakerIdentity` is `lk.transcribed_participant_identity` — WHO IS BEING\n * TRANSCRIBED, not who published the stream (the note-taker publishes every\n * one of them). The SFU-reported publisher identity below is independently\n * checked against the meeting's note-taker; captions remain hints and durable\n * segments remain the record (D16).\n */\nexport interface DriverTranscription {\n  /** `lk.segment_id`. Interim and final share it; that is what makes replacement possible. */\n  readonly segmentId: string;\n  readonly speakerIdentity: string;\n  /**\n   * The LiveKit participant that opened this text stream. Unlike\n   * `speakerIdentity`, this comes from the SFU and is the authority for who\n   * published a caption.\n   */\n  readonly publisherIdentity: string;\n  readonly text: string;\n  /** `lk.transcription_final`. */\n  readonly final: boolean;\n  /** `lk.transcribed_track_id`, when the sender supplied it. */\n  readonly trackId: string | null;\n  readonly at: string;\n}\n\nexport interface RoomDriverHandlers {\n  /** The FULL roster, every time. A delta protocol here drifts; a snapshot cannot. */\n  participants(participants: readonly DriverParticipant[]): void;\n  activeSpeakers(identities: readonly string[]): void;\n  quality(identity: string, quality: ConnectionQuality): void;\n  connectionState(state: DriverConnectionState): void;\n  /** In-room data messages: hand raise, reactions, in-room chat, AI events. */\n  data(topic: string, payload: string, fromIdentity: string | null): void;\n  /** A live caption. Interim and final both arrive here (D16). */\n  transcription(event: DriverTranscription): void;\n  /**\n   * A remote participant left the room, with LiveKit's reason by NAME (`CLIENT_INITIATED`, …) or\n   * null when none was given. Fired BEFORE the roster update that drops them, so an unannounced\n   * departure can be held as a `reconnecting` tile (S6b). Optional for older host drivers.\n   */\n  participantLeft?(identity: string, reason: string | null): void;\n  /** The room ended for this client. `reason` is shown to the user verbatim. */\n  disconnected(reason: string | null): void;\n  /**\n   * The ROOM's metadata — set only by the server (`UpdateRoomMetadata`), and\n   * delivered to every joiner ON JOIN, which is why the spotlight rides it: a\n   * data packet reaches only the people already in the room. Called once after\n   * connect and on every change. Optional so an older host driver still works.\n   */\n  roomMetadata?(metadata: string): void;\n  /**\n   * S6c — MEDIA. Can remote audio play (`false` = the browser's autoplay policy is holding it\n   * until a gesture)? Fired on every change and once right after connect. Optional for older drivers.\n   */\n  audioPlayback?(canPlay: boolean): void;\n  /** S6c — the device list changed (plugged / unplugged), AFTER the SDK re-picked defaults. */\n  devicesChanged?(): void;\n  /** S6c — the SDK could not acquire or keep a local device. `kind` when the SDK knows it. */\n  mediaDeviceError?(error: unknown, kind: \"audioinput\" | \"videoinput\" | null): void;\n  /**\n   * P1 connection-network — one sample of THIS tab's WebRTC path (round trip, loss, relay/TCP),\n   * read from the peer connections' stats every couple of seconds while connected. The rules\n   * that turn samples into what people see are `network-health.ts`. Optional for older drivers.\n   */\n  networkReading?(reading: NetworkReading): void;\n}\n\n/** A camera background effect. `image` replaces the background with `imageUrl`. */\nexport type VideoEffect =\n  | { readonly kind: \"none\" }\n  | { readonly kind: \"blur\"; readonly radius?: number }\n  | { readonly kind: \"image\"; readonly imageUrl: string };\n\n/** Microphone processing the browser applies before anything is sent. */\nexport interface AudioProcessing {\n  readonly noiseSuppression: boolean;\n  readonly echoCancellation: boolean;\n  readonly autoGainControl: boolean;\n}\n\nexport interface MeetRoomDriver {\n  connect(serverUrl: string, token: string): Promise<void>;\n  disconnect(): Promise<void>;\n  setMicrophoneEnabled(enabled: boolean): Promise<void>;\n  setCameraEnabled(enabled: boolean): Promise<void>;\n  setScreenShareEnabled(enabled: boolean): Promise<void>;\n  /**\n   * Reliable, topic-addressed data. The in-room control plane. `to` addresses\n   * named identities only (a private chat message); absent = everyone.\n   */\n  publishData(topic: string, payload: string, to?: readonly string[]): Promise<void>;\n  /**\n   * Apply microphone processing to the live track and to every future one.\n   * Optional: a driver without it makes the control ABSENT, never dead.\n   */\n  setAudioProcessing?(processing: AudioProcessing): Promise<void>;\n  /**\n   * Apply a background effect to the live camera and to every future one.\n   * Rejects with a sentence when this browser cannot run it.\n   */\n  setVideoEffect?(effect: VideoEffect): Promise<void>;\n  /** Whether this browser can run background effects at all. */\n  supportsVideoEffects?(): boolean;\n  /** Whether this browser can share a screen at all (iOS cannot). Absent = assume yes. */\n  supportsScreenShare?(): boolean;\n  /** The screen share being published carries sound (`share-audio`). */\n  screenShareHasAudio?(): boolean;\n  /**\n   * Attach a participant's track to a media element. Returns the detach\n   * function — returning it (rather than exposing `detach`) is what makes a\n   * leaked attachment impossible from the React side: the effect's cleanup IS\n   * the return value.\n   */\n  attach(identity: string, kind: DriverTrackKind, element: HTMLMediaElement): () => void;\n  /** The device the driver actually selected, so the UI never lies about it. */\n  activeDevices(): Readonly<Record<\"audioinput\" | \"videoinput\" | \"audiooutput\", string | null>>;\n  switchDevice(kind: \"audioinput\" | \"videoinput\" | \"audiooutput\", deviceId: string): Promise<void>;\n  /**\n   * S6c — resume remote audio the autoplay policy blocked. MUST run inside the person's click\n   * (the gesture is what the browser checks). Optional: a driver without it never blocks.\n   */\n  startAudio?(): Promise<void>;\n  /**\n   * S7 — a \"join here too\" companion plays no remote audio (the person's other device does; two\n   * speakers in one room echo). `false` removes every attached remote audio element and keeps new\n   * ones from attaching. Optional: a driver without it always plays.\n   */\n  setRemoteAudioPlayback?(enabled: boolean): void;\n}\n\nexport type RoomDriverFactory = (\n  handlers: RoomDriverHandlers,\n) => MeetRoomDriver | Promise<MeetRoomDriver>;\n\n/** Topics for the in-room control plane. One place, so senders cannot drift. */\nexport const DATA_TOPICS = {\n  reaction: \"mx.reaction\",\n  chat: \"mx.chat\",\n} as const;\n\n/**\n * 🚨 `mx.ai.note` and `mx.ai.transcript` WERE declared here and emitted by\n * nothing. They are gone (MRI-A12): the platform's own events are published by\n * the SERVER under `matrx.meet.*` — see `core/room-events.ts` — because a packet\n * a participant could publish is a packet a guest could forge, and these carry\n * durable rows. A participant topic for the same thing would be a second,\n * unauthenticated way to say it.\n */\n\nexport type DataTopic = (typeof DATA_TOPICS)[keyof typeof DATA_TOPICS];\n\n/**\n * THE LIVEKIT TRANSCRIPTION CONTRACT — not ours, so it is written down once\n * rather than spelled inline. The topic and these four attribute names are the\n * SDK's own (`lk.*`); the worker publishes to exactly them (MRI-A2) and a\n * rename on either side must break here, loudly, in one place.\n */\nexport const TRANSCRIPTION_TOPIC = \"lk.transcription\";\n\nexport const TRANSCRIPTION_ATTRIBUTES = {\n  segmentId: \"lk.segment_id\",\n  trackId: \"lk.transcribed_track_id\",\n  final: \"lk.transcription_final\",\n  /**\n   * WHO IS BEING TRANSCRIBED. The LiveKit JS client reports the PUBLISHER of a\n   * text stream, and the publisher is always the note-taker — so a caption\n   * carries the speaker in this attribute and falls back to the publisher only\n   * when it is absent (which attributes the line to the agent, visibly, rather\n   * than to the wrong person, silently).\n   */\n  speakerIdentity: \"lk.transcribed_participant_identity\",\n} as const;\n","/**\n * NETWORK HEALTH (CORE-DESIGN §3.3 CS, P1 connection-network) — the pure rules behind what each\n * person sees when a network degrades. No socket, no timer, no browser global: the driver hands\n * in readings, the engine hands in the clock, and every rule here is provable in a node test.\n *\n * Why the core judges quality itself and does not only repeat LiveKit's `ConnectionQuality`:\n * LiveKit scores a TCP/TURN path with 800 ms of round trip as \"good\" (no packets are lost on\n * TCP — they are just late), and it keeps a participant whose cable was pulled \"good\" for 25 s\n * and more. Google Meet documents media quality degrading at RTT ≥ 300 ms; that is the bar here.\n *\n * Four rules:\n * 1. **Self-assessment** (`createSelfAssessor`): this tab's own path, from its WebRTC stats —\n *    round trip, loss — with hysteresis so the reading does not flap.\n * 2. **The path** (`pathOf`): media relayed over TURN or carried over TCP is a restricted network\n *    (`net-udp-blocked`): the call works, quality may be reduced.\n * 3. **Liveness** (`createLivenessTracker`): every client says \"alive\" on a light data heartbeat\n *    that carries its own reading and whether its video is paused. A person who goes silent past\n *    `staleAfterMs` is shown `reconnecting` to everyone else (`net-others-see-drop`) — long before\n *    the media server gives up on them. A client that never sent a heartbeat (an agent, an older\n *    client) is never judged by it.\n * 4. **Video auto-off** (`createVideoAutoOff`): a poor reading that lasts\n *    `video_auto_off_after_poor_seconds` pauses this person's camera so their audio survives\n *    (`net-video-auto-off`); a person who turns it back on is not paused again until the path has\n *    recovered once.\n */\n\nimport type { ConnectionQuality } from \"./types\";\n\n/* ------------------------------------------------------------------ readings */\n\n/** One sample of this tab's WebRTC path, as the driver read it from `getStats()`. */\nexport interface NetworkReading {\n  /** Selected candidate pair's current round trip (ms), or null when not known. */\n  readonly rttMs: number | null;\n  /** Fraction of packets lost since the previous sample (0..1), or null. */\n  readonly lossRatio: number | null;\n  /** The selected local candidate is a TURN relay. */\n  readonly relayed: boolean | null;\n  /** The selected local candidate carries media over TCP. */\n  readonly tcp: boolean | null;\n}\n\nexport type NetworkPath = \"direct\" | \"restricted\" | \"unknown\";\n\nexport function pathOf(reading: NetworkReading): NetworkPath {\n  if (reading.relayed === null && reading.tcp === null) return \"unknown\";\n  return reading.relayed === true || reading.tcp === true ? \"restricted\" : \"direct\";\n}\n\n/** Google Meet's documented bar: media quality degrades at RTT ≥ 300 ms. */\nexport const POOR_RTT_MS = 300;\n/** Recovery needs clear daylight under the bar, so the reading does not flap at 299/301. */\nexport const RECOVERED_RTT_MS = 220;\nexport const POOR_LOSS = 0.08;\nexport const RECOVERED_LOSS = 0.03;\n\nexport type SelfQuality = \"good\" | \"poor\" | \"unknown\";\n\nexport interface SelfAssessor {\n  /** Fold in one sample; returns the reading after it. */\n  push(reading: NetworkReading): SelfQuality;\n  current(): SelfQuality;\n  reset(): void;\n}\n\n/**\n * Poor after `poorSamples` consecutive bad samples; good again after `goodSamples` consecutive\n * clearly-good ones. A sample with nothing measured changes nothing.\n */\nexport function createSelfAssessor(options: { poorSamples?: number; goodSamples?: number } = {}): SelfAssessor {\n  const poorSamples = options.poorSamples ?? 2;\n  const goodSamples = options.goodSamples ?? 3;\n  let quality: SelfQuality = \"unknown\";\n  let badRun = 0;\n  let goodRun = 0;\n  return {\n    push(reading) {\n      const { rttMs, lossRatio } = reading;\n      if (rttMs === null && lossRatio === null) return quality;\n      const bad = (rttMs !== null && rttMs >= POOR_RTT_MS) || (lossRatio !== null && lossRatio >= POOR_LOSS);\n      const clear =\n        (rttMs === null || rttMs < RECOVERED_RTT_MS) && (lossRatio === null || lossRatio < RECOVERED_LOSS);\n      badRun = bad ? badRun + 1 : 0;\n      goodRun = clear ? goodRun + 1 : 0;\n      if (badRun >= poorSamples) quality = \"poor\";\n      else if (quality !== \"poor\" && !bad) quality = \"good\";\n      else if (quality === \"poor\" && goodRun >= goodSamples) quality = \"good\";\n      return quality;\n    },\n    current: () => quality,\n    reset() {\n      quality = \"unknown\";\n      badRun = 0;\n      goodRun = 0;\n    },\n  };\n}\n\n/* ------------------------------------------------------------------ combining */\n\nconst RANK: Record<ConnectionQuality, number> = {\n  lost: 0,\n  poor: 1,\n  good: 2,\n  excellent: 3,\n  unknown: 4,\n};\n\n/** The worse of two readings; `unknown` never wins over a real one. */\nexport function worstQuality(a: ConnectionQuality, b: ConnectionQuality | SelfQuality | null | undefined): ConnectionQuality {\n  if (b === null || b === undefined || b === \"unknown\") return a;\n  if (a === \"unknown\") return b;\n  return RANK[b] < RANK[a] ? b : a;\n}\n\n/* ------------------------------------------------------------------ heartbeat */\n\n/** The participant data topic the heartbeat rides (lossy-tolerant, tiny). */\nexport const ALIVE_TOPIC = \"mx.alive\";\n\nexport interface AliveBeat {\n  /** The sender's own path reading. */\n  readonly q: SelfQuality;\n  /** The sender's camera is paused by the network (auto-off), not by their choice. */\n  readonly vp: boolean;\n}\n\nexport function encodeBeat(beat: AliveBeat): string {\n  return JSON.stringify({ q: beat.q, vp: beat.vp });\n}\n\n/** A deliberate Leave, said on the heartbeat so nobody holds a `reconnecting` tile for it. */\nexport function encodeBye(): string {\n  return JSON.stringify({ bye: true });\n}\n\nexport function isBye(payload: string): boolean {\n  try {\n    return (JSON.parse(payload) as { bye?: unknown }).bye === true;\n  } catch {\n    return false;\n  }\n}\n\nexport function decodeBeat(payload: string): AliveBeat | null {\n  try {\n    const raw = JSON.parse(payload) as { q?: unknown; vp?: unknown };\n    const q = raw.q === \"good\" || raw.q === \"poor\" ? raw.q : \"unknown\";\n    return { q, vp: raw.vp === true };\n  } catch {\n    return null;\n  }\n}\n\n/**\n * How often to beat. 2 s up to 25 people, then slower in proportion, so a 500-person room costs\n * every client about the same packets per second as a 25-person one.\n */\nexport function heartbeatIntervalMs(roomSize: number): number {\n  return 2000 * Math.max(1, Math.ceil(Math.max(1, roomSize) / 25));\n}\n\n/** Silent this long = shown reconnecting: three missed beats and a second of slack (7 s small). */\nexport function staleAfterMs(roomSize: number): number {\n  return heartbeatIntervalMs(roomSize) * 3 + 1000;\n}\n\n/** Never heard since they appeared this long = silent (14 s small): twice the stale window. */\nexport function firstBeatAllowanceMs(roomSize: number): number {\n  return staleAfterMs(roomSize) * 2;\n}\n\nexport interface LivenessTracker {\n  /** A beat (or any packet) arrived from `who`. */\n  heard(who: string, beat: AliveBeat | null): void;\n  /**\n   * `who` is in the room and runs this package, so it will beat. Starts their clock without a beat:\n   * someone cut before their FIRST beat reaches us is still noticed (`net-others-see-drop`), after\n   * `firstBeatAllowanceMs` — a newcomer's data channel can take seconds to open. Never call it for\n   * a participant that does not beat (an agent).\n   */\n  expect(who: string): void;\n  /**\n   * People who are silent: beat once and quiet past `staleAfterMs(roomSize)`, or expected and never\n   * heard past `firstBeatAllowanceMs(roomSize)`.\n   */\n  stale(present: readonly string[], roomSize: number): Set<string>;\n  /** The last reading `who` sent about their own path, or null. */\n  reported(who: string): AliveBeat | null;\n  /** This tab was itself cut off: everyone gets a fresh start from now (no false ghosts). */\n  restartClock(): void;\n  forget(who: string): void;\n  clear(): void;\n}\n\nexport function createLivenessTracker(now: () => number): LivenessTracker {\n  const lastHeard = new Map<string, number>();\n  /** Expected to beat, not heard yet: when they appeared. */\n  const firstSeen = new Map<string, number>();\n  const beats = new Map<string, AliveBeat>();\n  return {\n    heard(who, beat) {\n      lastHeard.set(who, now());\n      firstSeen.delete(who);\n      if (beat !== null) beats.set(who, beat);\n    },\n    expect(who) {\n      if (!lastHeard.has(who) && !firstSeen.has(who)) firstSeen.set(who, now());\n    },\n    stale(present, roomSize) {\n      const limit = staleAfterMs(roomSize);\n      const firstLimit = firstBeatAllowanceMs(roomSize);\n      const at = now();\n      const out = new Set<string>();\n      for (const who of present) {\n        const heard = lastHeard.get(who);\n        if (heard !== undefined) {\n          if (at - heard > limit) out.add(who);\n          continue;\n        }\n        const seen = firstSeen.get(who);\n        if (seen !== undefined && at - seen > firstLimit) out.add(who);\n      }\n      return out;\n    },\n    reported: (who) => beats.get(who) ?? null,\n    restartClock() {\n      const at = now();\n      for (const who of lastHeard.keys()) lastHeard.set(who, at);\n      for (const who of firstSeen.keys()) firstSeen.set(who, at);\n    },\n    forget(who) {\n      lastHeard.delete(who);\n      firstSeen.delete(who);\n      beats.delete(who);\n    },\n    clear() {\n      lastHeard.clear();\n      firstSeen.clear();\n      beats.clear();\n    },\n  };\n}\n\n/* ------------------------------------------------------------------ video auto-off */\n\nexport interface VideoAutoOff {\n  /**\n   * One step with the current reading and whether the camera is on. Returns `\"pause\"` exactly\n   * once when the camera should be paused for the network.\n   */\n  step(quality: SelfQuality, cameraOn: boolean): \"pause\" | null;\n  /** The person turned their video back on themselves: no auto-pause until the path recovers. */\n  retried(): void;\n  reset(): void;\n}\n\n/** `afterMs` ≤ 0 = the knob is off: never pause. */\nexport function createVideoAutoOff(afterMs: () => number, now: () => number): VideoAutoOff {\n  let poorSince: number | null = null;\n  let armed = true;\n  return {\n    step(quality, cameraOn) {\n      if (quality === \"good\") {\n        poorSince = null;\n        armed = true;\n        return null;\n      }\n      if (quality !== \"poor\" || !cameraOn) {\n        poorSince = quality === \"poor\" ? poorSince : null;\n        return null;\n      }\n      const at = now();\n      if (poorSince === null) poorSince = at;\n      const limit = afterMs();\n      if (!armed || limit <= 0 || at - poorSince < limit) return null;\n      armed = false;\n      return \"pause\";\n    },\n    retried() {\n      armed = false;\n    },\n    reset() {\n      poorSince = null;\n      armed = true;\n    },\n  };\n}\n\n/* ------------------------------------------------------------------ stats → reading */\n\n/** The few `RTCStats` fields the reading needs (structural: no DOM types in the core). */\nexport interface StatsEntry {\n  readonly id: string;\n  readonly type: string;\n  readonly [field: string]: unknown;\n}\n\n/**\n * One reading from a peer connection's `getStats()` entries: the SELECTED candidate pair (the\n * transport's `selectedCandidatePairId`, else the nominated succeeded pair), its round trip, its\n * local candidate's type and protocol, and the worst `fractionLost` the far end reported.\n */\nexport function readingFromStats(entries: Iterable<StatsEntry>): NetworkReading {\n  const byId = new Map<string, StatsEntry>();\n  for (const entry of entries) byId.set(entry.id, entry);\n  let pair: StatsEntry | undefined;\n  for (const entry of byId.values()) {\n    if (entry.type === \"transport\" && typeof entry[\"selectedCandidatePairId\"] === \"string\") {\n      pair = byId.get(entry[\"selectedCandidatePairId\"] as string);\n      if (pair !== undefined) break;\n    }\n  }\n  if (pair === undefined) {\n    for (const entry of byId.values()) {\n      if (entry.type === \"candidate-pair\" && entry[\"nominated\"] === true && entry[\"state\"] === \"succeeded\") {\n        pair = entry;\n        break;\n      }\n    }\n  }\n  let lossRatio: number | null = null;\n  for (const entry of byId.values()) {\n    if (entry.type === \"remote-inbound-rtp\" && typeof entry[\"fractionLost\"] === \"number\") {\n      lossRatio = Math.max(lossRatio ?? 0, entry[\"fractionLost\"] as number);\n    }\n  }\n  if (pair === undefined) return { rttMs: null, lossRatio, relayed: null, tcp: null };\n  const rtt = pair[\"currentRoundTripTime\"];\n  const local = typeof pair[\"localCandidateId\"] === \"string\" ? byId.get(pair[\"localCandidateId\"] as string) : undefined;\n  const candidateType = local?.[\"candidateType\"];\n  const protocol = local?.[\"protocol\"];\n  const relayProtocol = local?.[\"relayProtocol\"];\n  return {\n    rttMs: typeof rtt === \"number\" ? Math.round(rtt * 1000) : null,\n    lossRatio,\n    relayed: typeof candidateType === \"string\" ? candidateType === \"relay\" : null,\n    tcp:\n      typeof protocol === \"string\" || typeof relayProtocol === \"string\"\n        ? protocol === \"tcp\" || relayProtocol === \"tcp\" || relayProtocol === \"tls\"\n        : null,\n  };\n}\n\n/** Two transports (publisher, subscriber) → one reading: the worse round trip and loss, either path restricted. */\nexport function mergeReadings(readings: readonly NetworkReading[]): NetworkReading {\n  const max = (values: (number | null)[]): number | null => {\n    const known = values.filter((v): v is number => v !== null);\n    return known.length === 0 ? null : Math.max(...known);\n  };\n  const any = (values: (boolean | null)[]): boolean | null =>\n    values.every((v) => v === null) ? null : values.some((v) => v === true);\n  return {\n    rttMs: max(readings.map((r) => r.rttMs)),\n    lossRatio: max(readings.map((r) => r.lossRatio)),\n    relayed: any(readings.map((r) => r.relayed)),\n    tcp: any(readings.map((r) => r.tcp)),\n  };\n}\n","/**\n * THE ROOM ENGINE — the object a host mounts once and never reasons about.\n *\n * It owns every sequence a calling product gets wrong: ask for a token, connect,\n * project the roster, carry the in-room control plane, keep the phase honest\n * through a reconnect, and tear everything down exactly once. A consumer's job\n * is `engine.join(...)` and rendering a snapshot.\n *\n * THREE rules are structural here, not documented-and-hoped:\n *\n * 1. **The phase never lies.** `connecting` becomes `connected` only when the\n *    driver says so, and any failure becomes `failed` WITH the remedy attached\n *    to the snapshot. There is no path that leaves a spinner running forever —\n *    the single most common complaint about every video product.\n * 2. **Role comes from the TOKEN, never from the client.** A participant's role\n *    is read out of the server-minted metadata. A client that could decide it\n *    was host could mute anyone; here the claim is unforgeable because the\n *    server signed it.\n * 3. **Teardown is idempotent and total.** Leaving twice, or unmounting during\n *    a connect, disconnects once and leaves no listener behind. The half-torn\n *    room is what produces \"my camera light stays on after the call\".\n */\n\nimport {\n  IDLE_TRACK,\n  type LocalTrackState,\n} from \"./attendance\";\nimport { detectCapabilities } from \"./capabilities\";\nimport { createMediaSupervisor, type MediaPlatform, webMediaPlatform } from \"./media-supervisor\";\nimport {\n  classifyScreenShareError,\n  MeetError,\n  normalizeDeviceError,\n  normalizeMeetError,\n  normalizeScreenShareError,\n  SCREEN_SHARE_BLOCKED_REMEDY,\n} from \"./errors\";\n\n/** A system/policy block: the error's own remedy when it names one (policy), else the system one. */\nfunction SCREEN_SHARE_BLOCKED_REMEDY_FOR(remedy: string): string {\n  return /administrator|policy/i.test(remedy) ? remedy : SCREEN_SHARE_BLOCKED_REMEDY;\n}\nimport { applyRecordingState, applyRoomEvent, isRoomEventTopic, ROOM_EVENTS } from \"./room-events\";\nimport { displayNameFor, isGuestIdentity, personOf, userIdOfIdentity } from \"./names\";\nimport type { TabClaim } from \"./tab-claim\";\nimport { noteTakerIdentity } from \"./note-taker\";\nimport { captionSegment } from \"./transcript\";\nimport {\n  DATA_TOPICS,\n  type DriverParticipant,\n  type MeetRoomDriver,\n  type RoomDriverFactory,\n  type RoomDriverHandlers,\n  type VideoEffect,\n} from \"./room-driver\";\nimport { type MediaEffects, type MeetStore, NO_SHARE, UNKNOWN_LOCAL_NETWORK, type LocalNetwork } from \"./store\";\nimport {\n  ALIVE_TOPIC,\n  createLivenessTracker,\n  createSelfAssessor,\n  createVideoAutoOff,\n  decodeBeat,\n  encodeBeat,\n  encodeBye,\n  isBye,\n  heartbeatIntervalMs,\n  pathOf,\n  worstQuality,\n} from \"./network-health\";\nimport { resolveExit, type ExitServerWord } from \"./phase\";\nimport {\n  createConnectionSupervisor,\n  createWebNetworkPort,\n  DEFAULT_CONNECTION_POLICY,\n  isUnannouncedDeparture,\n  mergeGhosts,\n  type ConnectionPolicy,\n  type Ghost,\n  type NetworkPort,\n  type ResumeStorage,\n} from \"./connection-supervisor\";\nimport type { RoomToken, SecondDeviceAnswer, TokenClient } from \"./tokens\";\nimport {\n  asParticipantIdentity,\n  isHostRole,\n  type CallMode,\n  type ConnectionQuality,\n  type MeetIdentity,\n  type MeetingRecord,\n  type MeetParticipant,\n  type ParticipantIdentity,\n  type ParticipantRole,\n  type ParticipantStanding,\n  type RoomName,\n  type StageLayout,\n  asUserId,\n  type UserId,\n} from \"./types\";\n\nexport interface JoinRequest {\n  readonly roomName: RoomName;\n  readonly meetingId?: string | undefined;\n  readonly slug?: string | undefined;\n  /** `audio` joins with the camera off. Same room, same code path (D3). */\n  readonly mode: CallMode;\n  /**\n   * Whether to ATTEMPT the microphone on join. Defaults to true. `false` is a\n   * deliberate listen-only join — the pre-join screen's \"Join with microphone\"\n   * toggle. Either way the join itself never depends on the outcome; a refused\n   * device lands in `snapshot.media.microphone.unavailable`, not in a throw.\n   */\n  readonly microphone?: boolean | undefined;\n  /** Meet wave 5: a breakout room of this meeting; absent/null = the main room. */\n  readonly breakoutRoomId?: string | null | undefined;\n  /** HR-360 wave 2 (MD-16): ask to join as a silent observer. The server decides. */\n  readonly observe?: boolean | undefined;\n  /**\n   * S7: the person's answer when they are already in this meeting on another tab or device\n   * (`snapshot.secondDevice`): `switch_here` moves the call here, `join_too` adds this tab as a\n   * companion (no microphone, speaker off).\n   */\n  readonly secondDevice?: SecondDeviceAnswer | undefined;\n}\n\nexport interface RoomEngineOptions {\n  store: MeetStore;\n  tokens: TokenClient;\n  identity: MeetIdentity;\n  driverFactory: RoomDriverFactory;\n  /** S7: this page's tab claim (`core/tab-claim.ts`); absent = one connection per person. */\n  tabClaim?: TabClaim | undefined;\n  /** Canonical public metadata read; room packets alone never authorize teardown. */\n  resolveMeeting?: ((slug: string) => Promise<MeetingRecord>) | undefined;\n  onDiagnostic?: ((event: { level: \"info\" | \"warn\" | \"error\"; message: string; remedy?: string }) => void) | undefined;\n  /** Fired when the local participant leaves for any reason, including kicked. */\n  onLeft?: ((reason: string | null) => void) | undefined;\n  now?: (() => number) | undefined;\n  /** Remembered noise suppression / background choice (Meet wave 2). */\n  effectsStorage?: EffectsStorage | undefined;\n  /**\n   * The device the person PICKED for each kind (the pre-join pickers, the\n   * settings panel). Applied before any track is created — through 0.7.x the\n   * pickers stored a choice nothing ever read, so every join used the browser\n   * default whatever the screen said.\n   */\n  resolveDevice?: ((kind: \"audioinput\" | \"videoinput\" | \"audiooutput\") => string | null) | undefined;\n  /**\n   * §3.4 EXIT-REASON RESOLUTION: on every LiveKit disconnect the engine asks the server's state\n   * read what happened to THIS connection (`GET /v1/meet/state?connection=`). Resolves null when\n   * the read failed (offline / unreachable), undefined when this room has no state read (a call).\n   */\n  readExit?: ((connection: string, pass?: string | null) => Promise<ExitServerWord | null | undefined>) | undefined;\n  /** Was the page frozen when the connection dropped (Page Lifecycle)? → `inactive`. */\n  wasFrozen?: (() => boolean) | undefined;\n  /**\n   * S6b — the connection supervisor's ports. `network` = does the device have a network\n   * (default: `navigator.onLine`); `probe` = do our API and the media server answer (default:\n   * assume yes); `resume` = per-tab storage for the reload-after-offline marker (default: none).\n   */\n  /**\n   * S6c — the media supervisor's platform port (permissions, device list, visibility). Default:\n   * the browser's (`webMediaPlatform()`); `null` turns the supervisor's browser reads off.\n   */\n  mediaPlatform?: MediaPlatform | null | undefined;\n  connection?: {\n    readonly network?: NetworkPort | undefined;\n    readonly probe?: ((serverUrl: string | null) => Promise<boolean>) | undefined;\n    readonly resume?: ResumeStorage | undefined;\n  } | undefined;\n}\n\nexport interface RoomEngine {\n  join(request: JoinRequest): Promise<void>;\n  /**\n   * 🚨 THE HOST SAID YES — COME IN.\n   *\n   * A lobby token is minted with `canPublish: false` and `canSubscribe: false`\n   * (that is what makes the lobby real rather than a screen over a live\n   * microphone), so admission is not a UI state change: the cached token has to\n   * be thrown away and a NEW one minted with the grants the server now gives.\n   * Without this the waiting room's own sentence — \"you will join automatically\n   * once you are admitted\" — is a lie, and the guest waits forever.\n   */\n  rejoin(): Promise<void>;\n  /**\n   * S6b: rejoin BY ITSELF from `disconnected` (the connection supervisor calls this once the\n   * network and our servers answer). A fresh mint into the same identity: the server restores\n   * role, hand and admission from the person row.\n   */\n  autoRejoin(): Promise<void>;\n  /**\n   * S6b: this tab was in (or dropped from) the call before the page reloaded — Chrome's offline\n   * page reloading, a refresh. Returns true when it went straight back to joining (from\n   * `resolving`), false when there is nothing fresh to resume (the caller resolves as usual).\n   */\n  resume(roomName: RoomName): boolean;\n  /**\n   * Meet wave 5: go to a breakout room (`null` = back to the main room). The server\n   * mints the pass (`/token` with `breakout_room_id`) and refuses a room the plan does\n   * not allow; the move is a reconnect that never reads as leaving the meeting.\n   */\n  moveToBreakout(roomId: string | null): Promise<void>;\n  leave(): Promise<void>;\n  /** The person's own \"back to the device check\" press from `left` / `disconnected`. */\n  backToPrejoin(): void;\n  /**\n   * S7: BEFORE Join — is this person already live in `roomName` on another tab of THIS browser\n   * (`TabClaim.presentElsewhere`)? When yes the pre-join offers Switch here / Join here too up\n   * front (the same choice the server would otherwise ask after the press). Returns whether it did.\n   * A guest has no stable person key before the pass, so the server's own answer covers them.\n   */\n  checkElsewhere(roomName: RoomName): Promise<boolean>;\n  /** Clear a refused-share notice (the `share` region) the person dismissed. */\n  dismissShareNotice(): void;\n  setMicrophoneEnabled(enabled: boolean): Promise<void>;\n  setCameraEnabled(enabled: boolean): Promise<void>;\n  setScreenShareEnabled(enabled: boolean): Promise<void>;\n  react(emoji: string): Promise<void>;\n  /**\n   * A PRIVATE message to one person (Meet wave 2). Data plane only, addressed\n   * to that identity, NEVER saved — see `core/chat.ts` for the saved,\n   * everyone-chat, which goes through the server.\n   */\n  sendPrivateChat(to: ParticipantIdentity, text: string): Promise<void>;\n  /**\n   * Change this participant's own media processing — noise suppression and the\n   * camera background — on the live tracks, and remember it in this browser.\n   * A refused effect is a diagnostic and a revert, never a lost camera.\n   */\n  setEffects(next: Partial<MediaEffects>): Promise<void>;\n  /** Whether this browser can run a background effect at all (absent, never dead). */\n  supportsVideoEffects(): boolean;\n  /** Whether this browser can share a screen at all — the control is ABSENT where it cannot. */\n  supportsScreenShare(): boolean;\n  /** S6c: \"Enable sound\" — resume remote audio the autoplay policy holds. Call inside the click. */\n  enableAudio(): Promise<void>;\n  /** S6c: switch to the device the supervisor offered (a new one was plugged in). */\n  /** The pre-join preview's outcome for one kind (the media supervisor classifies a refusal). */\n  previewDevice(kind: \"microphone\" | \"camera\", outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }): Promise<void>;\n  acceptDeviceOffer(): Promise<void>;\n  dismissDeviceOffer(): void;\n  dismissDeviceNotice(): void;\n  undoDeviceNotice(): Promise<void>;\n  /** Choose the speaker (audio output) for this meeting. */\n  switchDevice(kind: \"audioinput\" | \"videoinput\" | \"audiooutput\", deviceId: string): Promise<void>;\n  pin(identity: ParticipantIdentity | null): void;\n  setLayout(layout: StageLayout): void;\n  attach(\n    identity: ParticipantIdentity,\n    kind: \"camera\" | \"microphone\" | \"screen\",\n    element: HTMLMediaElement,\n  ): () => void;\n  token(): RoomToken | null;\n  dispose(): Promise<void>;\n}\n\n/** Where this browser keeps a participant's media choices. */\nexport interface EffectsStorage {\n  load(): MediaEffects;\n  save(effects: MediaEffects): void;\n}\n\n/** What the server puts in the token's participant metadata. */\ninterface ParticipantMetadata {\n  readonly user_id?: string;\n  readonly role?: string;\n  readonly can_record?: boolean;\n  readonly is_agent?: boolean;\n  readonly avatar_url?: string;\n}\n\n/**\n * 🚨 THE SERVER'S WORD, ON TWO CARRIERS (MRI-A11, feedback `7418ef78`).\n *\n * aidream mints the role into the token's participant METADATA (a JSON blob)\n * AND as a LiveKit participant ATTRIBUTE. Both come out of one decision in\n * `services/meet/service.py`; neither can be written by a client. The attribute\n * is preferred because LiveKit delivers the attribute map on every roster\n * update, while a roster event can carry an empty metadata string — which is\n * precisely how, through 2026-09-08, EVERY participant projected as\n * \"participant\" and no host ever saw a host control in a browser.\n *\n * These strings are pinned on the server side too: `test_meet_service.py` reads\n * them out of THIS file and fails if the two sides drift.\n */\nexport const PARTICIPANT_ROLE_ATTRIBUTE = \"matrx.participant.role\";\n/** S8: the server's raise time of a hand (epoch ms), \"\" when down. Pinned with aidream's `room_state.ATTRIBUTE_HAND`. */\nexport const PARTICIPANT_HAND_ATTRIBUTE = \"matrx.hand\";\n\nfunction handFrom(value: string | undefined): { handRaised: boolean; handRaisedAt: number | null } {\n  const at = value === undefined || value.length === 0 ? Number.NaN : Number(value);\n  return Number.isFinite(at) ? { handRaised: true, handRaisedAt: at } : { handRaised: false, handRaisedAt: null };\n}\nexport const PARTICIPANT_CAN_RECORD_ATTRIBUTE = \"matrx.participant.can_record\";\n/** S7: `main` or `companion` (a \"join here too\" connection) — `config.py::ATTRIBUTE_CONNECTION_KIND`. */\nexport const CONNECTION_KIND_ATTRIBUTE = \"matrx.participant.connection_kind\";\n/** Standing travels beside the role (CORE-DESIGN §2.1). Pinned by aidream's tests too. */\nexport const PARTICIPANT_STANDING_ATTRIBUTE = \"matrx.participant.standing\";\n\nconst KNOWN_STANDINGS: readonly ParticipantStanding[] = [\"member\", \"invited\", \"outsider\", \"guest\"];\n\nfunction parseStanding(value: unknown): ParticipantStanding | null {\n  return KNOWN_STANDINGS.includes(value as ParticipantStanding) ? (value as ParticipantStanding) : null;\n}\n\nconst KNOWN_ROLES: readonly ParticipantRole[] = [\"host\", \"cohost\", \"presenter\", \"participant\", \"viewer\"];\n\n/**\n * An unrecognized role is `participant` — never `host`. A word this package\n * does not know is a server that is ahead of it, and the safe reading of an\n * unknown claim is the one that grants nothing.\n */\nfunction parseRole(value: string | undefined): ParticipantRole {\n  return KNOWN_ROLES.includes(value as ParticipantRole) ? (value as ParticipantRole) : \"participant\";\n}\n\n/**\n * Metadata is SERVER-MINTED and therefore trusted; it is still parsed\n * defensively, because a malformed blob must degrade a tile to \"participant\"\n * rather than throw inside a roster event and freeze the whole grid.\n */\nexport function projectParticipant(\n  driver: DriverParticipant,\n  joinedAt: string,\n): MeetParticipant {\n  let metadata: ParticipantMetadata = {};\n  if (driver.metadata !== null && driver.metadata.length > 0) {\n    try {\n      const parsed: unknown = JSON.parse(driver.metadata);\n      if (typeof parsed === \"object\" && parsed !== null) {\n        metadata = parsed as ParticipantMetadata;\n      }\n    } catch {\n      metadata = {};\n    }\n  }\n  const userId = typeof metadata.user_id === \"string\" ? asUserId(metadata.user_id) : null;\n  return {\n    // S7: a tile is a PERSON; LiveKit names the tab's connection (`<person>~<tab>`).\n    identity: personOf(driver.identity),\n    userId,\n    // 🚨 A RAW LIVEKIT IDENTITY IS NEVER A NAME (MRI-A18). Through 0.4.12 this\n    // line read `driver.name.length > 0 ? driver.name : driver.identity`, and\n    // that single fallback put `guest:v-spk-1` on the participant strip, the\n    // People panel, the meeting header and every Pin/Mute aria-label, in BOTH\n    // lanes — inside the very structure `core/names.ts` is taught from. A\n    // nameless tile is still a bug report nobody can action, so the fallback\n    // stays; it is now the name book's HONEST placeholder (\"Unnamed guest\", or\n    // the agent's product name) instead of the token. `store.setParticipants`\n    // then upgrades this to the best name anything has ever learned.\n    displayName: displayNameFor({}, driver.identity, driver.name),\n    avatarUrl: typeof metadata.avatar_url === \"string\" ? metadata.avatar_url : null,\n    // ATTRIBUTE FIRST, metadata second — see the constants above. Both are the\n    // server's; the attribute is simply the one that always arrives.\n    role: parseRole(driver.attributes[PARTICIPANT_ROLE_ATTRIBUTE] ?? metadata.role),\n    standing: parseStanding(\n      driver.attributes[PARTICIPANT_STANDING_ATTRIBUTE] ??\n        (metadata as { standing?: unknown }).standing,\n    ),\n    canRecord:\n      driver.attributes[PARTICIPANT_CAN_RECORD_ATTRIBUTE] === \"true\" ||\n      metadata.can_record === true,\n    isLocal: driver.isLocal,\n    isAgent: metadata.is_agent === true,\n    attributes: driver.attributes,\n    micEnabled: driver.micEnabled,\n    cameraEnabled: driver.cameraEnabled,\n    screenSharing: driver.screenSharing,\n    speaking: false,\n    // S8: a hand is the SERVER's (`hand_raised_at` on the person row, `/moderate raise_hand`),\n    // replicated as the `matrx.hand` attribute: epoch ms of the raise, \"\" when down. It is\n    // therefore delivered to late joiners and survives refresh and reconnect.\n    ...handFrom(driver.attributes[PARTICIPANT_HAND_ATTRIBUTE]),\n    quality: \"unknown\",\n    joinedAt,\n  };\n}\n\ninterface DataEnvelope {\n  readonly id?: string;\n  readonly at?: string;\n  /** Epoch ms a hand went up — the queue's order. */\n  readonly raisedAt?: number;\n  /** A private chat message's addressee. */\n  readonly to?: string;\n  readonly raised?: boolean;\n  readonly emoji?: string;\n  readonly text?: string;\n  readonly name?: string;\n}\n\nexport function createRoomEngine(options: RoomEngineOptions): RoomEngine {\n  const { store, tokens, identity } = options;\n  const now = options.now ?? (() => Date.now());\n  let driver: MeetRoomDriver | null = null;\n  let current: RoomToken | null = null;\n  let joining: Promise<void> | null = null;\n  // The request this engine last joined with, so an admitted guest can be let\n  // in without the surface having to remember how it got here.\n  let lastRequest: JoinRequest | null = null;\n  let disposed = false;\n  // True while a breakout move tears down one room to connect the next: that\n  // disconnect is not the person leaving the meeting.\n  let moving = false;\n  const confirmingEnds = new WeakSet<MeetRoomDriver>();\n  /** The media server of the last mint — what the probe asks after the room is gone. */\n  let lastServerUrl: string | null = null;\n  /** The meeting's connection knobs, from the last mint (S6b). */\n  let connectionPolicy: ConnectionPolicy = DEFAULT_CONNECTION_POLICY;\n  /** Remote people who dropped without leaving, held as `reconnecting` tiles (S6b). */\n  let ghosts = new Map<string, Ghost>();\n  let ghostTimer: ReturnType<typeof setTimeout> | null = null;\n  /** The last LIVE roster the driver reported, so an expiring ghost can re-project it. */\n  let liveRoster: readonly DriverParticipant[] = [];\n  /** S7: person key → every LiveKit connection they hold, and the one their tile shows. */\n  let personConnections = new Map<string, string[]>();\n  let mainConnection = new Map<string, string>();\n  function connectionsOf(who: string): string[] {\n    return personConnections.get(personOf(who)) ?? [who];\n  }\n  /** Departures LiveKit announced since the last roster: identity → reason name. */\n  const departures = new Map<string, string | null>();\n\n  /* P1 connection-network (`network-health.ts`): this tab's own path, and everyone's heartbeat. */\n  const liveness = createLivenessTracker(now);\n  const assessor = createSelfAssessor();\n  const autoOff = createVideoAutoOff(() => connectionPolicy.videoAutoOffAfterPoorSeconds * 1000, now);\n  /** LiveKit's own quality per PERSON — combined with the self-reported reading, never replaced. */\n  const lkQuality = new Map<string, ConnectionQuality>();\n  /** Connections that beat before and went silent: shown `reconnecting` to everyone here. */\n  let silent = new Set<string>();\n  /** Connections that announced a deliberate Leave on the heartbeat. */\n  const saidBye = new Set<string>();\n  let healthTimer: ReturnType<typeof setInterval> | null = null;\n  let lastBeatAt = 0;\n  let wasUnstable = false;\n\n  function patchLocalNetwork(next: Partial<LocalNetwork>): void {\n    const before = store.snapshot().localNetwork;\n    const merged = { ...before, ...next };\n    if (merged.path !== before.path || merged.quality !== before.quality || merged.videoPaused !== before.videoPaused) {\n      store.patch({ localNetwork: merged });\n    }\n  }\n\n  /** What a person's tile says about their connection: the worse of LiveKit's and their own word. */\n  function effectiveQuality(person: string, connection: string | undefined, isLocal: boolean): ConnectionQuality {\n    const fromServer = lkQuality.get(person) ?? \"unknown\";\n    if (isLocal) return worstQuality(fromServer, assessor.current());\n    return worstQuality(fromServer, connection === undefined ? null : liveness.reported(connection)?.q);\n  }\n\n  function refreshQualities(): void {\n    const snap = store.snapshot();\n    for (const p of snap.participants) {\n      if (p.reconnecting === true) continue;\n      const next = effectiveQuality(p.identity, mainConnection.get(p.identity), p.isLocal);\n      if (next !== \"unknown\" && next !== p.quality) store.setQuality(p.identity, next);\n    }\n  }\n\n  function stopHealth(): void {\n    if (healthTimer !== null) clearInterval(healthTimer);\n    healthTimer = null;\n    liveness.clear();\n    assessor.reset();\n    autoOff.reset();\n    silent = new Set();\n    saidBye.clear();\n    lkQuality.clear();\n    lastBeatAt = 0;\n    wasUnstable = false;\n    if (store.snapshot().localNetwork !== UNKNOWN_LOCAL_NETWORK) store.patch({ localNetwork: UNKNOWN_LOCAL_NETWORK });\n  }\n\n  /** One tick a second while in the call: beat, and judge who went silent. */\n  function healthTick(): void {\n    const snap = store.snapshot();\n    const target = driver;\n    if (disposed || target === null || snap.phase !== \"in_call\") return;\n    if (snap.connection !== \"stable\") {\n      // THIS tab is the one cut off: it hears nobody, which says nothing about them.\n      wasUnstable = true;\n      return;\n    }\n    if (wasUnstable) {\n      wasUnstable = false;\n      liveness.restartClock();\n    }\n    const size = liveRoster.length;\n    const at = now();\n    if (at - lastBeatAt >= heartbeatIntervalMs(size)) {\n      lastBeatAt = at;\n      const beat = encodeBeat({ q: assessor.current(), vp: snap.localNetwork.videoPaused });\n      void target.publishData(ALIVE_TOPIC, beat).catch(() => undefined);\n    }\n    const remotes = liveRoster.filter((p) => !p.isLocal).map((p) => p.identity);\n    const next = liveness.stale(remotes, size);\n    if (next.size !== silent.size || [...next].some((who) => !silent.has(who))) {\n      silent = next;\n      projectRoster(liveRoster, new Date(at).toISOString());\n    }\n  }\n\n  function startHealth(): void {\n    if (healthTimer !== null) return;\n    healthTimer = setInterval(healthTick, 1000);\n  }\n\n  /** The request to come back with: the last join, with the camera/mic as they are NOW. */\n  function requestAsNow(): JoinRequest | null {\n    if (lastRequest === null) return null;\n    const media = store.snapshot().media;\n    if (store.snapshot().phase !== \"in_call\") return lastRequest;\n    return { ...lastRequest, mode: media.camera.enabled ? \"video\" : \"audio\", microphone: media.microphone.enabled };\n  }\n\n  /** Drop the room this engine holds (no phase change — the caller says where the person went). */\n  async function dropRoom(): Promise<void> {\n    const target = driver;\n    driver = null;\n    if (current !== null) {\n      tokens.invalidate(current.roomName);\n      current = null;\n    }\n    store.setLocalTrack(\"microphone\", IDLE_TRACK);\n    store.setLocalTrack(\"camera\", IDLE_TRACK);\n    media.onDisconnected();\n    store.patch({ share: NO_SHARE, connection: \"stable\" });\n    clearGhosts();\n    stopHealth();\n    await target?.disconnect();\n  }\n\n  /** MY Leave: the room is dropped and the phase is `left` (§3.1). */\n  async function leaveRoom(): Promise<void> {\n    // A deliberate Leave says so on the heartbeat first, so nobody holds a `reconnecting` tile for\n    // someone who meant to go (`net-others-see-drop`). Bounded: a dead path never delays the Leave.\n    const target = driver;\n    if (target !== null && store.snapshot().phase === \"in_call\") {\n      await Promise.race([\n        target.publishData(ALIVE_TOPIC, encodeBye()).catch(() => undefined),\n        new Promise<void>((resolve) => setTimeout(resolve, 300)),\n      ]);\n    }\n    store.dispatch({ type: \"leave\" });\n    await dropRoom();\n    options.onLeft?.(null);\n  }\n\n  async function confirmMeetingEnd(): Promise<void> {\n    const meeting = store.snapshot().meeting;\n    const target = driver;\n    if (meeting === null || target === null || confirmingEnds.has(target) || options.resolveMeeting === undefined) return;\n    confirmingEnds.add(target);\n    let timer: ReturnType<typeof setTimeout> | undefined;\n    try {\n      const verified = await Promise.race([\n        options.resolveMeeting(meeting.slug),\n        new Promise<never>((_, reject) => {\n          timer = setTimeout(() => reject(new Error(\"Meeting end verification timed out\")), 5000);\n        }),\n      ]);\n      if (disposed || driver !== target || store.snapshot().meeting?.id !== meeting.id) return;\n      if (verified.id !== meeting.id || verified.roomName !== meeting.roomName || verified.endedAt === null) {\n        report(\"warn\", \"Meet ignored an unconfirmed meeting-end notice\", \"The canonical meeting is still live or does not match this room.\");\n        return;\n      }\n      // Keep newer roster/metadata updates; only the durable ending is needed.\n      const latest = store.snapshot().meeting;\n      if (latest === null) return;\n      store.patch({ meeting: { ...latest, endedAt: verified.endedAt } });\n      // time-limit-warning: the screen says WHY the meeting ended (the server recorded the trigger on this connection).\n      const connection = current?.connectionIdentity ?? current?.identity ?? store.snapshot().localIdentity ?? null;\n      let why: ExitServerWord | null | undefined;\n      try {\n        why = options.readExit !== undefined && connection !== null ? await options.readExit(connection, current?.meetingPass ?? null) : undefined;\n      } catch {\n        why = null;\n      }\n      store.dispatch({ type: \"ended\" }, { reason: why?.exitReason === \"time_limit\" ? \"time_limit\" : \"ended\" });\n      await dropRoom();\n      options.onLeft?.(\"ended\");\n    } catch (error) {\n      report(\"error\", `Meet could not confirm or finish meeting teardown: ${String(error)}`, \"Check the meeting link again; if media remains active, close this meeting tab.\");\n    } finally {\n      if (timer !== undefined) clearTimeout(timer);\n      confirmingEnds.delete(target);\n    }\n  }\n\n  function report(level: \"info\" | \"warn\" | \"error\", message: string, remedy?: string): void {\n    options.onDiagnostic?.(remedy === undefined ? { level, message } : { level, message, remedy });\n  }\n\n  /** Consecutive screen-share refusals no browser can tell from a closed picker. */\n  let ambiguousShareDenials = 0;\n\n  /**\n   * THE JOIN FAILED. Only a join can fail the join: the machine accepts `join_failed` from\n   * `joining` alone, so a caller anywhere else (an in-call action) cannot move the phase with it\n   * — the failure is still recorded and reported, and the call goes on. A gate reason renders\n   * `refused:<reason>` (`ended` → `ended`); no reason renders `disconnected` with Rejoin — never\n   * pre-join (the old `failed` → pre-join fallback is gone).\n   */\n  function failJoin(error: unknown, operation: string): MeetError {\n    const normalized = normalizeMeetError(error, operation);\n    store.patch({\n      failure: {\n        message: normalized.message,\n        remedy: normalized.remedy,\n        reason: normalized.reason,\n        retryAt: normalized.retryAfterSeconds === null ? null : now() + normalized.retryAfterSeconds * 1000,\n        stage: \"join\",\n      },\n    });\n    store.dispatch({ type: \"join_failed\", reason: normalized.reason ?? null });\n    report(\n      normalized.code === \"session-unavailable\" ? \"warn\" : \"error\",\n      normalized.message,\n      normalized.remedy,\n    );\n    return normalized;\n  }\n\n  /**\n   * A move between rooms (breakout) left the person in NO room: that is an exit, resolved as\n   * `disconnected` with Rejoin (§3.4) — the failure is kept for the screen's remedy.\n   */\n  async function lostRoom(error: unknown, operation: string): Promise<MeetError> {\n    const normalized = normalizeMeetError(error, operation);\n    store.patch({ failure: { message: normalized.message, remedy: normalized.remedy, reason: normalized.reason } });\n    await dropRoom();\n    store.dispatch({ type: \"exit\", to: \"disconnected\" });\n    report(\"error\", normalized.message, normalized.remedy);\n    return normalized;\n  }\n\n  // S6c — MS, the media supervisor. Its regions never move the phase.\n  const media = createMediaSupervisor({\n    store,\n    platform: options.mediaPlatform === undefined ? webMediaPlatform() : options.mediaPlatform,\n    driver: () => driver,\n    report,\n  });\n\n  const handlers: RoomDriverHandlers = {\n    audioPlayback(canPlay) {\n      media.onAudioPlayback(canPlay);\n    },\n    devicesChanged() {\n      media.onDevicesChanged();\n    },\n    mediaDeviceError(error, kind) {\n      media.onDeviceError(error, kind);\n    },\n    participants(list) {\n      const joinedAt = new Date(now()).toISOString();\n      projectRoster(list, joinedAt);\n    },\n    participantLeft(who, reason) {\n      departures.set(who, reason);\n    },\n    roomMetadata(metadata) {\n      // S8 THE SERVER'S ROOM STATE (CORE-DESIGN §2.6 RS). Only aidream's\n      // `room_state.publish_room_state` writes it, always whole, read back from the rows. A\n      // malformed or empty string means \"nothing set\", never a throw inside a room event.\n      let parsed: Record<string, unknown> = {};\n      if (metadata.length > 0) {\n        try {\n          const value: unknown = JSON.parse(metadata);\n          if (typeof value === \"object\" && value !== null) parsed = value as Record<string, unknown>;\n        } catch {\n          report(\n            \"warn\",\n            \"meet: the room's metadata is not JSON, so the room state was not read from it\",\n            \"Only aidream writes room metadata; check services/meet/room_state.py.\",\n          );\n        }\n      }\n      const key = (name: string): ParticipantIdentity | null => {\n        const value = parsed[name];\n        return typeof value === \"string\" && value.length > 0 ? asParticipantIdentity(personOf(value)) : null;\n      };\n      const waiting = typeof parsed[\"waiting_count\"] === \"number\" ? (parsed[\"waiting_count\"] as number) : 0;\n      const before = store.snapshot();\n      const next = { spotlight: key(\"spotlight\"), actingHost: key(\"acting_host\"), presenter: key(\"presenter\"), waitingCount: waiting };\n      if (\n        before.spotlight !== next.spotlight ||\n        before.actingHost !== next.actingHost ||\n        before.presenter !== next.presenter ||\n        before.waitingCount !== next.waitingCount\n      ) {\n        store.patch(next);\n      }\n      if (parsed[\"recording\"] !== undefined && parsed[\"recording\"] !== null) {\n        applyRecordingState(store, { meeting_id: parsed[\"meeting_id\"], recording: parsed[\"recording\"] });\n      }\n    },\n    activeSpeakers(identities) {\n      store.setSpeaking([...new Set(identities.map((who) => personOf(who)))]);\n    },\n    quality(who, value) {\n      const person = personOf(who);\n      lkQuality.set(person, value);\n      const local = store.snapshot().participants.find((p) => p.identity === person)?.isLocal === true;\n      store.setQuality(person, value === \"lost\" ? value : effectiveQuality(person, who, local));\n    },\n    networkReading(reading) {\n      const snap = store.snapshot();\n      if (snap.phase !== \"in_call\" || snap.connection !== \"stable\") return;\n      startHealth();\n      const before = assessor.current();\n      const quality = assessor.push(reading);\n      const path = pathOf(reading);\n      if (quality !== before) {\n        report(\"info\", `meet: this connection reads ${quality} (round trip ${reading.rttMs ?? \"?\"} ms, path ${path})`, \"Diagnostic only.\");\n      }\n      patchLocalNetwork({ quality, ...(path !== \"unknown\" ? { path } : {}) });\n      refreshQualities();\n      // `net-video-auto-off`: a path poor for the knob's time pauses the camera to keep the audio.\n      const cameraOn = snap.media.camera.enabled;\n      if (autoOff.step(quality, cameraOn) === \"pause\" && driver !== null) {\n        const target = driver;\n        report(\"info\", \"meet: the camera was paused because the connection is poor\", \"The audio is kept; Try video again turns it back on.\");\n        void enableTrack(target, \"camera\", false).then((state) => {\n          if (!state.enabled) patchLocalNetwork({ videoPaused: true });\n        });\n      }\n    },\n    connectionState(state) {\n      // `reconnecting` is a VISIBLE state, not a silent one — and it is the `connection`\n      // REGION, never a phase (CORE-DESIGN §3.1/§3.2): the person is still in the call. Which\n      // region value (signal blip, full reconnect, offline, servers unreachable) is the\n      // connection supervisor's call (S6b).\n      supervisor.driverState(state);\n      if (state === \"connected\" && store.snapshot().phase === \"joining\") store.dispatch({ type: \"connected\" });\n      if (state === \"connected\") {\n        // Beat at once: a person who drops in their first seconds is still known to everyone.\n        startHealth();\n        lastBeatAt = 0;\n        healthTick();\n      }\n    },\n    transcription(event) {\n      // A CAPTION IS A HINT (D16). It is stored as one, next to the durable\n      // rows, and the reconciliation in `transcript.ts` decides which of the two\n      // a line ends up being. Nothing else in this package reads captions.\n      const snapshot = store.snapshot();\n      const meeting = snapshot.meeting;\n      if (meeting === null) {\n        // A caption with no meeting record has nothing durable to reconcile\n        // against later. An ad-hoc call room is exactly that case; dropping it\n        // is correct, and it is not silent — it is stated here.\n        return;\n      }\n      // `lk.transcribed_participant_identity` is supplied by the publisher and\n      // only says who they CLAIM to be transcribing. The stream's publisher is\n      // the SFU-reported identity; captions are admitted only from this\n      // meeting's deterministic note-taker. This remains display-only (D16),\n      // but a room participant cannot write a fake line into the caption rail.\n      // This check deliberately does not wait for a roster event: the first\n      // note-taker utterance may arrive before its roster projection.\n      if (event.publisherIdentity !== noteTakerIdentity(meeting.id)) {\n        report(\n          \"warn\",\n          \"meet: ignored a caption from a participant that is not this meeting's note-taker\",\n          \"Captions are accepted only from the server-dispatched note-taker; the durable transcript remains authoritative.\",\n        );\n        return;\n      }\n      const speakerIdentity = personOf(event.speakerIdentity);\n      const speaker = snapshot.participants.find(\n        (participant) => participant.identity === speakerIdentity,\n      );\n      store.ingestCaption(\n        captionSegment({\n          captionId: event.segmentId,\n          meetingId: meeting.id,\n          identity: speakerIdentity,\n          // 🚨 ONE ANSWER TO \"WHO SAID THAT\" (MRI-A16). This line used to fall\n          // back to `event.speakerIdentity` — the raw LiveKit token — which is\n          // how a guest's caption rail read `guest:c8-spk-1` in the same second\n          // the host's read \"Ada Lovelace\". The book keeps the last known name\n          // for somebody who has left, and says \"Unnamed guest\" when nothing\n          // anywhere has ever known one. It never prints a token.\n          speaker: displayNameFor(snapshot.names, speakerIdentity, speaker?.displayName),\n          text: event.text,\n          final: event.final,\n          startedAt: event.at,\n        }),\n      );\n    },\n    data(topic, payload, from) {\n      // 🚨 THE SERVER'S OWN EVENTS COME FIRST, and they are the only live feed a\n      // session-less guest has (MRI-A12). They are handled before the `mx.*`\n      // control plane because they are a different KIND of message: published by\n      // the platform with a `roomAdmin` grant no participant token can claim,\n      // carrying durable rows rather than a sender's intent.\n      if (isRoomEventTopic(topic)) {\n        // `matrx.meet.*` is a server namespace, not an ACL. Any participant\n        // may publish to a topic, including one with an agent-looking name;\n        // only RoomService.SendData reaches the SDK without a participant.\n        if (from !== null) {\n          report(\n            \"warn\",\n            `meet: ignored participant-published server event on ${topic}`,\n            \"Only aidream may publish matrx.meet.* events. The durable meeting record remains unchanged.\",\n          );\n          return;\n        }\n        let body: unknown;\n        try {\n          body = JSON.parse(payload);\n        } catch {\n          report(\n            \"warn\",\n            `meet: dropped an unparseable room event on ${topic}`,\n            \"This topic is published by aidream only. Non-JSON here means a client is \" +\n              \"publishing under the server's namespace, or the payload was truncated.\",\n          );\n          return;\n        }\n        if (topic === ROOM_EVENTS.ended && options.resolveMeeting !== undefined) {\n          const meeting = store.snapshot().meeting;\n          if (typeof body === \"object\" && body !== null && \"meeting_id\" in body && body.meeting_id === meeting?.id) {\n            void confirmMeetingEnd();\n          } else {\n            report(\"warn\", \"Meet ignored an ending for another or missing meeting\", \"Only a matching canonical meeting can end this transport.\");\n          }\n          return;\n        }\n        const outcome = applyRoomEvent({ store, topic, payload: body, now });\n        if (!outcome.handled) {\n          // NEVER SILENT. A dropped room event is a note, a decision or an\n          // ending that a guest will simply never see, and the reason has to be\n          // reachable from the surface rather than from a debugger.\n          report(\n            \"warn\",\n            `meet: ignored a room event on ${topic} — ${outcome.ignored ?? \"no reason given\"}`,\n            \"The durable row still exists behind the meeting link. Signed-in members \" +\n              \"receive it over Postgres Changes; a guest sees it on their next join.\",\n          );\n        }\n        return;\n      }\n      let envelope: DataEnvelope = {};\n      try {\n        const parsed: unknown = JSON.parse(payload);\n        if (typeof parsed === \"object\" && parsed !== null) envelope = parsed as DataEnvelope;\n      } catch {\n        report(\n          \"warn\",\n          `meet: dropped an unparseable data message on ${topic}`,\n          \"A sender is publishing non-JSON on a reserved mx.* topic. Use publishData through \" +\n            \"the engine so the envelope is always well formed.\",\n        );\n        return;\n      }\n      const sender = personOf(from ?? \"\");\n      if (from !== null) {\n        if (topic === ALIVE_TOPIC && isBye(payload)) {\n          saidBye.add(from);\n          return;\n        }\n        const beat = topic === ALIVE_TOPIC ? decodeBeat(payload) : null;\n        const before = liveness.reported(from);\n        liveness.heard(from, beat);\n        if (topic === ALIVE_TOPIC) {\n          startHealth();\n          if (beat !== null && (before?.q !== beat.q || before?.vp !== beat.vp || silent.has(from))) {\n            silent.delete(from);\n            projectRoster(liveRoster, new Date(now()).toISOString());\n            refreshQualities();\n          } else if (silent.delete(from)) {\n            projectRoster(liveRoster, new Date(now()).toISOString());\n          }\n          return;\n        }\n      }\n      switch (topic) {\n        case DATA_TOPICS.reaction:\n          if (typeof envelope.emoji === \"string\") {\n            store.addReaction({\n              id: envelope.id ?? `${sender}-${now()}`,\n              identity: sender,\n              emoji: envelope.emoji,\n              at: now(),\n            });\n          }\n          return;\n        case DATA_TOPICS.chat:\n          // ONLY PRIVATE MESSAGES ride the data plane since 0.8: a message to\n          // everyone is SAVED through the server and arrives as the server's\n          // `matrx.meet.chat`. A participant's un-addressed `mx.chat` packet is\n          // an older client's ephemeral chat — shown, never mistaken for saved.\n          if (typeof envelope.text === \"string\") {\n            const local = store.snapshot().localIdentity;\n            store.addChat({\n              id: envelope.id ?? `${sender}-${now()}`,\n              identity: sender,\n              displayName: envelope.name ?? sender,\n              text: envelope.text,\n              at: envelope.at ?? new Date(now()).toISOString(),\n              ...(typeof envelope.to === \"string\" && local !== null ? { to: local } : {}),\n            });\n          }\n          return;\n        default:\n          // Unknown topics are IGNORED, never thrown on — that is what lets a\n          // newer client ship a new in-room feature without breaking old ones.\n          return;\n      }\n    },\n    disconnected(reason) {\n      // A breakout move, or a disconnect THIS engine asked for (Leave, end, dispose), is not\n      // an exit to resolve: the caller already said where the person went.\n      if (moving || driver === null) return;\n      void resolveExitAndApply(reason);\n    },\n  };\n\n  /**\n   * §3.4 — LiveKit dropped this tab. Ask the server what happened to THIS connection, then land\n   * on the phase the resolution names. Never pre-join; `disconnected` always offers Rejoin.\n   */\n  async function resolveExitAndApply(hint: string | null): Promise<void> {\n    const connection = current?.connectionIdentity ?? current?.identity ?? store.snapshot().localIdentity ?? null;\n    // The pass this connection held — read BEFORE the room is dropped (which forgets the token):\n    // S7's \"switched to another tab\" is only the server's word, never LiveKit's.\n    const heldPass = current?.meetingPass ?? null;\n    // Come back as you were: the camera and microphone as they are at the drop (S6b), for the\n    // auto-rejoin, a manual Rejoin and a reload alike — `dropRoom` resets the local tracks.\n    lastRequest = requestAsNow();\n    // THE SERVER ENDED THIS SESSION (removed, room closed, token revoked), so the cached token\n    // is dead: the next Join must mint again and read the server's own decision. Reusing it\n    // showed \"invalid token: revoked\" under a camera-refusal remedy (production 2026-09-27).\n    await dropRoom();\n    let server: ExitServerWord | null | undefined;\n    if (options.readExit === undefined || connection === null || store.snapshot().meeting === null) {\n      server = undefined;\n    } else {\n      try {\n        server = await options.readExit(connection, heldPass);\n      } catch {\n        server = null;\n      }\n    }\n    if (disposed) return;\n    const resolved = resolveExit({ server, hint, frozen: options.wasFrozen?.() ?? false });\n    // The state read failed: the supervisor knows WHICH failure — no network, or our servers.\n    store.patch({ connection: server === null ? supervisor.exitConnection() : resolved.connection });\n    if (resolved.to === \"waiting:knocking\") {\n      store.patch({\n        waiting: {\n          admission: \"knocking\",\n          admittersPresent: null,\n          reknockAllowed: true,\n          knockExpiresAt: null,\n          pollSeconds: store.snapshot().waiting?.pollSeconds ?? 3,\n          liveVersion: 0,\n        },\n      });\n    }\n    store.dispatch({ type: \"exit\", to: resolved.to }, { reason: resolved.reason, notice: resolved.notice });\n    report(\n      resolved.to === \"disconnected\" ? \"warn\" : \"info\",\n      `meet: the room connection ended (${hint ?? \"no LiveKit reason\"}) → ${resolved.to}`,\n      resolved.to === \"disconnected\" ? \"Press Rejoin; the meeting is still going.\" : \"The screen says what happened.\",\n    );\n    options.onLeft?.(hint);\n  }\n\n  async function connect(request: JoinRequest): Promise<void> {\n    store.patch({ failure: null, waiting: null, roomName: request.roomName, share: NO_SHARE, connection: \"stable\" });\n    const tabId = options.tabClaim !== undefined ? await options.tabClaim.tabId : null;\n    const token = await tokens.get({\n      roomName: request.roomName,\n      identity,\n      ...(request.meetingId !== undefined ? { meetingId: request.meetingId } : {}),\n      ...(request.slug !== undefined ? { slug: request.slug } : {}),\n      ...(request.breakoutRoomId != null ? { breakoutRoomId: request.breakoutRoomId } : {}),\n      ...(request.observe === true ? { observe: true } : {}),\n      ...(tabId !== null ? { tabId } : {}),\n      ...(request.secondDevice !== undefined ? { secondDevice: request.secondDevice } : {}),\n    });\n    if (token.secondDeviceChoice != null) {\n      // S7: ALREADY IN THIS MEETING on another tab or device. Nothing was minted; the pre-join\n      // offers the meeting's choice and the person's press joins again with the answer.\n      store.patch({ secondDevice: { rule: token.secondDeviceChoice }, localIdentity: token.identity });\n      store.dispatch({ type: \"second_device\" });\n      report(\"info\", `meet: already in this meeting elsewhere — offering the choice (${token.secondDeviceChoice})`);\n      return;\n    }\n    if (store.snapshot().secondDevice !== null) store.patch({ secondDevice: null });\n    // A switch happens once: a later rejoin of THIS tab must not displace a tab opened since.\n    if (request.secondDevice === \"switch_here\" && lastRequest !== null) {\n      const { secondDevice: _answered, ...rest } = lastRequest;\n      lastRequest = rest;\n    }\n    options.tabClaim?.inRoom(String(request.roomName), String(token.identity), token.secondDeviceRule ?? null);\n    current = token;\n    lastServerUrl = token.serverUrl;\n    connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;\n    store.patch({ captionsStartTimeoutSeconds: connectionPolicy.captionsStartTimeoutSeconds });\n    if (token.leavePolicy !== undefined) store.patch({ leavePolicy: token.leavePolicy });\n    store.patch({ canReclaim: token.canReclaim === true });\n    // 🚨 THE GRANTS LAND WITH THE TOKEN, before any roster exists (MRI-A11).\n    // Waiting for the LiveKit roster to learn that this person is the host means\n    // the host's own controls flicker in — or, when a roster event arrives with\n    // empty metadata, never appear at all. That was the shipped defect.\n    store.patch({\n      localIdentity: token.identity,\n      breakoutRoomId: token.breakoutRoomId ?? null,\n      grants: {\n        role: token.role,\n        standing: token.standing,\n        canRecord: token.canRecord,\n        canPublish: token.canPublish,\n        canSubscribe: token.canSubscribe,\n        observersVisibleTo: token.observersVisibleTo ?? \"everyone\",\n      },\n    });\n\n    // THE LOBBY IS A PHASE, NOT AN ERROR (D6). The server said \"wait\"; the UI\n    // shows the waiting room and the room channel delivers the host's decision.\n    //\n    // 🚨 S4: A TOKEN THAT CANNOT SUBSCRIBE NEVER BECOMES AN IN-CALL SCREEN. A waiting guest\n    // was once shown an empty room (\"Just you\") while the host still listed them as waiting:\n    // a media connection that can hear nobody IS the waiting room, whatever flag came with\n    // it. The wait itself is then read from the server (`GET /v1/meet/state`), never from a\n    // broadcast (CORE-DESIGN §2.6).\n    if (token.lobby || !token.canSubscribe) {\n      const admission = token.admissionState !== undefined && token.admissionState !== \"admitted\"\n        ? token.admissionState\n        : \"knocking\";\n      store.patch({\n        waiting: {\n          admission,\n          admittersPresent: null,\n          reknockAllowed: true,\n          knockExpiresAt: null,\n          pollSeconds: token.pollSeconds ?? 3,\n          liveVersion: 0,\n        },\n      });\n      store.dispatch({ type: \"admission\", admission });\n      return;\n    }\n\n    store.patch({ waiting: null });\n    const created = await options.driverFactory(handlers);\n    if (disposed) {\n      // Unmounted mid-connect. Disconnect the room we just built rather than\n      // leaking it — this is the \"camera light stays on\" bug.\n      await created.disconnect();\n      return;\n    }\n    driver = created;\n    // S7: a companion plays no remote audio — set before the connect so no packet is ever heard.\n    if (token.connectionKind === \"companion\") created.setRemoteAudioPlayback?.(false);\n    await created.connect(token.serverUrl, token.token);\n\n    // 🚨 IN THE ROOM. Attendance is settled HERE, before a single device is\n    // touched. Everything below is best-effort publishing; nothing below can\n    // unwind the join. See `attendance.ts` for the defect this closes.\n    store.patch({ failure: null, connection: \"stable\" });\n    store.dispatch({ type: \"connected\" });\n    store.setLocalTrack(\"microphone\", IDLE_TRACK);\n    store.setLocalTrack(\"camera\", IDLE_TRACK);\n    media.start();\n\n    // THE REMEMBERED CHOICES GO ON BEFORE ANY DEVICE DOES, so the first frame\n    // anyone sees is already blurred and the first word already cleaned.\n    const effects = options.effectsStorage?.load() ?? store.snapshot().effects;\n    store.patch({ effects });\n    // Only what DIFFERS from the browser default is applied on the way in: a\n    // default join touches nothing it does not have to.\n    if (!effects.noiseSuppression || effects.background !== \"none\") {\n      try {\n        await applyEffects(created, effects);\n      } catch {\n        // Reported inside; the join never depends on an effect.\n      }\n    }\n    for (const kind of [\"audioinput\", \"videoinput\", \"audiooutput\"] as const) {\n      const chosen = options.resolveDevice?.(kind) ?? null;\n      if (chosen === null || chosen === \"default\") continue;\n      try {\n        await created.switchDevice(kind, chosen);\n      } catch (error) {\n        const normalized = normalizeDeviceError(error, `meet.switchDevice(${kind})`);\n        report(\"warn\", normalized.message, normalized.remedy);\n      }\n    }\n\n    if (request.mode === \"video\") {\n      await enableTrack(created, \"camera\", true);\n    }\n    // S7: a companion (\"join here too\") never opens the microphone — the person's other device\n    // is the one that speaks.\n    if (request.microphone !== false && current?.connectionKind !== \"companion\") {\n      await enableTrack(created, \"microphone\", true);\n    }\n    // What is in use now is the baseline a later unplug is measured against.\n    media.onConnected();\n  }\n\n  /**\n   * THE ONE PATH that turns a local device on or off — used by the join and by\n   * the in-room controls alike, so \"enable it later\" cannot behave differently\n   * from \"enable it on the way in\". A refusal is recorded as state with the\n   * browser's own reason and a remedy, reported as a diagnostic, and returned;\n   * it is never thrown, because there is no caller for whom losing the room is\n   * the right answer to a busy microphone.\n   */\n  async function enableTrack(\n    target: MeetRoomDriver,\n    kind: \"microphone\" | \"camera\",\n    enabled: boolean,\n  ): Promise<LocalTrackState> {\n    try {\n      if (kind === \"microphone\") await target.setMicrophoneEnabled(enabled);\n      else await target.setCameraEnabled(enabled);\n      const state: LocalTrackState = { enabled, unavailable: null };\n      store.setLocalTrack(kind, state);\n      return state;\n    } catch (error) {\n      // S6c: the refusal is classified against the permission store (Block vs the operating\n      // system vs a missing or busy device) — the error name alone cannot tell them apart.\n      const refused = await media.unavailable(error, kind, `meet.${kind}`);\n      const state: LocalTrackState = { enabled: false, unavailable: refused };\n      store.setLocalTrack(kind, state);\n      report(\"warn\", refused.message, refused.remedy);\n      return state;\n    }\n  }\n\n  async function publish(\n    topic: string,\n    body: Record<string, unknown>,\n    to?: readonly string[],\n  ): Promise<void> {\n    if (driver === null) return;\n    // S7: a private message goes to a PERSON — every connection they hold.\n    const addresses = to === undefined ? undefined : to.flatMap((who) => connectionsOf(who));\n    await driver.publishData(topic, JSON.stringify(body), addresses);\n  }\n\n  async function applyEffects(target: MeetRoomDriver, effects: MediaEffects): Promise<void> {\n    try {\n      await target.setAudioProcessing?.({\n        noiseSuppression: effects.noiseSuppression,\n        echoCancellation: true,\n        autoGainControl: true,\n      });\n    } catch (error) {\n      report(\"warn\", `meet: noise suppression could not be applied: ${String(error)}`, \"The microphone keeps working without it.\");\n    }\n    if (target.setVideoEffect === undefined) return;\n    const effect: VideoEffect =\n      effects.background === \"blur\"\n        ? { kind: \"blur\" }\n        : effects.background === \"image\" && effects.backgroundImage !== null\n          ? { kind: \"image\", imageUrl: effects.backgroundImage }\n          : { kind: \"none\" };\n    if (effect.kind !== \"none\" && target.supportsVideoEffects?.() === false) return;\n    try {\n      await target.setVideoEffect(effect);\n    } catch (error) {\n      const normalized = normalizeMeetError(error, \"meet.setVideoEffect\");\n      report(\"warn\", normalized.message, normalized.remedy);\n      throw normalized;\n    }\n  }\n\n  /**\n   * THE ROSTER, WITH OTHERS' DROPS HELD (S6b, `net-others-see-drop`). A participant LiveKit\n   * dropped without a deliberate reason stays as a `reconnecting` tile for\n   * `reconnect_grace_seconds`; they disappear at once when they come back (same identity — one\n   * tile, never a copy) or when the grace runs out.\n   */\n  function projectRoster(list: readonly DriverParticipant[], joinedAt: string): void {\n    const at = now();\n    const previous = new Map(liveRoster.map((p) => [p.identity, p]));\n    const present = new Set(list.map((p) => p.identity));\n    const graceMs = connectionPolicy.reconnectGraceSeconds * 1000;\n    // NO SILENT DROP. A remote who was on the roster and is not on this one left the room; if the\n    // media layer said nothing about it (no ParticipantDisconnected), it is an unexplained departure\n    // — held like any drop, and announced, never a tile that just vanishes.\n    if (store.snapshot().phase === \"in_call\") {\n      for (const [who, last] of previous) {\n        if (last.isLocal || present.has(who) || departures.has(who)) continue;\n        departures.set(who, null);\n        report(\"warn\", `meet: ${who} vanished from the room's roster with no departure event; held as reconnecting`, \"The media layer dropped a participant silently; the tile is kept for the reconnect grace.\");\n      }\n    }\n    for (const [who, reason] of departures) {\n      const last = previous.get(who);\n      // A drop is a LiveKit reason that is not deliberate, OR a person who had already gone silent\n      // on the heartbeat (the media server can report a pulled cable as an ordinary close) — never\n      // someone who said goodbye.\n      const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));\n      report(\"info\", `meet: ${who} left the room (${reason ?? \"no reason\"}${dropped ? \", held as reconnecting\" : \"\"})`, \"Diagnostic only.\");\n      if (last !== undefined && !last.isLocal && !present.has(who) && graceMs > 0 && dropped) {\n        ghosts.set(who, { participant: last, until: at + graceMs });\n      }\n    }\n    for (const who of departures.keys()) {\n      liveness.forget(who);\n      silent.delete(who);\n      saidBye.delete(who);\n    }\n    departures.clear();\n    liveRoster = list;\n    // A person (`user:` / `guest:` — minted by our token route, so running this package) beats;\n    // start their clock now, so someone cut before their first beat reaches us still turns\n    // `reconnecting`. Agents and any other kind never beat and are never expected to.\n    for (const p of list) {\n      if (!p.isLocal && (isGuestIdentity(p.identity) || userIdOfIdentity(p.identity) !== null)) liveness.expect(p.identity);\n    }\n    // `share-stopped-by-browser`: the browser's own \"Stop sharing\" ends the track and LiveKit\n    // unpublishes it — the share region follows the roster, never a stale \"presenting\".\n    const localNow = list.find((p) => p.isLocal);\n    if (localNow !== undefined && !localNow.screenSharing && store.snapshot().share.state === \"presenting\") {\n      store.patch({ share: NO_SHARE });\n    }\n    const merged = mergeGhosts(list, ghosts, at);\n    ghosts = merged.kept;\n    // S7: ONE TILE PER PERSON. A person on two tabs/devices is two LiveKit connections; the tile\n    // shows the one to look at — this tab first, then a live main connection, then any.\n    const people = new Map<string, { entry: (typeof merged.roster)[number]; rank: number }>();\n    const connections = new Map<string, string[]>();\n    for (const entry of merged.roster) {\n      const person = personOf(entry.identity);\n      connections.set(person, [...(connections.get(person) ?? []), entry.identity]);\n      const rank =\n        (entry.isLocal ? 8 : 0) +\n        (entry.reconnecting === true ? 0 : 4) +\n        (entry.attributes[CONNECTION_KIND_ATTRIBUTE] === \"companion\" ? 0 : 2) +\n        (entry.cameraEnabled || entry.micEnabled ? 1 : 0);\n      const held = people.get(person);\n      if (held === undefined || rank > held.rank) people.set(person, { entry, rank });\n    }\n    personConnections = connections;\n    mainConnection = new Map([...people].map(([person, { entry }]) => [person, entry.identity]));\n    store.setParticipants(\n      [...people.values()].map(({ entry }) => {\n        const projected = projectParticipant(entry, joinedAt);\n        if (entry.reconnecting === true || (!entry.isLocal && silent.has(entry.identity) && !saidBye.has(entry.identity))) {\n          return { ...projected, reconnecting: true, quality: \"lost\" as const };\n        }\n        const videoPaused = entry.isLocal\n          ? store.snapshot().localNetwork.videoPaused\n          : liveness.reported(entry.identity)?.vp === true;\n        const quality = effectiveQuality(projected.identity, entry.identity, entry.isLocal);\n        return {\n          ...projected,\n          ...(quality !== \"unknown\" && quality !== \"lost\" ? { quality } : {}),\n          ...(videoPaused ? { videoPaused: true } : {}),\n        };\n      }),\n    );\n    scheduleGhostExpiry();\n  }\n\n  function scheduleGhostExpiry(): void {\n    if (ghostTimer !== null) clearTimeout(ghostTimer);\n    ghostTimer = null;\n    if (ghosts.size === 0 || disposed) return;\n    const next = Math.min(...[...ghosts.values()].map((g) => g.until));\n    ghostTimer = setTimeout(() => {\n      ghostTimer = null;\n      if (disposed || driver === null) return;\n      projectRoster(liveRoster, new Date(now()).toISOString());\n    }, Math.max(0, next - now()) + 50);\n  }\n\n  function clearGhosts(): void {\n    ghosts = new Map();\n    departures.clear();\n    liveRoster = [];\n    if (ghostTimer !== null) clearTimeout(ghostTimer);\n    ghostTimer = null;\n  }\n\n  const supervisor = createConnectionSupervisor({\n    store,\n    network: options.connection?.network ?? createWebNetworkPort(),\n    probe: () => options.connection?.probe?.(current?.serverUrl ?? lastServerUrl) ?? Promise.resolve(true),\n    policy: () => connectionPolicy,\n    autoRejoin: () => engine.autoRejoin(),\n    currentRequest: requestAsNow,\n    resume: options.connection?.resume,\n    now,\n    report: (level, message) => report(level, message),\n  });\n\n  const engine: RoomEngine = {\n    join(request) {\n      // SINGLE FLIGHT: a strict-mode double effect and a user's second click\n      // share one join. Two joins for one identity make LiveKit drop the first.\n      if (joining !== null) return joining;\n      // THE PERSON'S PRESS (§3.1): prejoin / left / disconnected / superseded → joining. An\n      // answered call or an admission already moved the phase to `joining`.\n      if (store.snapshot().phase !== \"joining\" && !store.dispatch({ type: \"join\", click: true })) {\n        report(\n          \"warn\",\n          `meet.join: cannot join from \"${store.snapshot().phase}\"`,\n          \"Join is offered from the pre-join, left, disconnected and replaced screens only.\",\n        );\n        return Promise.resolve();\n      }\n      lastRequest = request;\n      joining = connect(request)\n        .catch((error: unknown) => {\n          throw failJoin(error, \"meet.join\");\n        })\n        .finally(() => {\n          joining = null;\n        });\n      return joining;\n    },\n    async rejoin() {\n      const request = lastRequest;\n      if (request === null) {\n        // Nothing to rejoin is not an error and never a silent no-op: it means\n        // this engine never joined, which a caller can only reach by wiring the\n        // admission signal to a room nobody is waiting in.\n        report(\n          \"warn\",\n          \"meet.rejoin: this room engine has never joined, so there is nothing to rejoin\",\n          \"Call join() first. An admission verdict for a participant who never knocked is \" +\n            \"ignored rather than minting a token nobody asked for.\",\n        );\n        return;\n      }\n      if (joining !== null) return joining;\n      // ADMITTED from the waiting room, or the person's own Rejoin (disconnected / left /\n      // replaced) — the two ways in that are not the first Join (§3.1).\n      const phase = store.snapshot().phase;\n      // `join` covers the person's presses (Rejoin, Ask to join again); `admitted` the server's yes.\n      const moved =\n        phase === \"joining\" ||\n        store.dispatch({ type: \"join\", click: true }) ||\n        store.dispatch({ type: \"admitted\" });\n      if (!moved) {\n        report(\"warn\", `meet.rejoin: cannot rejoin from \"${phase}\"`, \"Rejoin is offered after leaving, a lost connection, or admission.\");\n        return;\n      }\n      // THE LOBBY TOKEN IS THROWN AWAY. It grants neither publish nor\n      // subscribe; reusing it would put the admitted guest in the room as a\n      // participant who can neither speak nor hear.\n      tokens.invalidate(request.roomName);\n      current = null;\n      joining = connect(request)\n        .catch((error: unknown) => {\n          throw failJoin(error, \"meet.rejoin\");\n        })\n        .finally(() => {\n          joining = null;\n        });\n      return joining;\n    },\n    async autoRejoin() {\n      const request = lastRequest;\n      if (request === null || joining !== null) return joining ?? undefined;\n      // Not a click: only `disconnected` → `joining` (§3.1). Anything else (the person already\n      // pressed Rejoin, left, or the meeting ended) means there is nothing to do.\n      if (!store.dispatch({ type: \"auto_rejoin\" })) return;\n      tokens.invalidate(request.roomName);\n      current = null;\n      joining = connect(request)\n        .catch((error: unknown) => {\n          throw failJoin(error, \"meet.autoRejoin\");\n        })\n        .finally(() => {\n          joining = null;\n        });\n      return joining;\n    },\n    resume(roomName) {\n      const marker = supervisor.resumable(roomName);\n      if (marker === null || joining !== null) return false;\n      if (!store.dispatch({ type: \"resumed\" })) return false;\n      lastRequest = { ...marker.request, roomName };\n      report(\"info\", \"meet: this tab was in the call before the page reloaded — rejoining\");\n      tokens.invalidate(roomName);\n      current = null;\n      joining = connect(lastRequest)\n        .catch((error: unknown) => {\n          throw failJoin(error, \"meet.resume\");\n        })\n        .finally(() => {\n          joining = null;\n        });\n      joining.catch(() => undefined);\n      return true;\n    },\n    async moveToBreakout(roomId) {\n      const request = lastRequest;\n      if (request === null || driver === null) {\n        report(\n          \"warn\",\n          \"meet.moveToBreakout: this engine is not in a meeting room\",\n          \"Join the meeting first; a breakout is a room OF a meeting.\",\n        );\n        return;\n      }\n      if ((store.snapshot().breakoutRoomId ?? null) === roomId) return;\n      if (joining !== null) await joining.catch(() => undefined);\n      const previous = driver;\n      const next: JoinRequest = {\n        ...request,\n        breakoutRoomId: roomId,\n        // Arrive as you were: camera and microphone as they are now.\n        mode: store.snapshot().media.camera.enabled ? \"video\" : \"audio\",\n        microphone: store.snapshot().media.microphone.enabled,\n      };\n      moving = true;\n      try {\n        driver = null;\n        tokens.invalidate(request.roomName);\n        current = null;\n        await previous.disconnect();\n        lastRequest = next;\n        joining = connect(next).finally(() => {\n          joining = null;\n        });\n        await joining;\n      } catch (error) {\n        // THE WAY BACK IS ALWAYS OPEN: a refused breakout returns the person to the\n        // main room rather than leaving them in no room at all.\n        const normalized = normalizeMeetError(error, \"meet.moveToBreakout\");\n        report(\"warn\", normalized.message, normalized.remedy);\n        if (roomId !== null) {\n          lastRequest = { ...next, breakoutRoomId: null };\n          joining = connect(lastRequest).finally(() => {\n            joining = null;\n          });\n          await joining.catch(async (again: unknown) => {\n            throw await lostRoom(again, \"meet.moveToBreakout\");\n          });\n        } else {\n          throw await lostRoom(error, \"meet.moveToBreakout\");\n        }\n        throw normalized;\n      } finally {\n        moving = false;\n      }\n    },\n    leave: leaveRoom,\n    async checkElsewhere(roomName) {\n      const claim = options.tabClaim;\n      const userId = identity.userId;\n      if (claim === undefined || userId === null) return false;\n      const before = store.snapshot();\n      if (before.phase !== \"prejoin\" || before.secondDevice !== null) return false;\n      const person = `user:${String(userId)}`;\n      const found =\n        claim.presenceElsewhere !== undefined\n          ? await claim.presenceElsewhere(String(roomName), person)\n          : (await claim.presentElsewhere(String(roomName), person))\n            ? { rule: null }\n            : null;\n      // `allow_both` (Zoom): nobody is asked — Join adds this tab, as the server would.\n      if (found === null || found.rule === \"allow_both\") return false;\n      // The person may have pressed Join (or left) while the other tabs answered.\n      const now = store.snapshot();\n      if (now.phase !== \"prejoin\" || now.secondDevice !== null) return false;\n      // The live tab's word for the meeting's `second_device` rule (Meet's choice when unknown).\n      store.patch({ secondDevice: { rule: found.rule ?? \"ask_switch_or_join\" } });\n      report(\"info\", \"meet: this browser already has you in this meeting — offering the choice before Join\");\n      return true;\n    },\n    backToPrejoin() {\n      // The person's own press from `left` / `disconnected` (§3.1) — the only way back.\n      store.dispatch({ type: \"back_to_prejoin\", click: true });\n    },\n    // Turning a device on mid-meeting is the SAME operation as turning it on\n    // during the join, so it runs the same function. A failure here used to\n    // stamp the room `failed` — a busy microphone would blank a live meeting.\n    async setMicrophoneEnabled(enabled) {\n      if (driver === null) return;\n      await enableTrack(driver, \"microphone\", enabled);\n    },\n    async setCameraEnabled(enabled) {\n      if (driver === null) return;\n      const state = await enableTrack(driver, \"camera\", enabled);\n      // `net-video-auto-off` \"Try video again\": the person's own choice wins; no re-pause until\n      // the path has recovered once.\n      if (enabled && state.enabled && store.snapshot().localNetwork.videoPaused) {\n        autoOff.retried();\n        patchLocalNetwork({ videoPaused: false });\n      }\n      if (!enabled && store.snapshot().localNetwork.videoPaused) patchLocalNetwork({ videoPaused: false });\n    },\n    async setScreenShareEnabled(enabled) {\n      if (driver === null) return;\n      // 🚨 AN IN-CALL ACTION NEVER CHANGES THE CALL PHASE (CORE-DESIGN §3.3 SA). Every outcome\n      // lands in the `share` REGION; there is no phase event for it at all.\n      // A probe that itself throws is not \"unsupported\": try the share, and let ITS outcome say.\n      let unsupported = false;\n      try {\n        unsupported = enabled && driver.supportsScreenShare?.() === false;\n      } catch {\n        unsupported = false;\n      }\n      if (unsupported) {\n        // This browser cannot share (no getDisplayMedia): say so, keep the call.\n        store.patch({ share: { state: \"refused\", reason: \"unsupported\", remedy: null, at: now() } });\n        report(\"warn\", \"meet: this browser cannot share a screen\", \"Share from a desktop browser (Chrome, Edge, Firefox or Safari).\");\n        return;\n      }\n      if (enabled) store.patch({ share: { state: \"picking\", reason: null, remedy: null, at: now() } });\n      try {\n        await driver.setScreenShareEnabled(enabled);\n        ambiguousShareDenials = 0;\n        const audio = enabled ? driver?.screenShareHasAudio?.() : undefined;\n        store.patch({\n          share: { state: enabled ? \"presenting\" : \"none\", reason: null, remedy: null, at: now(), ...(audio !== undefined ? { audio } : {}) },\n        });\n      } catch (error) {\n        const kind = classifyScreenShareError(error);\n        if (kind === \"ambiguous\") {\n          // Closing the picker is a choice, and some browsers cannot tell it from a\n          // block: stay silent once, explain on the second consecutive refusal.\n          ambiguousShareDenials += 1;\n          if (ambiguousShareDenials < 2) {\n            store.patch({ share: NO_SHARE });\n            return;\n          }\n        }\n        ambiguousShareDenials = 0;\n        const normalized = normalizeScreenShareError(error, \"meet.setScreenShareEnabled\");\n        report(\"warn\", normalized.message, normalized.remedy);\n        store.patch({\n          share: {\n            state: \"refused\",\n            reason: kind === \"other\" ? \"failed\" : \"blocked\",\n            remedy: kind === \"other\" ? normalized.remedy : SCREEN_SHARE_BLOCKED_REMEDY_FOR(normalized.remedy),\n            at: now(),\n          },\n        });\n      }\n    },\n    dismissShareNotice() {\n      const state = store.snapshot().share.state;\n      if (state === \"refused\" || state === \"ended\") store.patch({ share: NO_SHARE });\n    },\n    async react(emoji) {\n      const local = store.snapshot().localIdentity;\n      const id = `${local ?? \"local\"}-${now()}`;\n      if (local !== null) {\n        store.addReaction({ id, identity: local, emoji, at: now() });\n      }\n      await publish(DATA_TOPICS.reaction, { id, emoji });\n    },\n    async sendPrivateChat(to, text) {\n      const trimmed = text.trim();\n      if (trimmed.length === 0) return;\n      const local = store.snapshot().localIdentity;\n      const id = `${local ?? \"local\"}-${now()}`;\n      const at = new Date(now()).toISOString();\n      if (local !== null) {\n        store.addChat({ id, identity: local, displayName: identity.displayName, text: trimmed, at, to });\n      }\n      await publish(\n        DATA_TOPICS.chat,\n        { id, text: trimmed, at, name: identity.displayName, to },\n        [to],\n      );\n    },\n    async setEffects(next) {\n      const previous = store.snapshot().effects;\n      const merged: MediaEffects = { ...previous, ...next };\n      store.patch({ effects: merged });\n      options.effectsStorage?.save(merged);\n      if (driver === null) return;\n      try {\n        await applyEffects(driver, merged);\n      } catch {\n        // The camera keeps running without the effect; the choice reverts so\n        // the control never claims an effect that is not on screen.\n        const reverted: MediaEffects = { ...merged, background: previous.background, backgroundImage: previous.backgroundImage };\n        store.patch({ effects: reverted });\n        options.effectsStorage?.save(reverted);\n      }\n    },\n    supportsVideoEffects() {\n      return driver?.supportsVideoEffects?.() ?? false;\n    },\n    supportsScreenShare() {\n      // Before a room exists the browser itself is asked (a phone never shows Share screen).\n      return driver?.supportsScreenShare?.() ?? detectCapabilities().canShareScreen;\n    },\n    async switchDevice(kind, deviceId) {\n      if (driver === null) return;\n      await driver.switchDevice(kind, deviceId);\n    },\n    enableAudio: () => media.enableAudio(),\n    previewDevice: (kind, outcome) => media.preview(kind, outcome),\n    acceptDeviceOffer: () => media.acceptOffer(),\n    dismissDeviceOffer: () => media.dismissOffer(),\n    dismissDeviceNotice: () => media.dismissNotice(),\n    undoDeviceNotice: () => media.undoNotice(),\n    pin(who) {\n      store.patch({ pinned: who, layout: who === null ? \"grid\" : \"speaker\" });\n    },\n    setLayout(layout) {\n      store.patch({ layout });\n    },\n    attach(who, kind, element) {\n      if (driver === null) return () => undefined;\n      // S7: the tile is the person; its media is their main connection's.\n      return driver.attach(mainConnection.get(personOf(who)) ?? who, kind, element);\n    },\n    token: () => current,\n    async dispose() {\n      disposed = true;\n      supervisor.dispose();\n      media.stop();\n      clearGhosts();\n      if (driver !== null) {\n        const target = driver;\n        driver = null;\n        await target.disconnect();\n      }\n      store.reset();\n    },\n  };\n  return engine;\n}\n\n/** Exported for the host-power check in UI code — one definition, one rank. */\nexport function canModerate(participant: MeetParticipant | undefined): boolean {\n  return participant !== undefined && isHostRole(participant.role);\n}\n\nexport function hostUserIds(participants: readonly MeetParticipant[]): readonly UserId[] {\n  return participants\n    .filter((participant) => participant.role === \"host\" && participant.userId !== null)\n    .map((participant) => participant.userId as UserId);\n}\n","/**\n * A PARTICIPANT'S OWN MEDIA CHOICES, REMEMBERED (Meet wave 2).\n *\n * Noise suppression and the camera background are personal and per device —\n * Zoom and Meet both remember them — so they live in this browser, never on a\n * server. Blocked storage means the defaults (suppression on, no background),\n * never a failed join.\n */\n\nimport type { EffectsStorage } from \"./room\";\nimport { DEFAULT_EFFECTS, type MediaEffects } from \"./store\";\n\nfunction coerce(value: unknown): MediaEffects {\n  if (typeof value !== \"object\" || value === null) return DEFAULT_EFFECTS;\n  const row = value as Record<string, unknown>;\n  const background =\n    row[\"background\"] === \"blur\" || row[\"background\"] === \"image\" ? row[\"background\"] : \"none\";\n  const backgroundImage = typeof row[\"backgroundImage\"] === \"string\" ? row[\"backgroundImage\"] : null;\n  return {\n    noiseSuppression: row[\"noiseSuppression\"] !== false,\n    background: background === \"image\" && backgroundImage === null ? \"none\" : background,\n    backgroundImage,\n  };\n}\n\nexport function createWebEffectsStorage(key = \"mx.meet.effects\"): EffectsStorage {\n  let memory: MediaEffects = DEFAULT_EFFECTS;\n  const storage = (globalThis as { localStorage?: Storage }).localStorage;\n  return {\n    load() {\n      if (storage === undefined) return memory;\n      try {\n        const raw = storage.getItem(key);\n        return raw === null ? memory : coerce(JSON.parse(raw));\n      } catch {\n        return memory;\n      }\n    },\n    save(effects) {\n      memory = effects;\n      try {\n        storage?.setItem(key, JSON.stringify(effects));\n      } catch {\n        // Storage blocked: the choice lasts for this visit.\n      }\n    },\n  };\n}\n","/**\n * THE IN-ROOM SERVER CALLS (Meet wave 2) — host moderation and the SAVED chat.\n *\n * 🚨 **Why these are server calls and not data packets.** Through 0.7.x a host's\n * \"Mute\" and \"Remove\" were published on the room's data plane (`mx.host`) and\n * nothing anywhere listened: the buttons did nothing. A client cannot be the\n * authority on host power, and a guest cannot write the database. So both go to\n * aidream (`POST /v1/meet/moderate`, `POST|GET /v1/meet/chat`), which decides the\n * actor's role from the meeting itself, performs the act through LiveKit's server\n * API, writes what is durable, and tells the room on its own `matrx.meet.*` topic.\n *\n * A guest proves who they are with the meeting pass this server signed for them, in\n * `x-meet-pass` — a header, never a URL.\n */\n\nimport { refusalFromResponse } from \"./ai\";\nimport type { MeetApi } from \"./api\";\nimport { MeetError } from \"./errors\";\nimport { collabFromState, withItem } from \"./collab\";\nimport { chatFromRow } from \"./room-events\";\nimport type { MeetStore, RoomChatMessage } from \"./store\";\nimport { MEET_ROUTES, MEETING_PASS_HEADER } from \"./tokens\";\nimport type { ParticipantIdentity } from \"./types\";\n\n/** Every host power the server performs. One vocabulary with `services/meet/moderation.py`. */\nexport type ModerationAction =\n  | \"mute\"\n  | \"stop_video\"\n  | \"stop_screen\"\n  | \"mute_all\"\n  | \"ask_unmute\"\n  | \"ask_all_unmute\"\n  | \"spotlight\"\n  | \"sync_presenter\"\n  | \"raise_hand\"\n  | \"lower_hand\"\n  | \"lower_all_hands\"\n  | \"make_cohost\"\n  | \"make_presenter\"\n  | \"revoke_presenter\"\n  | \"set_av_lock\"\n  | \"revoke_cohost\"\n  | \"transfer_host\"\n  | \"reclaim_host\"\n  | \"rename\"\n  | \"remove\"\n  | \"report\";\n\nexport const MODERATION_ACTIONS: readonly ModerationAction[] = [\n  \"mute\",\n  \"stop_video\",\n  \"stop_screen\",\n  \"mute_all\",\n  \"ask_unmute\",\n  \"ask_all_unmute\",\n  \"spotlight\",\n  \"sync_presenter\",\n  \"raise_hand\",\n  \"lower_hand\",\n  \"lower_all_hands\",\n  \"make_cohost\",\n  \"make_presenter\",\n  \"revoke_presenter\",\n  \"set_av_lock\",\n  \"revoke_cohost\",\n  \"transfer_host\",\n  \"reclaim_host\",\n  \"rename\",\n  \"remove\",\n  \"report\",\n];\n\nexport interface ModerationRequest {\n  readonly action: ModerationAction;\n  readonly identity?: ParticipantIdentity | null | undefined;\n  readonly name?: string | undefined;\n  readonly value?: string | undefined;\n  readonly reason?: string | undefined;\n}\n\nexport interface ModerationResult {\n  readonly action: ModerationAction;\n  readonly affected: readonly string[];\n  /** The server's sentence for the actor. */\n  readonly message: string;\n}\n\nexport interface InRoomClient {\n  moderate(request: ModerationRequest): Promise<ModerationResult>;\n  /** Send a message to EVERYONE. Saved; shows at once as pending, then as saved. */\n  sendChat(text: string): Promise<void>;\n  /** Read the saved chat once per join, so a late joiner sees what was said. */\n  loadChat(): Promise<void>;\n  /**\n   * Meet wave 5: read the polls, questions, whiteboard and breakout plan this viewer\n   * may see, once per join. A refusal is written to `collab.error`, never thrown away.\n   */\n  loadCollab(): Promise<void>;\n  /**\n   * Meet wave 5: one poll / Q&A / whiteboard / breakout action. The server's answer is\n   * folded into the store at once (the room packet that follows is the same item).\n   * Returns the server's sentence; throws a `MeetError` with the server's words.\n   */\n  collab(request: CollabRequest): Promise<CollabResult>;\n  /**\n   * Meet wave 5: translate finished caption lines into `language` for this viewer.\n   * Results land in `collab.captionTranslations`; a refusal in `captionTranslationError`.\n   */\n  translateCaptions(language: string, lines: readonly { id: string; text: string }[]): Promise<void>;\n}\n\n/** Every room-item action the server performs. One vocabulary with `services/meet/collab.py`. */\nexport type CollabAction =\n  | \"poll_create\"\n  | \"poll_update\"\n  | \"poll_launch\"\n  | \"poll_close\"\n  | \"poll_share\"\n  | \"poll_vote\"\n  | \"poll_delete\"\n  | \"question_ask\"\n  | \"question_upvote\"\n  | \"question_answer\"\n  | \"question_reopen\"\n  | \"question_dismiss\"\n  | \"question_delete\"\n  | \"stroke_add\"\n  | \"stroke_erase\"\n  | \"whiteboard_clear\"\n  | \"breakout_open\"\n  | \"breakout_update\"\n  | \"breakout_broadcast\"\n  | \"breakout_move\"\n  | \"breakout_join\"\n  | \"breakout_close\"\n  | \"breakout_expire\"\n  /** HR-360 wave 2 (MD-15): move everyone's app panel to one section. */\n  | \"focus_set\";\n\nexport interface CollabRequest {\n  readonly action: CollabAction;\n  readonly itemId?: string | undefined;\n  readonly question?: string | undefined;\n  readonly options?: readonly string[] | undefined;\n  readonly multiple?: boolean | undefined;\n  readonly anonymous?: boolean | undefined;\n  readonly optionIds?: readonly string[] | undefined;\n  readonly text?: string | undefined;\n  readonly stroke?:\n    | {\n        readonly points: readonly (readonly [number, number])[];\n        readonly color: string;\n        readonly width: number;\n        readonly tool: \"pen\" | \"highlighter\";\n      }\n    | undefined;\n  readonly rooms?: readonly { readonly name: string; readonly identities: readonly string[] }[] | undefined;\n  readonly allowChoose?: boolean | undefined;\n  readonly minutes?: number | undefined;\n  readonly identity?: string | undefined;\n  /** `null` = the main room (breakout_join / breakout_move). */\n  readonly roomId?: string | null | undefined;\n  /** focus_set: the app panel's key and the section everyone looks at. */\n  readonly panel?: string | undefined;\n  readonly section?: string | undefined;\n}\n\nexport interface CollabResult {\n  readonly action: CollabAction;\n  readonly message: string;\n  readonly removed: readonly string[];\n  /** The id of the item the server returned (a created poll, a new question), or null. */\n  readonly itemId: string | null;\n}\n\nexport interface InRoomClientOptions {\n  api: MeetApi;\n  store: MeetStore;\n  /** The room pass for THIS meeting, or null (a signed-in member needs none). */\n  resolveRoomToken: () => string | null;\n  now?: (() => number) | undefined;\n}\n\nexport function createInRoomClient(options: InRoomClientOptions): InRoomClient {\n  const { api, store } = options;\n  const now = options.now ?? (() => Date.now());\n\n  function meetingId(operation: string): string {\n    const meeting = store.snapshot().meeting;\n    if (meeting === null) {\n      throw new MeetError(\n        \"not-found\",\n        `${operation}: this room has no meeting record`,\n        \"Moderation and saved chat belong to a meeting. An ad-hoc call has neither.\",\n      );\n    }\n    return meeting.id;\n  }\n\n  function headers(): Record<string, string> | undefined {\n    const token = options.resolveRoomToken();\n    return token === null ? undefined : { [MEETING_PASS_HEADER]: token };\n  }\n\n  function refusal(response: Response, operation: string, remedy: string): Promise<MeetError> {\n    return refusalFromResponse(response, operation, remedy);\n  }\n\n  // S8 PRESENTER IS TRUTH FROM THE MEDIA. Who presents is the run's (replicated room state) and\n  // the SERVER decides it from the screen-share track it sees in the room (track webhooks, and\n  // this nudge) — a client never claims it. The nudge carries no claim: \"my share may have\n  // changed, look\". It is derived from the local screen-share track, once per change, because\n  // that track also ends when the browser's own \"Stop sharing\" bar (or the shared window\n  // closing) kills it — a path no button of ours sees.\n  let toldSharing = false;\n  let tellChain: Promise<void> = Promise.resolve();\n  store.subscribe(() => {\n    const local = store.snapshot().participants.find((p) => p.isLocal);\n    const sharing = local?.screenSharing === true;\n    if (sharing === toldSharing || local === undefined) return;\n    toldSharing = sharing;\n    tellChain = tellChain\n      .then(() => client.moderate({ action: \"sync_presenter\" }))\n      .then(\n        () => undefined,\n        (error: unknown) => {\n          // Not retried on every store change (that would be a storm). The share itself is\n          // media and keeps working; the track webhook still tells the server.\n          console.warn(`[meet] the server did not take the screen-share change: ${String(error)}`);\n        },\n      );\n  });\n\n  const client: InRoomClient = {\n    async moderate(request) {\n      const operation = `meet.moderate(${request.action})`;\n      const hdrs = headers();\n      const response = await api.request({\n        path: MEET_ROUTES.moderate,\n        method: \"POST\",\n        operation,\n        body: {\n          meeting_id: meetingId(operation),\n          action: request.action,\n          ...(request.identity != null ? { identity: request.identity } : {}),\n          ...(request.name !== undefined ? { name: request.name } : {}),\n          ...(request.value !== undefined ? { value: request.value } : {}),\n          ...(request.reason !== undefined ? { reason: request.reason } : {}),\n        },\n        ...(hdrs !== undefined ? { headers: hdrs } : {}),\n      });\n      if (!response.ok) {\n        throw await refusal(\n          response,\n          operation,\n          \"Nothing was changed. The server decides host powers from the meeting itself.\",\n        );\n      }\n      const payload = (await response.json()) as Record<string, unknown>;\n      return {\n        action: request.action,\n        affected: Array.isArray(payload[\"affected\"])\n          ? payload[\"affected\"].filter((value): value is string => typeof value === \"string\")\n          : [],\n        message: typeof payload[\"message\"] === \"string\" ? payload[\"message\"] : \"Done.\",\n      };\n    },\n\n    async sendChat(text) {\n      const body = text.trim();\n      if (body.length === 0) return;\n      const operation = \"meet.sendChat\";\n      const id = meetingId(operation);\n      const snapshot = store.snapshot();\n      const me = snapshot.participants.find((p) => p.identity === snapshot.localIdentity);\n      // PENDING AT ONCE: a message that appears only after a round trip feels\n      // broken. It is marked pending (not `saved`) until the server's row lands.\n      const localId = `pending-${now()}`;\n      const pending: RoomChatMessage = {\n        id: localId,\n        identity: snapshot.localIdentity ?? (\"local\" as ParticipantIdentity),\n        displayName: me?.displayName ?? \"You\",\n        text: body,\n        at: new Date(now()).toISOString(),\n        saved: false,\n      };\n      store.addChat(pending);\n      const hdrs = headers();\n      let response: Response;\n      try {\n        response = await api.request({\n          path: MEET_ROUTES.chat,\n          method: \"POST\",\n          operation,\n          body: { meeting_id: id, body },\n          ...(hdrs !== undefined ? { headers: hdrs } : {}),\n        });\n      } catch (error) {\n        store.settleChat(localId, { failed: \"Not sent — the server could not be reached.\" });\n        throw error;\n      }\n      if (!response.ok) {\n        const error = await refusal(response, operation, \"Your message was not sent.\");\n        store.settleChat(localId, { failed: error.message });\n        throw error;\n      }\n      const saved = chatFromRow((await response.json()) as Record<string, unknown>);\n      if (saved === null) {\n        store.settleChat(localId, { failed: \"The server's answer could not be read.\" });\n        return;\n      }\n      store.settleChat(localId, saved);\n    },\n\n    async loadChat() {\n      const operation = \"meet.loadChat\";\n      const id = meetingId(operation);\n      const hdrs = headers();\n      const response = await api.request({\n        path: `${MEET_ROUTES.chat}?meeting_id=${encodeURIComponent(id)}`,\n        method: \"GET\",\n        operation,\n        ...(hdrs !== undefined ? { headers: hdrs } : {}),\n      });\n      if (!response.ok) {\n        throw await refusal(\n          response,\n          operation,\n          \"Messages sent before you joined could not be read. New messages still arrive.\",\n        );\n      }\n      const payload = (await response.json()) as { messages?: unknown };\n      const rows = Array.isArray(payload.messages) ? payload.messages : [];\n      const messages = rows\n        .map((row) =>\n          typeof row === \"object\" && row !== null ? chatFromRow(row as Record<string, unknown>) : null,\n        )\n        .filter((message): message is RoomChatMessage => message !== null);\n      store.loadChat(messages);\n    },\n\n    async loadCollab() {\n      const operation = \"meet.loadCollab\";\n      const id = meetingId(operation);\n      const hdrs = headers();\n      const response = await api.request({\n        path: `${MEET_ROUTES.collab}?meeting_id=${encodeURIComponent(id)}`,\n        method: \"GET\",\n        operation,\n        ...(hdrs !== undefined ? { headers: hdrs } : {}),\n      });\n      if (!response.ok) {\n        const error = await refusal(\n          response,\n          operation,\n          \"Polls, questions and the whiteboard could not be read. New ones still arrive.\",\n        );\n        store.patch({ collab: { ...store.snapshot().collab, loaded: true, error: error.message } });\n        throw error;\n      }\n      const body = (await response.json()) as Record<string, unknown>;\n      store.patch({ collab: collabFromState(body, store.snapshot().collab) });\n    },\n\n    async collab(request) {\n      const operation = `meet.collab(${request.action})`;\n      const hdrs = headers();\n      const response = await api.request({\n        path: MEET_ROUTES.collab,\n        method: \"POST\",\n        operation,\n        body: {\n          meeting_id: meetingId(operation),\n          action: request.action,\n          ...(request.itemId !== undefined ? { item_id: request.itemId } : {}),\n          ...(request.question !== undefined ? { question: request.question } : {}),\n          ...(request.options !== undefined ? { options: request.options } : {}),\n          ...(request.multiple !== undefined ? { multiple: request.multiple } : {}),\n          ...(request.anonymous !== undefined ? { anonymous: request.anonymous } : {}),\n          ...(request.optionIds !== undefined ? { option_ids: request.optionIds } : {}),\n          ...(request.text !== undefined ? { text: request.text } : {}),\n          ...(request.stroke !== undefined ? { stroke: request.stroke } : {}),\n          ...(request.rooms !== undefined ? { rooms: request.rooms } : {}),\n          ...(request.allowChoose !== undefined ? { allow_choose: request.allowChoose } : {}),\n          ...(request.minutes !== undefined ? { minutes: request.minutes } : {}),\n          ...(request.identity !== undefined ? { identity: request.identity } : {}),\n          ...(request.roomId !== undefined ? { room_id: request.roomId } : {}),\n          ...(request.panel !== undefined ? { panel: request.panel } : {}),\n          ...(request.section !== undefined ? { section: request.section } : {}),\n        },\n        ...(hdrs !== undefined ? { headers: hdrs } : {}),\n      });\n      if (!response.ok) {\n        throw await refusal(response, operation, \"Nothing was changed.\");\n      }\n      const payload = (await response.json()) as Record<string, unknown>;\n      const removed = Array.isArray(payload[\"removed\"])\n        ? payload[\"removed\"].filter((v): v is string => typeof v === \"string\")\n        : [];\n      let next = store.snapshot().collab;\n      const item = payload[\"item\"];\n      if (typeof item === \"object\" && item !== null) next = withItem(next, item as Record<string, unknown>);\n      if (removed.length > 0) {\n        const gone = new Set(removed);\n        next = {\n          ...next,\n          polls: next.polls.filter((p) => !gone.has(p.id)),\n          questions: next.questions.filter((q) => !gone.has(q.id)),\n          strokes: next.strokes.filter((st) => !gone.has(st.id)),\n        };\n      }\n      store.patch({ collab: next });\n      const itemId =\n        typeof item === \"object\" && item !== null && typeof (item as Record<string, unknown>)[\"id\"] === \"string\"\n          ? ((item as Record<string, unknown>)[\"id\"] as string)\n          : null;\n      return {\n        action: request.action,\n        message: typeof payload[\"message\"] === \"string\" ? payload[\"message\"] : \"Done.\",\n        removed,\n        itemId,\n      };\n    },\n\n    async translateCaptions(language, lines) {\n      if (lines.length === 0) return;\n      const operation = \"meet.translateCaptions\";\n      const hdrs = headers();\n      const response = await api.request({\n        path: MEET_ROUTES.captionsTranslate,\n        method: \"POST\",\n        operation,\n        body: { meeting_id: meetingId(operation), target_language: language, lines },\n        ...(hdrs !== undefined ? { headers: hdrs } : {}),\n      });\n      if (!response.ok) {\n        const error = await refusal(response, operation, \"Captions stay in the language they were spoken.\");\n        store.patch({\n          collab: { ...store.snapshot().collab, captionTranslationError: error.message },\n        });\n        throw error;\n      }\n      const payload = (await response.json()) as { translations?: Record<string, unknown> };\n      const current = store.snapshot().collab;\n      // A reply for a language the viewer has since left is not shown.\n      if (current.captionLanguage !== language) return;\n      const merged: Record<string, string> = { ...current.captionTranslations };\n      for (const [id, value] of Object.entries(payload.translations ?? {})) {\n        if (typeof value === \"string\") merged[id] = value;\n      }\n      store.patch({\n        collab: { ...current, captionTranslations: merged, captionTranslationError: null },\n      });\n    },\n  };\n  return client;\n}\n","/**\n * THE ONE PLACE `livekit-client` IS TOUCHED.\n *\n * Everything above this file talks to `MeetRoomDriver`. That containment is\n * what lets the engine's whole behavior — ring timeouts, admission, escalation,\n * reconnection — be proven in a node test, and it is why an SDK upgrade is a\n * single-file review rather than a package-wide audit.\n *\n * 🚨 **THE IMPORT IS DYNAMIC, DELIBERATELY.** `import type` is erased, and the\n * runtime `await import(\"livekit-client\")` happens inside `connect()`. So:\n * importing `@ai-matrx/meet` during SSR, or on a page that renders a call\n * BUTTON but never a call, pulls in none of the media SDK and touches no\n * browser API (independence contract §4). A static import here would put ~400KB\n * of WebRTC into every consumer's first load and break RSC rendering.\n *\n * The mapping helpers below are exported for their own tests: an SDK enum\n * renamed upstream must fail a named test, not silently become \"unknown\" on\n * every tile.\n */\n\nimport type {\n  ConnectionQuality as LiveKitQuality,\n  Participant,\n  Room,\n  RoomOptions,\n} from \"livekit-client\";\nimport { detectCapabilities } from \"./capabilities\";\nimport { MeetError, normalizeDeviceError, normalizeScreenShareError } from \"./errors\";\nimport {\n  TRANSCRIPTION_ATTRIBUTES,\n  TRANSCRIPTION_TOPIC,\n  type AudioProcessing,\n  type DriverConnectionState,\n  type DriverParticipant,\n  type DriverTrackKind,\n  type MeetRoomDriver,\n  type RoomDriverHandlers,\n  type VideoEffect,\n} from \"./room-driver\";\nimport type { ConnectionQuality } from \"./types\";\nimport { createReconnectPolicy } from \"./connection-supervisor\";\nimport { mergeReadings, readingFromStats, type NetworkReading, type StatsEntry } from \"./network-health\";\n\n/**\n * LiveKit's quality enum → ours. Mapped explicitly rather than cast: the SDK\n * has five states and our UI has five sentences, and an unmapped one must\n * degrade to `unknown` (an honest \"we don't know\") rather than to `excellent`\n * (a lie that hides a failing call).\n */\nexport function mapQuality(quality: LiveKitQuality | string): ConnectionQuality {\n  switch (quality) {\n    case \"excellent\":\n      return \"excellent\";\n    case \"good\":\n      return \"good\";\n    case \"poor\":\n      return \"poor\";\n    case \"lost\":\n      return \"lost\";\n    default:\n      return \"unknown\";\n  }\n}\n\nexport function mapConnectionState(state: string): DriverConnectionState {\n  switch (state) {\n    case \"connected\":\n      return \"connected\";\n    case \"connecting\":\n      return \"connecting\";\n    case \"reconnecting\":\n      return \"reconnecting\";\n    // Only the signal socket is down (S6b): its own region value, so the supervisor can tell a\n    // signal blip from a full media reconnect.\n    case \"signalReconnecting\":\n      return \"signal_reconnecting\";\n    default:\n      return \"disconnected\";\n  }\n}\n\n/**\n * A LiveKit participant → our snapshot.\n *\n * 🚨 `name` IS REPORTED EXACTLY AS LIVEKIT GAVE IT, empty string and all\n * (MRI-A18). Through 0.4.12 it fell back to the identity here, which meant a\n * driver — the thing furthest from any screen — invented a \"name\" that\n * `core/names.ts` then had to recognize and refuse. A driver reports; it does\n * not name. The one fallback lives in `projectParticipant`, and it is the name\n * book's honest placeholder rather than a token.\n */\nexport function snapshotParticipant(\n  participant: Pick<\n    Participant,\n    \"identity\" | \"name\" | \"metadata\" | \"isMicrophoneEnabled\" | \"isCameraEnabled\" | \"isScreenShareEnabled\"\n  > & { attributes?: Readonly<Record<string, string>> | undefined },\n  isLocal: boolean,\n): DriverParticipant {\n  const name = participant.name;\n  return {\n    identity: participant.identity,\n    name: name ?? \"\",\n    metadata: participant.metadata ?? null,\n    // ATTRIBUTES ARE PART OF THE SNAPSHOT, not read ad hoc later: the note-taker\n    // announces the consent notice here (D10) and the roster is the only place\n    // this package looks at a participant.\n    attributes: participant.attributes ?? {},\n    isLocal,\n    micEnabled: participant.isMicrophoneEnabled,\n    cameraEnabled: participant.isCameraEnabled,\n    screenSharing: participant.isScreenShareEnabled,\n  };\n}\n\nexport interface LiveKitDriverOptions {\n  /** Adaptive stream + dynacast default ON — R5 scale honesty, not a knob. */\n  roomOptions?: RoomOptions | undefined;\n}\n\n/** The browser defaults every call product ships with. */\nexport const DEFAULT_AUDIO_PROCESSING: AudioProcessing = {\n  noiseSuppression: true,\n  echoCancellation: true,\n  autoGainControl: true,\n};\n\n/**\n * Background effects run a segmentation model on the GPU (MediaPipe via\n * `@livekit/track-processors`). A browser without `OffscreenCanvas` or WebGL2\n * cannot — the control is then ABSENT, never a toggle that silently fails.\n */\nexport function videoEffectsSupported(): boolean {\n  const scope = globalThis as unknown as {\n    OffscreenCanvas?: unknown;\n    document?: { createElement(tag: string): { getContext(kind: string): unknown } };\n  };\n  if (typeof scope.OffscreenCanvas === \"undefined\" || scope.document === undefined) return false;\n  try {\n    return scope.document.createElement(\"canvas\").getContext(\"webgl2\") !== null;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Put the chosen effect on the local camera. The processor package is imported\n * lazily, exactly like `livekit-client` itself, so a meeting nobody blurs never\n * downloads a segmentation model.\n */\nasync function applyVideoEffect(target: Room, effect: VideoEffect): Promise<void> {\n  const { Track } = await import(\"livekit-client\");\n  const track = target.localParticipant.getTrackPublication(Track.Source.Camera)?.track as\n    | {\n        setProcessor(processor: unknown): Promise<void>;\n        stopProcessor(): Promise<void>;\n      }\n    | undefined;\n  if (track === undefined) return; // camera off: applied when it turns on.\n  try {\n    if (effect.kind === \"none\") {\n      await track.stopProcessor();\n      return;\n    }\n    const processors = await import(\"@livekit/track-processors\");\n    const processor =\n      effect.kind === \"blur\"\n        ? processors.BackgroundBlur(effect.radius ?? 12)\n        : processors.VirtualBackground(effect.imageUrl);\n    await track.setProcessor(processor);\n  } catch (error) {\n    throw new MeetError(\n      \"media-unsupported\",\n      \"The background effect could not start on this camera\",\n      \"Background effects need a browser with WebGL2 (current Chrome, Edge, Firefox or Safari). \" +\n        \"Your video continues without the effect.\",\n      error,\n    );\n  }\n}\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nexport function createLiveKitDriver(\n  handlers: RoomDriverHandlers,\n  options: LiveKitDriverOptions = {},\n): MeetRoomDriver {\n  let room: Room | null = null;\n  /**\n   * The roster projection for the CURRENT room, kept out here so `connect()`\n   * can fire it once the transport is up. See the call site for why.\n   */\n  let projectRoster: (() => void) | null = null;\n  /** What the person chose, kept so a re-enabled track gets it too. */\n  let audioCapture: AudioProcessing = DEFAULT_AUDIO_PROCESSING;\n  let videoEffect: VideoEffect = { kind: \"none\" };\n\n  /**\n   * P1 connection-network: sample this tab's path every 2 s while connected. `engine.pcManager`\n   * is the SDK's own handle on the two peer connections; a reading is skipped (never invented)\n   * while a transport is missing or reconnecting.\n   */\n  let statsTimer: ReturnType<typeof setInterval> | null = null;\n  function stopStatsPoll(): void {\n    if (statsTimer !== null) clearInterval(statsTimer);\n    statsTimer = null;\n  }\n  function startStatsPoll(target: Room): void {\n    stopStatsPoll();\n    if (handlers.networkReading === undefined) return;\n    const sample = async (): Promise<void> => {\n      if (room !== target) return;\n      const manager = (target.engine as unknown as {\n        pcManager?: { publisher?: { getStats(): Promise<RTCStatsReport> | undefined }; subscriber?: { getStats(): Promise<RTCStatsReport> | undefined } };\n      }).pcManager;\n      if (manager === undefined) return;\n      const readings: NetworkReading[] = [];\n      for (const transport of [manager.publisher, manager.subscriber]) {\n        try {\n          const report = await transport?.getStats();\n          if (report !== undefined) readings.push(readingFromStats(report.values() as Iterable<StatsEntry>));\n        } catch {\n          // A transport mid-restart has no stats; the next sample reads it.\n        }\n      }\n      if (readings.length > 0 && room === target) handlers.networkReading?.(mergeReadings(readings));\n    };\n    statsTimer = setInterval(() => void sample(), 2000);\n  }\n\n  async function load(): Promise<Room> {\n    if (room !== null) return room;\n    let module: typeof import(\"livekit-client\");\n    try {\n      module = await import(\"livekit-client\");\n    } catch (error) {\n      throw new MeetError(\n        \"misconfigured\",\n        \"livekit-client could not be loaded\",\n        \"`livekit-client` is a dependency of @ai-matrx/meet and is imported lazily at \" +\n          \"connect time. If this failed, the bundler excluded it — remove it from any \" +\n          \"`external`/`serverExternalPackages` list, or pass your own driver factory.\",\n        error,\n      );\n    }\n    const { Room: LiveKitRoom, RoomEvent, Track } = module;\n    const created = new LiveKitRoom({\n      // R5: large meetings degrade gracefully instead of melting a laptop.\n      adaptiveStream: true,\n      dynacast: true,\n      // S6b: OUR retry schedule — jittered from attempt 0 (the SDK's default has no jitter on its\n      // first two attempts), give-up limits in one place (`connection-supervisor.ts`).\n      reconnectPolicy: createReconnectPolicy(),\n      ...options.roomOptions,\n    });\n    /** LiveKit's numeric `DisconnectReason` → its NAME; a number means nothing outside this file. */\n    const reasonName = (reason: unknown): string | null =>\n      reason === undefined || reason === null\n        ? null\n        : ((module.DisconnectReason as unknown as Record<number, string> | undefined)?.[reason as number] ?? String(reason));\n\n    const emitRoster = (): void => {\n      rosterQueued = false;\n      // A roster queued just before this room was dropped belongs to nobody now.\n      if (room !== created) return;\n      const local = snapshotParticipant(created.localParticipant, true);\n      const remotes = [...created.remoteParticipants.values()].map((participant) =>\n        snapshotParticipant(participant, false),\n      );\n      // The FULL roster every time. Every one of these six events changes what\n      // a tile must render, and a delta protocol across six sources drifts.\n      handlers.participants([local, ...remotes]);\n    };\n    // 🚨 THE ROSTER WAITS FOR THE END OF LIVEKIT'S CALL STACK (`net-others-see-drop`).\n    // livekit-client's `handleParticipantDisconnected` deletes the person from\n    // `remoteParticipants`, THEN unpublishes their tracks (TrackUnsubscribed → a roster without\n    // them), and only THEN emits ParticipantDisconnected with the reason. Emitting at once made\n    // the tile vanish before anyone knew why — never held as reconnecting. One microtask later\n    // the reason is in, and a burst of events costs one roster.\n    let rosterQueued = false;\n    const roster = (): void => {\n      if (rosterQueued) return;\n      rosterQueued = true;\n      queueMicrotask(emitRoster);\n    };\n\n    // At connect the roster is projected at once (no LiveKit call stack to wait out).\n    projectRoster = emitRoster;\n\n    // 🚨 A REMOTE MICROPHONE IS PLAYED HERE, OR NOWHERE. `livekit-client` never\n    // plays a remote audio track by itself (`webAudioMix` is off by default): a\n    // subscribed track makes sound only once `track.attach()` gives it a media\n    // element. Until 0.7.10 nothing attached audio, so every meeting received\n    // everyone's audio packets and played none of them (production\n    // re-verification, 2026-09-29). Audio is NOT tied to tiles on purpose: the\n    // stage paginates and the Board strip overflows, and a person on page two\n    // must still be heard.\n    created\n      .on(RoomEvent.TrackSubscribed, (track) => {\n        if (track.kind !== Track.Kind.Audio || typeof document === \"undefined\") return;\n        if (!remoteAudioPlayback) return;\n        const element = track.attach();\n        element.setAttribute(\"data-mx-meet-audio\", \"\");\n        audioSink().appendChild(element);\n      })\n      .on(RoomEvent.TrackUnsubscribed, (track) => {\n        if (track.kind !== Track.Kind.Audio) return;\n        for (const element of track.detach()) element.remove();\n      });\n\n    created\n      .on(RoomEvent.ParticipantConnected, roster)\n      // WHY they left goes first (S6b): an unannounced drop is held as a `reconnecting` tile,\n      // and the roster that follows must already know it.\n      .on(RoomEvent.ParticipantDisconnected, (participant, reason) => {\n        handlers.participantLeft?.(participant.identity, reasonName(reason));\n        roster();\n      })\n      .on(RoomEvent.TrackSubscribed, roster)\n      .on(RoomEvent.TrackUnsubscribed, roster)\n      .on(RoomEvent.TrackMuted, roster)\n      .on(RoomEvent.TrackUnmuted, roster)\n      .on(RoomEvent.LocalTrackPublished, (publication) => {\n        // `share-stopped-by-browser`: the browser's own \"Stop sharing\" ends the share's track;\n        // unpublish it (screen and its sound) so everyone's stage and this tab's controls follow.\n        if (publication.source === Track.Source.ScreenShare) {\n          const ended = (): void => {\n            void created.localParticipant.setScreenShareEnabled(false).catch(() => undefined);\n          };\n          publication.track?.mediaStreamTrack.addEventListener(\"ended\", ended, { once: true });\n        }\n        roster();\n      })\n      .on(RoomEvent.LocalTrackUnpublished, roster)\n      // A SERVER DECISION CHANGED MID-MEETING (Meet wave 2): a co-host made or\n      // unmade, the host handed over, a rename. The server re-stamps the\n      // roster through `UpdateParticipant`; these three events carry it here.\n      .on(RoomEvent.ParticipantNameChanged, roster)\n      .on(RoomEvent.ParticipantAttributesChanged, roster)\n      .on(RoomEvent.ParticipantMetadataChanged, roster)\n      .on(RoomEvent.RoomMetadataChanged, (metadata) => {\n        handlers.roomMetadata?.(metadata ?? \"\");\n      })\n      // S6c MEDIA (the media supervisor's inputs). Autoplay: LiveKit flips this when an\n      // attached remote audio element's play() is refused, and back when startAudio() (inside\n      // a click) or a later play succeeds.\n      .on(RoomEvent.AudioPlaybackStatusChanged, (canPlay: boolean) => {\n        handlers.audioPlayback?.(canPlay);\n      })\n      .on(RoomEvent.MediaDevicesChanged, () => {\n        handlers.devicesChanged?.();\n      })\n      .on(RoomEvent.MediaDevicesError, (error: Error, kind?: MediaDeviceKind) => {\n        handlers.mediaDeviceError?.(error, kind === \"audioinput\" || kind === \"videoinput\" ? kind : null);\n      })\n      .on(RoomEvent.ActiveSpeakersChanged, (speakers) => {\n        handlers.activeSpeakers(speakers.map((speaker) => speaker.identity));\n      })\n      .on(RoomEvent.ConnectionQualityChanged, (quality, participant) => {\n        handlers.quality(participant.identity, mapQuality(quality));\n      })\n      .on(RoomEvent.ConnectionStateChanged, (state) => {\n        handlers.connectionState(mapConnectionState(state));\n      })\n      .on(RoomEvent.DataReceived, (payload, participant, _kind, topic) => {\n        handlers.data(\n          topic ?? \"\",\n          decoder.decode(payload),\n          participant?.identity ?? null,\n        );\n      })\n      .on(RoomEvent.Disconnected, (reason) => {\n        stopStatsPoll();\n        audioContainer?.remove();\n        audioContainer = null;\n        // §3.4 ER reads LiveKit's reason by NAME (`DUPLICATE_IDENTITY`, `PARTICIPANT_REMOVED`, …):\n        // the enum is numeric on the wire, and a number means nothing outside this file.\n        handlers.disconnected(reasonName(reason));\n      });\n\n    // LIVE CAPTIONS (D16). The agent publishes one text stream per utterance on\n    // `lk.transcription`, re-sending the same `lk.segment_id` as the words firm\n    // up, and the FINAL flag says which one is the last. The chunks are read as\n    // they arrive — waiting for `readAll()` would make captions appear only\n    // once the sentence was over, which is not a caption.\n    //\n    // 🚨 REGISTERED BEFORE `connect()`, deliberately: LiveKit buffers data\n    // packets that arrive before the room is connected and replays them, but a\n    // handler registered after the first stream header lands misses that\n    // utterance outright — the first thing anyone says in the meeting.\n    try {\n      created.registerTextStreamHandler(TRANSCRIPTION_TOPIC, (reader, participantInfo) => {\n        const attributes: Record<string, string> = { ...(reader.info.attributes ?? {}) };\n        const segmentId =\n          attributes[TRANSCRIPTION_ATTRIBUTES.segmentId] ?? reader.info.id;\n        const trackId = attributes[TRANSCRIPTION_ATTRIBUTES.trackId] ?? null;\n        const final = attributes[TRANSCRIPTION_ATTRIBUTES.final] === \"true\";\n        // `lk.transcribed_participant_identity` is WHO IS BEING TRANSCRIBED.\n        // The SFU's publisher identity stays the note-taker, so using it here\n        // would attribute the whole meeting to the agent. Do not use the\n        // sender-identity override: LiveKit accepts it from an agent publisher,\n        // but aidream deliberately does not set it.\n        const speakerIdentity =\n          attributes[TRANSCRIPTION_ATTRIBUTES.speakerIdentity] ?? participantInfo.identity;\n        const at = new Date(reader.info.timestamp || Date.now()).toISOString();\n        void (async () => {\n          let text = \"\";\n          try {\n            for await (const chunk of reader) {\n              text += chunk;\n              // Emit as it grows: a caption that only appears when the sentence\n              // ends is a transcript, not a caption.\n              handlers.transcription({\n                segmentId,\n                speakerIdentity,\n                publisherIdentity: participantInfo.identity,\n                text,\n                final,\n                trackId,\n                at,\n              });\n            }\n          } catch (error) {\n            // A caption stream that dies is a caption we do not have. It is\n            // never fatal to the meeting and never silent.\n            handlers.data(\n              TRANSCRIPTION_TOPIC,\n              JSON.stringify({ error: String((error as Error)?.message ?? error) }),\n              participantInfo.identity,\n            );\n          }\n        })();\n      });\n    } catch {\n      // Registering twice throws in the SDK. `load()` is single-flight through\n      // `room`, so this can only happen on a re-entrant remount — in which case\n      // the existing handler is already delivering captions.\n    }\n\n    // Kept for `attach`, which needs the SDK's Source enum at call time.\n    sources = {\n      camera: Track.Source.Camera,\n      microphone: Track.Source.Microphone,\n      screen: Track.Source.ScreenShare,\n    };\n    trackEvents = {\n      subscribed: RoomEvent.TrackSubscribed,\n      localPublished: RoomEvent.LocalTrackPublished,\n    };\n    room = created;\n    return created;\n  }\n\n  let sources: Record<DriverTrackKind, string> | null = null;\n  /** The SDK's event names `attach` listens on, captured with `sources`. */\n  let trackEvents: { subscribed: string; localPublished: string } | null = null;\n\n  /** The hidden container every remote audio element of THIS room lives in. */\n  let audioContainer: HTMLElement | null = null;\n  /** S7: false for a companion connection — no remote audio element is ever attached. */\n  let remoteAudioPlayback = true;\n  function audioSink(): HTMLElement {\n    if (audioContainer !== null && audioContainer.isConnected) return audioContainer;\n    const container = document.createElement(\"div\");\n    container.setAttribute(\"data-mx-meet-audio-sink\", \"\");\n    container.setAttribute(\"aria-hidden\", \"true\");\n    container.style.display = \"none\";\n    document.body.appendChild(container);\n    audioContainer = container;\n    return container;\n  }\n\n  function requireRoom(operation: string): Room {\n    if (room === null) {\n      throw new MeetError(\n        \"transport\",\n        `${operation}: the room is not connected`,\n        \"Call connect() first. The engine never reaches this — it gates every media call \" +\n          \"on its own phase — so seeing it means a consumer drove the driver directly.\",\n      );\n    }\n    return room;\n  }\n\n  return {\n    async connect(serverUrl, token) {\n      const target = await load();\n      try {\n        await target.connect(serverUrl, token);\n      } catch (error) {\n        // A connect failure is either media permission (user-actionable) or\n        // transport. Both must reach the UI with a sentence, never a spinner.\n        throw normalizeDeviceError(error, \"meet.connect\");\n      }\n      // 🚨 PROJECT THE ROSTER ONCE, HERE. Every other roster source is an\n      // EVENT, and a participant who publishes nothing into an empty room\n      // generates none of them: no `LocalTrackPublished`, no\n      // `ParticipantConnected`, no track events. Until 0.3.2 the join always\n      // published a microphone, so `LocalTrackPublished` fired and hid this —\n      // and the moment listen-only attendance became possible, a listen-only\n      // host was absent from their own People panel, had no tile, and got NO\n      // host controls at all (the note-taker could not be started), because\n      // host powers are read off the local participant's roster entry.\n      projectRoster?.();\n      // The room's metadata arrives WITH the join (the spotlight lives there),\n      // and `RoomMetadataChanged` fires only for later changes.\n      handlers.roomMetadata?.(target.metadata ?? \"\");\n      // S6c: the autoplay state as of the join — `AudioPlaybackStatusChanged` fires only on change.\n      handlers.audioPlayback?.(target.canPlaybackAudio);\n      startStatsPoll(target);\n    },\n    async disconnect() {\n      if (room === null) return;\n      const target = room;\n      room = null;\n      try {\n        target.unregisterTextStreamHandler(TRANSCRIPTION_TOPIC);\n      } catch {\n        // Already gone. Teardown is idempotent by contract.\n      }\n      projectRoster = null;\n      stopStatsPoll();\n      audioContainer?.remove();\n      audioContainer = null;\n      await target.disconnect();\n    },\n    async setMicrophoneEnabled(enabled) {\n      try {\n        await requireRoom(\"setMicrophoneEnabled\").localParticipant.setMicrophoneEnabled(\n          enabled,\n          audioCapture,\n        );\n      } catch (error) {\n        throw normalizeDeviceError(error, \"meet.setMicrophoneEnabled\");\n      }\n    },\n    async setCameraEnabled(enabled) {\n      try {\n        const target = requireRoom(\"setCameraEnabled\");\n        await target.localParticipant.setCameraEnabled(enabled);\n        // A REMEMBERED EFFECT FOLLOWS THE CAMERA. Turning the camera back on must\n        // not quietly show the room behind someone who chose to blur it.\n        if (enabled && videoEffect.kind !== \"none\") await applyVideoEffect(target, videoEffect);\n      } catch (error) {\n        throw normalizeDeviceError(error, \"meet.setCameraEnabled\");\n      }\n    },\n    async setScreenShareEnabled(enabled) {\n      try {\n        // Ask for the tab's sound too (`share-audio`): Chrome then offers \"Also share tab audio\".\n        await requireRoom(\"setScreenShareEnabled\").localParticipant.setScreenShareEnabled(\n          enabled,\n          enabled ? { audio: true, systemAudio: \"include\" } : undefined,\n        );\n      } catch (error) {\n        throw normalizeScreenShareError(error, \"meet.setScreenShareEnabled\");\n      }\n    },\n    async publishData(topic, payload, to) {\n      await requireRoom(\"publishData\").localParticipant.publishData(\n        // `reliable` is not optional for a control plane: a dropped\n        // \"hand lowered\" leaves a hand up on every other screen forever.\n        encoder.encode(payload) as Uint8Array<ArrayBuffer>,\n        to === undefined || to.length === 0\n          ? { reliable: true, topic }\n          : { reliable: true, topic, destinationIdentities: [...to] },\n      );\n    },\n    async setAudioProcessing(processing) {\n      audioCapture = { ...audioCapture, ...processing };\n      const target = room;\n      if (target === null) return;\n      const { Track } = await import(\"livekit-client\");\n      const publication = target.localParticipant.getTrackPublication(Track.Source.Microphone);\n      const track = publication?.track;\n      if (track === undefined || publication?.isMuted === true) return;\n      try {\n        // The browser's own processing, applied to the LIVE track: a restart\n        // with new constraints, the same device, no renegotiation.\n        await (track as unknown as { restartTrack(options: object): Promise<void> }).restartTrack({\n          ...audioCapture,\n          ...(target.getActiveDevice(\"audioinput\") !== undefined\n            ? { deviceId: target.getActiveDevice(\"audioinput\") }\n            : {}),\n        });\n      } catch (error) {\n        throw normalizeDeviceError(error, \"meet.setAudioProcessing\");\n      }\n    },\n    async setVideoEffect(effect) {\n      videoEffect = effect;\n      const target = room;\n      if (target === null) return;\n      await applyVideoEffect(target, effect);\n    },\n    supportsVideoEffects() {\n      return videoEffectsSupported();\n    },\n    screenShareHasAudio() {\n      const target = room;\n      if (target === null) return false;\n      // `Track.Source.ScreenShareAudio`, by value: the SDK enum is not in scope outside connect().\n      return target.localParticipant.getTrackPublications().some((p) => String(p.source) === \"screen_share_audio\" && p.track !== undefined);\n    },\n    supportsScreenShare() {\n      // iOS Safari and most phones have no `getDisplayMedia` at all.\n      // A phone browser that exposes it still cannot present (`share-unsupported-mobile`).\n      return detectCapabilities().canShareScreen;\n    },\n    attach(identity, kind, element) {\n      const target = requireRoom(\"attach\");\n      const source = sources?.[kind];\n      if (source === undefined) return () => undefined;\n      // 🚨 THE TRACK MAY NOT EXIST YET, AND MAY BE REPLACED LATER. A tile\n      // renders as soon as the roster says the camera is on — which is known\n      // from the PUBLICATION, before the track is SUBSCRIBED — and the tile's\n      // element stays mounted, so its ref never runs again. Until 0.7.10 an\n      // attach that found no track returned a no-op for good: a person\n      // admitted from the waiting room was a black tile for everyone already\n      // inside (production re-verification, 2026-09-29). So the attach keeps\n      // listening for this participant's track and (re)attaches whenever it\n      // arrives or is republished; the returned cleanup stops listening too.\n      let current: { detach(element: HTMLMediaElement): unknown } | null = null;\n      const sync = (): void => {\n        const participant =\n          target.localParticipant.identity === identity\n            ? target.localParticipant\n            : target.remoteParticipants.get(identity);\n        const track = participant?.getTrackPublication(source as never)?.track;\n        if (track === undefined || track === current) return;\n        current?.detach(element);\n        track.attach(element);\n        current = track;\n      };\n      const onTrack = (...args: unknown[]): void => {\n        // TrackSubscribed(track, publication, participant) /\n        // LocalTrackPublished(publication, participant) — the participant is\n        // always the last argument.\n        const who = args[args.length - 1] as { identity?: string } | undefined;\n        if (who?.identity === identity) sync();\n      };\n      sync();\n      const events = trackEvents;\n      if (events !== null) {\n        target.on(events.subscribed as never, onTrack as never);\n        target.on(events.localPublished as never, onTrack as never);\n      }\n      // The DETACH IS THE RETURN VALUE — a React effect's cleanup cannot forget\n      // to call something it was handed.\n      return () => {\n        if (events !== null) {\n          target.off(events.subscribed as never, onTrack as never);\n          target.off(events.localPublished as never, onTrack as never);\n        }\n        current?.detach(element);\n        current = null;\n      };\n    },\n    activeDevices() {\n      const target = room;\n      if (target === null) {\n        return { audioinput: null, videoinput: null, audiooutput: null };\n      }\n      return {\n        audioinput: target.getActiveDevice(\"audioinput\") ?? null,\n        videoinput: target.getActiveDevice(\"videoinput\") ?? null,\n        audiooutput: target.getActiveDevice(\"audiooutput\") ?? null,\n      };\n    },\n    async switchDevice(kind, deviceId) {\n      try {\n        await requireRoom(\"switchDevice\").switchActiveDevice(kind, deviceId);\n      } catch (error) {\n        throw normalizeDeviceError(error, \"meet.switchDevice\");\n      }\n    },\n    setRemoteAudioPlayback(enabled) {\n      remoteAudioPlayback = enabled;\n      if (enabled || audioContainer === null) return;\n      for (const element of Array.from(audioContainer.querySelectorAll(\"[data-mx-meet-audio]\"))) {\n        if (element instanceof HTMLMediaElement) element.srcObject = null;\n        element.remove();\n      }\n    },\n    async startAudio() {\n      // S6c: inside the person's click. LiveKit plays every attached remote audio element and\n      // resumes its AudioContext; success flips `AudioPlaybackStatusChanged` back to true.\n      const target = room;\n      if (target === null) return;\n      await target.startAudio();\n    },\n  };\n}\n\n/**\n * THE PRE-JOIN CAMERA PREVIEW (Meet wave 2) — the same SDK track and the same\n * background processor the room will use, so what someone sees before joining\n * is exactly what the meeting will see. Lives here because this file is the one\n * place `livekit-client` is touched.\n */\nexport interface CameraPreview {\n  attach(element: HTMLVideoElement): void;\n  setEffect(effect: VideoEffect): Promise<void>;\n  stop(): void;\n}\n\nexport async function createCameraPreview(\n  deviceId: string | null,\n  effect: VideoEffect,\n): Promise<CameraPreview> {\n  let module: typeof import(\"livekit-client\");\n  try {\n    module = await import(\"livekit-client\");\n  } catch (error) {\n    throw new MeetError(\n      \"misconfigured\",\n      \"livekit-client could not be loaded for the camera preview\",\n      \"The bundler excluded `livekit-client`; remove it from any `external` list.\",\n      error,\n    );\n  }\n  let track: Awaited<ReturnType<typeof module.createLocalVideoTrack>>;\n  try {\n    track = await module.createLocalVideoTrack(deviceId === null ? {} : { deviceId });\n  } catch (error) {\n    throw normalizeDeviceError(error, \"meet.cameraPreview\");\n  }\n  const target = track as unknown as {\n    setProcessor(processor: unknown): Promise<void>;\n    stopProcessor(): Promise<void>;\n  };\n  async function apply(next: VideoEffect): Promise<void> {\n    if (next.kind === \"none\") {\n      await target.stopProcessor();\n      return;\n    }\n    const processors = await import(\"@livekit/track-processors\");\n    await target.setProcessor(\n      next.kind === \"blur\"\n        ? processors.BackgroundBlur(next.radius ?? 12)\n        : processors.VirtualBackground(next.imageUrl),\n    );\n  }\n  if (effect.kind !== \"none\" && videoEffectsSupported()) {\n    try {\n      await apply(effect);\n    } catch {\n      // The preview still shows the camera; the settings say the effect failed.\n    }\n  }\n  return {\n    attach(element) {\n      track.attach(element);\n    },\n    setEffect: apply,\n    stop() {\n      track.stop();\n      track.detach();\n    },\n  };\n}\n","/**\n * THE OBSERVATION ROOT (CORE-DESIGN §5.6, step S0).\n *\n * Exactly one `[data-meet-root]` per tab on a meeting page, carrying the\n * HARNESS-CONTRACT's attributes derived from the store (`core/observation.ts`).\n * The package renders it once — `<MeetingRoom>` wraps every screen in it, and a\n * consumer that draws its own screen around the room (link resolution, the\n * guest-name step, a Board layout) wraps that screen in `<MeetRoot>` too, with\n * a `phase` when there is no store yet.\n *\n * The wrapper is `display: contents`: it generates no box, so no layout, size\n * or stacking changes; it exists only to carry the attributes. It also\n * publishes `window.__matrxMeet` — diagnostics only, never a verdict.\n */\n\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { copyText } from \"@ai-matrx/kit/clipboard\";\nimport { detectCapabilities, unsupportedWords, type MeetCapabilities } from \"../core/capabilities\";\nimport {\n  observe,\n  rootAttributes,\n  staticObservation,\n  type MeetObservation,\n  type ObservedPhase,\n} from \"../core/observation\";\nimport type { MeetingRecord } from \"../core/types\";\nimport { useMeetSnapshot } from \"./provider\";\n\nexport interface CoreRootOptions {\n  /** The row the consumer resolved (the guest lane has no other copy). */\n  readonly meeting?: MeetingRecord | null | undefined;\n  /** A screen the consumer renders before any store exists (resolving, a dead link). */\n  readonly phase?: ObservedPhase | undefined;\n  readonly reason?: string | null | undefined;\n}\n\n/** The observation for this tab, one stable object per change. */\nexport function useCoreObservation(options: CoreRootOptions = {}): MeetObservation {\n  const snapshot = useMeetSnapshot();\n  const { meeting, phase, reason } = options;\n  return useMemo(\n    () =>\n      phase !== undefined\n        ? staticObservation(phase, reason ?? null)\n        : observe({ snapshot, meeting: meeting ?? null }),\n    [snapshot, meeting, phase, reason],\n  );\n}\n\n/** The root element's `data-meet-*` attributes. Spread onto ONE element per tab. */\nexport function useCoreRootProps(options: CoreRootOptions = {}): Record<string, string> {\n  const observation = useCoreObservation(options);\n  return useMemo(() => rootAttributes(observation), [observation]);\n}\n\ninterface MeetDiagnostics {\n  readonly contract: \"HARNESS-CONTRACT\";\n  snapshot(): { readonly observation: MeetObservation; readonly storePhase: string | null };\n  /** Not derived before CORE-DESIGN step S6a — an empty list here means \"not computed\", not \"none\". */\n  readonly activeCatalogStates: readonly string[];\n  readonly activeCatalogStatesDerived: false;\n}\n\n/** `<MeetRoot>` — the one observation root. Generates no box. */\nexport function MeetRoot({\n  children,\n  ...options\n}: CoreRootOptions & { children?: ReactNode }): ReactNode {\n  const snapshot = useMeetSnapshot();\n  const probed = useCapabilities();\n  const base = useCoreObservation(options);\n  // CG (`browser-unsupported`): a browser that cannot run a call is told so BEFORE any name step,\n  // pre-join or Join button — on every screen this root wraps, whoever renders it.\n  const unsupported = probed !== null && !probed.canJoin;\n  const observation = useMemo<MeetObservation>(\n    () => (unsupported ? { ...staticObservation(\"unsupported\", probed?.reason ?? null) } : base),\n    [unsupported, probed, base],\n  );\n  const attrs = useMemo(() => rootAttributes(observation), [observation]);\n  const latest = useRef({ observation, storePhase: snapshot?.phase ?? null });\n  latest.current = { observation, storePhase: snapshot?.phase ?? null };\n\n  useEffect(() => {\n    if (typeof window === \"undefined\") return undefined;\n    const diagnostics: MeetDiagnostics = {\n      contract: \"HARNESS-CONTRACT\",\n      snapshot: () => latest.current,\n      activeCatalogStates: [],\n      activeCatalogStatesDerived: false,\n    };\n    const target = window as unknown as { __matrxMeet?: MeetDiagnostics };\n    target.__matrxMeet = diagnostics;\n    return () => {\n      if (target.__matrxMeet === diagnostics) delete target.__matrxMeet;\n    };\n  }, []);\n\n  return (\n    <div {...attrs} style={{ display: \"contents\" }}>\n      {unsupported && probed !== null ? <UnsupportedBrowser capabilities={probed} /> : children}\n    </div>\n  );\n}\n\n/** This browser's capabilities, read after mount (a server render knows nothing; no hydration drift). */\nexport function useCapabilities(): MeetCapabilities | null {\n  const [found, setFound] = useState<MeetCapabilities | null>(null);\n  useEffect(() => {\n    setFound(detectCapabilities());\n  }, []);\n  return found;\n}\n\n/** The screen for a browser that cannot join: what to open instead, and the link to copy. */\nfunction UnsupportedBrowser({ capabilities }: { capabilities: MeetCapabilities }): ReactNode {\n  const words = unsupportedWords(capabilities);\n  const [copied, setCopied] = useState(false);\n  const href = typeof window === \"undefined\" ? \"\" : window.location.href;\n  return (\n    <div className=\"mx-meet\">\n      <div className=\"mx-meet__waiting\" data-meet-exit=\"unsupported\">\n        <h1 className=\"mx-meet__prejoin-title\">{words.title}</h1>\n        <p className=\"mx-meet__hint\" role=\"status\" data-meet-notice=\"browser-unsupported\">\n          {words.body}\n        </p>\n        {href.length > 0 ? (\n          <button\n            type=\"button\"\n            className=\"mx-meet__primary\"\n            onClick={() => {\n              void copyText(href).then((copied) => copied && setCopied(true));\n            }}\n          >\n            {copied ? \"Link copied\" : \"Copy link\"}\n          </button>\n        ) : null}\n      </div>\n    </div>\n  );\n}\n","/**\n * THE OBSERVATION CONTRACT, DERIVED FROM TODAY'S STORE (CORE-DESIGN §7 step S0).\n *\n * The real-browser scenario harness reads a meeting through a small set of\n * `data-meet-*` attributes (common-docs `meet/duplicates/HARNESS-CONTRACT.md`,\n * owned by the harness lane). This module turns the store's `MeetSnapshot`\n * into exactly those values — pure, framework-free, rendered ONCE by the\n * package (`useCoreRootProps()` / `<MeetRoot>`), never per skin.\n *\n * S0 rule: TODAY'S VALUES ONLY. Every value here is what the person actually\n * sees on today's screens, including today's defects — a `failed` or `left`\n * room renders the pre-join screen, so its phase is `prejoin`, and the harness\n * records that as the defect it is. A value the store does not know (host\n * presence before joining, autoplay blocking) is OMITTED rather than guessed:\n * an absent attribute reads as \"unknown\", a guessed one would lie.\n */\n\nimport type { DevicePreview, LocalTrackState, PermissionReading } from \"./attendance\";\nimport { deviceNoticeCode, deviceUnavailableReason } from \"./media-supervisor\";\nimport type { ConnectionRegion, MeetSnapshot } from \"./store\";\nimport { isLivePhase, isWaitingPhase, reasonOf, type MeetPhase } from \"./phase\";\nimport { effectiveRole, effectiveStanding } from \"./store\";\nimport { consentPending, isLockedFor, mayAdmitNow } from \"./live-policy\";\nimport { isLinkFollower } from \"./types\";\nimport type {\n  ConnectionQuality,\n  MeetParticipant,\n  MeetingRecord,\n  ParticipantRole,\n  ParticipantStanding,\n} from \"./types\";\n\n/**\n * `data-meet-role` is the HARNESS CONTRACT's vocabulary (host · cohost · participant · guest):\n * a link follower whose role is `participant` renders `guest` (CORE-DESIGN §2.1); `presenter` /\n * `viewer` render `participant` until the contract adopts them (§3.7 C3).\n */\nexport type ObservedRole = \"host\" | \"cohost\" | \"presenter\" | \"participant\" | \"guest\";\n\nexport function observedRole(role: ParticipantRole, standing: ParticipantStanding | null | undefined): ObservedRole {\n  if (role === \"host\" || role === \"cohost\" || role === \"presenter\") return role;\n  return isLinkFollower(standing) ? \"guest\" : \"participant\";\n}\n\n/** `data-meet-phase` — the core's phase IS the contract value (S6a: no translation layer). */\nexport type ObservedPhase = MeetPhase;\n\nexport type ObservedConnection = ConnectionRegion;\n\nexport interface MeetObservation {\n  readonly phase: ObservedPhase;\n  readonly reason: string | null;\n  readonly role: ObservedRole | \"none\";\n  readonly connection: ObservedConnection;\n  /** null = this tab does not know (it is not in the room). */\n  readonly hostPresent: boolean | null;\n  readonly lobbyCount: number;\n  readonly recording: boolean;\n  /** null = today's store does not track autoplay blocking. */\n  readonly audioBlocked: boolean | null;\n  /** null outside `joining` / `in_call` — no device is in play there today. */\n  readonly camera: string | null;\n  readonly microphone: string | null;\n}\n\nexport interface ObserveInput {\n  readonly snapshot: MeetSnapshot | null;\n  /** The row the consumer resolved, when the store has none yet (the guest lane). */\n  readonly meeting?: MeetingRecord | null | undefined;\n}\n\n/**\n * The store's device state → the contract's `camera` / `microphone` value (CORE-DESIGN §3.2).\n * The reason comes from the media supervisor (S6c), which reads the browser's permission store: a\n * kind the browser denies is `unavailable:denied` even when nothing tried to open it.\n */\nexport function observedDevice(\n  track: LocalTrackState,\n  permission: PermissionReading = \"unknown\",\n  held: \"locked\" | \"muted_by_host\" | null = null,\n): string {\n  if (held === \"locked\") return \"locked\";\n  if (track.enabled) return \"on\";\n  if (held === \"muted_by_host\") return \"muted_by_host\";\n  const reason = deviceUnavailableReason(track, permission);\n  return reason === null ? \"muted_by_me\" : `unavailable:${reason}`;\n}\n\n/**\n * The pre-join check → the contract's `camera` / `microphone` value (P1 `perm-*`, `device-none-found`,\n * `device-busy`). `prompting` = the browser is asking; null = nothing was tried and nothing is known.\n */\nexport function observedPreview(preview: DevicePreview, permission: PermissionReading = \"unknown\"): string | null {\n  if (permission === \"denied\") return \"unavailable:denied\";\n  switch (preview.state) {\n    case \"on\":\n      return \"on\";\n    case \"off\":\n      return \"muted_by_me\";\n    case \"prompting\":\n      return \"prompting\";\n    case \"unavailable\":\n      return `unavailable:${preview.unavailable?.reason ?? \"failed\"}`;\n    default:\n      return null;\n  }\n}\n\n/** Does this snapshot's meeting row say it is over? */\nfunction endedRecord(snapshot: MeetSnapshot | null, given: MeetingRecord | null): boolean {\n  const record = snapshot?.meeting ?? given;\n  return record !== null && record.endedAt !== null;\n}\n\n/**\n * The phase the person is looking at: the store's phase, verbatim (CORE-DESIGN §3.1). The one\n * derivation left is the ended meeting: a row that says it is over renders `ended` for anyone not\n * in a live connection, whichever carrier delivered the ending first.\n */\nexport function observedPhase(input: ObserveInput): ObservedPhase {\n  const { snapshot } = input;\n  if (snapshot === null) return \"resolving\";\n  const phase = snapshot.phase;\n  if (endedRecord(snapshot, input.meeting ?? null) && !isLivePhase(phase) && !isCallPhase(phase)) return \"ended\";\n  return phase;\n}\n\nfunction isCallPhase(phase: MeetPhase): boolean {\n  return phase.startsWith(\"ringing_\") || phase.startsWith(\"call_\") || phase === \"answered_elsewhere\";\n}\n\nconst ADMITTER_ROLES: ReadonlySet<ParticipantRole> = new Set([\"host\", \"cohost\"]);\n\nexport function observe(input: ObserveInput): MeetObservation {\n  const { snapshot } = input;\n  const phase = observedPhase(input);\n  const inCall = phase === \"in_call\";\n  const actual: ParticipantRole | \"none\" = inCall && snapshot !== null ? effectiveRole(snapshot) : \"none\";\n  const canAdmit = snapshot !== null && mayAdmitNow(actual, snapshot.participants, snapshot.livePolicy);\n  const role: ObservedRole | \"none\" =\n    actual === \"none\" || snapshot === null ? \"none\" : observedRole(actual, effectiveStanding(snapshot));\n  const deviceInPlay = phase === \"joining\" || inCall;\n  const region = snapshot?.mediaRegion;\n  const atPrejoin = phase === \"prejoin\" && region !== undefined;\n  return {\n    phase,\n    reason: phase === \"ended\" ? (snapshot?.reason ?? null) : (snapshot?.reason ?? reasonOf(phase)),\n    role,\n    // `net-blip`: in the call, a drop shorter than `reconnect_banner_delay_ms` is not something the\n    // person sees — the contract says what is on screen, so it reads `stable` until the banner shows.\n    connection: snapshot === null\n      ? \"stable\"\n      : inCall && snapshot.connection !== \"stable\" && !snapshot.connectionBanner\n        ? \"stable\"\n        : snapshot.connection,\n    hostPresent: inCall && snapshot !== null\n      ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role))\n      : snapshot !== null && isWaitingPhase(snapshot.phase)\n        ? (snapshot.waiting?.admittersPresent ?? null)\n        : null,\n    lobbyCount: canAdmit && snapshot !== null\n      ? snapshot.lobby.filter((entry) => entry.state === \"knocking\").length\n      : 0,\n    recording: snapshot?.recording === \"recording\" || snapshot?.recording === \"stopping\",\n    // S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).\n    audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === \"blocked\" : null,\n    camera: deviceInPlay && snapshot !== null\n      ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera, lockedFor(snapshot, \"camera\", inCall))\n      : atPrejoin ? observedPreview(region.preview.camera, region.permission.camera) : null,\n    microphone: deviceInPlay && snapshot !== null\n      ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone, lockedFor(snapshot, \"microphone\", inCall))\n      : atPrejoin ? observedPreview(region.preview.microphone, region.permission.microphone) : null,\n  };\n}\n\n/** The organizer's lock (or a host's mute) as the person's own device state. */\nfunction lockedFor(snapshot: MeetSnapshot, kind: \"microphone\" | \"camera\", inCall: boolean): \"locked\" | \"muted_by_host\" | null {\n  if (!inCall) return null;\n  const role = effectiveRole(snapshot);\n  if (isLockedFor(snapshot.livePolicy, role, kind)) return \"locked\";\n  if (\n    snapshot.livePolicy.recordingConsent === \"view_only_until_agree\" &&\n    consentPending(snapshot.livePolicy, role, snapshot.recording === \"recording\", snapshot.recordingConsentGiven)\n  ) {\n    return \"locked\";\n  }\n  if (kind === \"microphone\" && snapshot.mutedByHost) return \"muted_by_host\";\n  return null;\n}\n\n/** A phase the consumer renders itself (link resolution, the guest-name step, a dead link). */\nexport function staticObservation(phase: ObservedPhase, reason: string | null = null): MeetObservation {\n  return {\n    phase,\n    reason,\n    role: \"none\",\n    connection: phase === \"disconnected\" ? \"server_unreachable\" : \"stable\",\n    hostPresent: null,\n    lobbyCount: 0,\n    recording: false,\n    audioBlocked: null,\n    camera: null,\n    microphone: null,\n  };\n}\n\n/** The root element's attributes. Unknown values are omitted, never guessed. */\nexport function rootAttributes(o: MeetObservation): Record<string, string> {\n  const attrs: Record<string, string> = {\n    \"data-meet-root\": \"\",\n    \"data-meet-phase\": o.phase,\n    \"data-meet-role\": o.role,\n    \"data-meet-connection\": o.connection,\n    \"data-meet-lobby-count\": String(o.lobbyCount),\n    \"data-meet-recording\": String(o.recording),\n  };\n  if (o.reason !== null) attrs[\"data-meet-reason\"] = o.reason;\n  if (o.hostPresent !== null) attrs[\"data-meet-host-present\"] = String(o.hostPresent);\n  if (o.audioBlocked !== null) attrs[\"data-meet-audio-blocked\"] = String(o.audioBlocked);\n  if (o.camera !== null) attrs[\"data-meet-camera\"] = o.camera;\n  if (o.microphone !== null) attrs[\"data-meet-microphone\"] = o.microphone;\n  attrs[\"data-meet-regions\"] = JSON.stringify({\n    connection: o.connection,\n    camera: o.camera,\n    mic: o.microphone,\n    audio_output: o.audioBlocked === null ? null : o.audioBlocked ? \"blocked\" : \"playing\",\n    recording: o.recording,\n  });\n  return attrs;\n}\n\n/** The contract's per-person connection vocabulary. `unknown` is not a reading. */\nexport function observedQuality(quality: ConnectionQuality): string | null {\n  switch (quality) {\n    case \"excellent\":\n    case \"good\":\n      return \"good\";\n    case \"poor\":\n      return \"poor\";\n    case \"lost\":\n      return \"lost\";\n    default:\n      return null;\n  }\n}\n\n/** `[data-meet-participant]` attributes for one person's tile or roster row. */\nexport function participantAttributes(p: MeetParticipant): Record<string, string> {\n  const attrs: Record<string, string> = {\n    \"data-meet-participant\": \"\",\n    \"data-meet-participant-identity\": p.identity,\n    \"data-meet-participant-name\": p.displayName,\n    \"data-meet-participant-role\": observedRole(p.role, p.standing),\n    \"data-meet-participant-self\": String(p.isLocal),\n  };\n  // A person who dropped without leaving is `reconnecting` (S6b), whatever their last quality was.\n  const quality = p.reconnecting === true ? \"reconnecting\" : observedQuality(p.quality);\n  if (quality !== null) attrs[\"data-meet-participant-connection\"] = quality;\n  return attrs;\n}\n\n/** The listen-only notice's contract code, from why the microphone is off. */\nexport function microphoneNoticeCode(track: LocalTrackState, permission: PermissionReading = \"unknown\"): \"mic-blocked\" | \"device-lost\" | null {\n  const reason = deviceUnavailableReason(track, permission);\n  if (reason === null) return null;\n  return deviceNoticeCode(\"microphone\", reason) === \"mic-blocked\" ? \"mic-blocked\" : \"device-lost\";\n}\n","\"use client\";\n\n/**\n * THE HOOKS. Thin shells over the framework-free core — every one of them\n * exists so a consumer never writes the sequence itself.\n *\n * The rule that shapes this file: a hook returns DATA and ACTIONS, never a\n * \"you must also call this on unmount\" instruction. `useTrack` hands back a ref\n * callback whose cleanup is the detach; `useRoom` disposes with the component.\n * A correct-usage checklist in a README is a bug waiting for a deadline.\n *\n * 🚨 **NO HOOK IN THIS FILE THROWS WHEN THE PROVIDER IS INERT** (0.2.1).\n * `<MeetProvider>` is deliberately inert until a client, an organization and an\n * identity are all real — which is EVERY server render, every signed-out\n * visitor, and every moment before the active organization hydrates. Through\n * 0.2.0 these hooks called `useRequiredMeetHost()`, so the exact three-line\n * integration the README prescribes returned a 500 on every route for every\n * such visitor, and the first real consumer had to wrap our own components in\n * a host-side guard (register MRI-D1). A hook now reports an inert runtime as\n * DATA — empty lists, `canCall: false`, `available: false` — so the components\n * above render nothing or an honest sentence on their own. Only an ACTION\n * invoked with no runtime fails, and it fails loudly with a remedy; it can not\n * be reached from a surface that renders correctly.\n */\n\nimport type { MeetPhase } from \"../core/phase\";\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport { useRealtimeManager } from \"@ai-matrx/data/realtime/react\";\nimport { createStreamLevelMeter } from \"@ai-matrx/browser-audio/core\";\nimport { meetingTopic } from \"../core/channels\";\nimport {\n  createMeetingRecordCache,\n  type MeetingRecordAnswer,\n  type MeetingRecordCache,\n} from \"../core/record-cache\";\nimport type { MeetAnswerCoverage } from \"../core/ai\";\nimport { type BrowserFamily, type OsFamily, webMediaPlatform } from \"../core/media-supervisor\";\nimport { isObserverRole } from \"../core/types\";\nimport { IDLE_MEDIA, IDLE_MEDIA_REGION, listenOnlyNotice, type LocalMediaState, type MediaRegionState } from \"../core/attendance\";\nimport { MeetError } from \"../core/errors\";\nimport {\n  noteTakerLabel,\n  noteTakerParticipant,\n  noteTakerStatus,\n  type NoteTakerStatus,\n} from \"../core/note-taker\";\nimport { displayNameFor, type NameBook } from \"../core/names\";\nimport { readableTranscript } from \"../core/transcript\";\nimport { resolveCaptionsState } from \"../core/captions-state\";\n\n/** A stable empty book, so `useMemo` does not re-run on every render. */\nconst EMPTY_NAMES: NameBook = {};\nimport { END_MEETING_NOT_SERVED } from \"../core/meetings\";\nimport { computeStage, DEFAULT_PAGE_SIZE, type Stage } from \"../core/layout\";\nimport { canModerateParticipant } from \"../core/meetings\";\nimport { canChat as canChatUnder, canShareUnder, consentPending, DEFAULT_LIVE_POLICY, isLockedFor, mayAdmitNow, minutesLeft, type ChatMode } from \"../core/live-policy\";\nimport { DEFAULT_LEAVE_POLICY, leaveChoices, type LeaveChoice, type LeavePolicy } from \"../core/leave\";\nimport { isRecordingInFlight, recordingLabel } from \"../core/recording\";\nimport type { MeetingSession } from \"../core/meetings\";\nimport type { JoinRequest, RoomEngine } from \"../core/room\";\nimport type { ModerationRequest, ModerationResult } from \"../core/in-room\";\nimport {\n  DEFAULT_EFFECTS,\n  effectiveRole,\n  effectiveStanding,\n  REACTION_TTL_MS,\n  type MediaEffects,\n  type MeetSnapshot,\n  type MeetWaiting,\n  type ModerationNotice,\n} from \"../core/store\";\nimport { isHostRole } from \"../core/types\";\nimport {\n  guestRecordAccessSetting,\n  activeWrapUpSummary,\n  loadGuestMeetingRecord,\n  loadMeetingRecordParts,\n  setGuestRecordAccess,\n  type GuestRecordAccessResolution,\n  type GuestRecordAccessSetting,\n  type MeetingRecordBundle,\n} from \"../core/record\";\nimport type {\n  CallInvite,\n  CallMode,\n  LobbyEntry,\n  MeetParticipant,\n  MeetingId,\n  MeetingNote,\n  MeetingRecord,\n  OrganizationId,\n  ParticipantIdentity,\n  RoomName,\n  StageLayout,\n  TranscriptSource,\n  UserId,\n  WrapUpAnnouncement,\n} from \"../core/types\";\nimport {\n  useCanRecord,\n  useIsHost,\n  useRole,\n  useMeetHost,\n  useMeetSnapshot,\n  type MeetHost,\n} from \"./provider\";\n\n/**\n * The ONE sentence every hook says when an action is invoked with no runtime.\n * It names the state and the fix; it never returns a silent no-op, because a\n * button that quietly does nothing is the failure this package exists to avoid.\n */\nconst NO_RUNTIME_REMEDY =\n  \"Render this inside a <MeetProvider> that has a Supabase client, an organization id and \" +\n  \"an identity (userId or guestName). The provider stays inert until all three are real, \" +\n  \"and while it is inert this package's components render nothing rather than a dead control.\";\n\nfunction noRuntime(action: string): MeetError {\n  return new MeetError(\n    \"misconfigured\",\n    `[@ai-matrx/meet] ${action}: there is no meet runtime on this tree.`,\n    NO_RUNTIME_REMEDY,\n  );\n}\n\nfunction requireHost(host: MeetHost | null, action: string): MeetHost {\n  if (host === null) throw noRuntime(action);\n  return host;\n}\n\nfunction requireEngine(engine: RoomEngine | null, action: string): RoomEngine {\n  if (engine === null) throw noRuntime(action);\n  return engine;\n}\n\nfunction requireSession(session: MeetingSession | null, action: string): MeetingSession {\n  if (session === null) throw noRuntime(action);\n  return session;\n}\n\nexport interface UseRoomResult {\n  /** The contract phase, verbatim (CORE-DESIGN §3.1). */\n  readonly phase: MeetPhase;\n  readonly participants: readonly MeetParticipant[];\n  readonly failure: { readonly message: string; readonly remedy: string } | null;\n  /** S7: already in this meeting on another tab or device — the pre-join offers the choice. */\n  readonly secondDevice: { readonly rule: string } | null;\n  join: (request: JoinRequest) => Promise<void>;\n  /** S7: offer Switch here / Join here too BEFORE Join when another tab of this browser has the person live. */\n  checkElsewhere: (roomName: RoomName) => Promise<boolean>;\n  leave: () => Promise<void>;\n  toggleMicrophone: () => Promise<void>;\n  toggleCamera: () => Promise<void>;\n  toggleScreenShare: () => Promise<void>;\n  /** False where the browser cannot share a screen at all (iOS), or the meeting's rule keeps this person from it: the control is absent. */\n  readonly canShareScreen: boolean;\n  /** Someone ELSE is presenting right now, under a one-at-a-time rule: pressing Share asks first (`share-takeover`). */\n  /** False when the meeting's `share_who_can` rule keeps this person from presenting (the control is absent; no \"present from a computer\" hint either). */\n  readonly sharingAllowed: boolean;\n  readonly otherPresenter: { readonly name: string; readonly rule: \"one_takeover\" | \"one_replace\" } | null;\n  toggleHand: () => Promise<void>;\n  react: (emoji: string) => Promise<void>;\n  /** To EVERYONE — saved through the server (Meet wave 2). */\n  sendChat: (text: string) => Promise<void>;\n  /** To ONE person — data plane only, never saved. */\n  sendPrivateChat: (to: ParticipantIdentity, text: string) => Promise<void>;\n  pin: (identity: ParticipantIdentity | null) => void;\n  setLayout: (layout: StageLayout) => void;\n  readonly local: MeetParticipant | null;\n}\n\n/** `share-takeover`: who is presenting if it is somebody else and the rule allows only one at a time. */\nfunction otherPresenterOf(snapshot: MeetSnapshot | null): UseRoomResult[\"otherPresenter\"] {\n  if (snapshot === null || snapshot.presenter === null || snapshot.presenter === snapshot.localIdentity) return null;\n  const rule = snapshot.livePolicy.shareConcurrency;\n  if (rule === \"multiple\") return null;\n  const who = snapshot.participants.find((p) => p.identity === snapshot.presenter);\n  return who === undefined ? null : { name: who.displayName, rule };\n}\n\nexport function useRoom(): UseRoomResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const engine = host?.engine ?? null;\n\n  const local =\n    snapshot?.participants.find(\n      (participant) => participant.identity === snapshot.localIdentity,\n    ) ?? null;\n\n  return {\n    phase: snapshot?.phase ?? \"resolving\",\n    participants: snapshot?.participants ?? [],\n    failure: snapshot?.failure ?? null,\n    secondDevice: snapshot?.secondDevice ?? null,\n    local,\n    // An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).\n    sharingAllowed: snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot)),\n    canShareScreen:\n      (engine?.supportsScreenShare() ?? true) &&\n      !isObserverRole(snapshot?.grants.role ?? null) &&\n      // The server's word that sharing was taken away arrives before the rules refresh does: the control goes at once.\n      !(snapshot?.share.state === \"ended\" && snapshot.share.reason === \"not_allowed\") &&\n      (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),\n    otherPresenter: otherPresenterOf(snapshot),\n    join: useCallback(\n      async (request: JoinRequest) => requireEngine(engine, \"join\").join(request),\n      [engine],\n    ),\n    checkElsewhere: useCallback(\n      async (roomName: RoomName) => (engine === null ? false : engine.checkElsewhere(roomName)),\n      [engine],\n    ),\n    leave: useCallback(async () => requireEngine(engine, \"leave\").leave(), [engine]),\n    toggleMicrophone: useCallback(\n      async () =>\n        requireEngine(engine, \"toggleMicrophone\").setMicrophoneEnabled(\n          !(local?.micEnabled ?? false),\n        ),\n      [engine, local],\n    ),\n    toggleCamera: useCallback(\n      async () =>\n        requireEngine(engine, \"toggleCamera\").setCameraEnabled(!(local?.cameraEnabled ?? false)),\n      [engine, local],\n    ),\n    toggleScreenShare: useCallback(async () => {\n      const on = !(local?.screenSharing ?? false);\n      // S8: who presents follows the local screen-share TRACK (createInRoomClient), not this\n      // click — the browser's own \"Stop sharing\" bar ends the track without our button.\n      await requireEngine(engine, \"toggleScreenShare\").setScreenShareEnabled(on);\n    }, [engine, local]),\n    // S8: a hand is SERVER state (`/moderate raise_hand · lower_hand`, server time), replicated\n    // back as the `matrx.hand` attribute — no client sets its own hand on the wire.\n    toggleHand: useCallback(async () => {\n      if (host === null) throw noRuntime(\"toggleHand\");\n      await host.inRoom.moderate({ action: local?.handRaised === true ? \"lower_hand\" : \"raise_hand\" });\n    }, [host, local]),\n    react: useCallback(\n      async (emoji: string) => requireEngine(engine, \"react\").react(emoji),\n      [engine],\n    ),\n    sendChat: useCallback(\n      async (text: string) => {\n        if (host === null) throw noRuntime(\"sendChat\");\n        await host.inRoom.sendChat(text);\n      },\n      [host],\n    ),\n    sendPrivateChat: useCallback(\n      async (to: ParticipantIdentity, text: string) =>\n        requireEngine(engine, \"sendPrivateChat\").sendPrivateChat(to, text),\n      [engine],\n    ),\n    pin: useCallback(\n      (identity: ParticipantIdentity | null) => requireEngine(engine, \"pin\").pin(identity),\n      [engine],\n    ),\n    setLayout: useCallback(\n      (layout: StageLayout) => requireEngine(engine, \"setLayout\").setLayout(layout),\n      [engine],\n    ),\n  };\n}\n\n/** The stage, recomputed only when the roster or the layout actually changes. */\nexport function useStage(pageSize = DEFAULT_PAGE_SIZE): Stage {\n  const snapshot = useMeetSnapshot();\n  const [page, setPage] = useState(0);\n  const stage = useMemo(\n    () =>\n      computeStage({\n        participants: snapshot?.participants ?? [],\n        layout: snapshot?.layout ?? \"grid\",\n        pinned: snapshot?.pinned ?? null,\n        spotlight: snapshot?.spotlight ?? null,\n        activeSpeakers: snapshot?.activeSpeakers ?? [],\n        pageSize,\n        page,\n      }),\n    [snapshot, pageSize, page],\n  );\n  // Clamp back into range when people leave — a page that scrolled past the\n  // end must not render an empty stage.\n  useEffect(() => {\n    if (page > stage.pageCount - 1) setPage(Math.max(0, stage.pageCount - 1));\n  }, [page, stage.pageCount]);\n  return stage;\n}\n\n/**\n * Attach a participant's media to an element. The returned ref callback's\n * CLEANUP is the detach — there is nothing a consumer can forget to call.\n */\nexport function useTrack(\n  identity: ParticipantIdentity | null,\n  kind: \"camera\" | \"microphone\" | \"screen\",\n): (element: HTMLMediaElement | null) => void {\n  const host = useMeetHost();\n  const detachRef = useRef<(() => void) | null>(null);\n  return useCallback(\n    (element: HTMLMediaElement | null) => {\n      detachRef.current?.();\n      detachRef.current = null;\n      if (element === null || identity === null || host === null) return;\n      detachRef.current = host.engine.attach(identity, kind, element);\n    },\n    [host, identity, kind],\n  );\n}\n\nexport interface UseCallsResult {\n  readonly incoming: readonly CallInvite[];\n  readonly outgoing: CallInvite | null;\n  /** `null` for a guest identity — the UI renders nothing rather than a dead button. */\n  readonly canCall: boolean;\n  call: (people: readonly UserId[], mode: CallMode) => Promise<CallInvite>;\n  accept: (invite: CallInvite) => Promise<void>;\n  decline: (invite: CallInvite, message?: string) => Promise<void>;\n  cancel: (invite: CallInvite) => Promise<void>;\n}\n\nexport function useCalls(): UseCallsResult {\n  // NOT `useRequiredMeetHost`. `<IncomingCallHost/>` is mounted app-wide by\n  // contract, so it renders on every server render and for every signed-out\n  // visitor — states in which this provider is correctly inert.\n  const host = useMeetHost();\n  const center = host?.calls ?? null;\n  const [, force] = useState(0);\n\n  // The call center is not a store (it is a lifecycle object), so a ring must\n  // re-render this hook. The 1s tick only re-renders when what this hook\n  // returns (the invites' identities) actually changed: an idle app-wide\n  // `<IncomingCallHost/>` used to re-render every second for nothing.\n  const lastSeen = useRef(\"|\");\n  useEffect(() => {\n    if (center === null) return undefined;\n    const timer = setInterval(() => {\n      const seen = `${center.incoming().map((invite) => invite.id).join(\",\")}|${center.outgoing()?.id ?? \"\"}`;\n      if (seen === lastSeen.current) return;\n      lastSeen.current = seen;\n      force((value) => value + 1);\n    }, 1_000);\n    return () => clearInterval(timer);\n  }, [center]);\n\n  return {\n    incoming: center?.incoming() ?? [],\n    outgoing: center?.outgoing() ?? null,\n    canCall: center !== null,\n    call: useCallback(\n      async (people: readonly UserId[], mode: CallMode) => {\n        if (center === null) {\n          throw noRuntime(\n            host === null ? \"call\" : \"call (a guest identity has no calling surface, D6)\",\n          );\n        }\n        const invite = await center.call({ people, mode });\n        force((value) => value + 1);\n        return invite;\n      },\n      [center, host],\n    ),\n    accept: useCallback(\n      async (invite: CallInvite) => {\n        if (center === null || host === null) return;\n        await center.accept(invite.id, invite.mode);\n        await host.engine.join({ roomName: invite.roomName, mode: invite.mode });\n        force((value) => value + 1);\n      },\n      [center, host],\n    ),\n    decline: useCallback(\n      async (invite: CallInvite, message?: string) => {\n        if (center === null) return;\n        await center.decline(invite.id, message);\n        force((value) => value + 1);\n      },\n      [center],\n    ),\n    cancel: useCallback(\n      async (invite: CallInvite) => {\n        if (center === null) return;\n        await center.cancel(invite.id);\n        force((value) => value + 1);\n      },\n      [center],\n    ),\n  };\n}\n\nexport interface UseLobbyResult {\n  readonly waiting: readonly LobbyEntry[];\n  /** People this host (or a co-host) declined, who stay declined until it is lifted. */\n  readonly declined: readonly LobbyEntry[];\n  readonly canAdmit: boolean;\n  admit: (entry: LobbyEntry) => Promise<void>;\n  deny: (entry: LobbyEntry) => Promise<void>;\n  admitAll: () => Promise<void>;\n  /** Lift a denial (`meet_undeny`) so the person may ask again. */\n  undeny: (entry: LobbyEntry) => Promise<void>;\n}\n\nexport function useLobby(): UseLobbyResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const isHost = useIsHost();\n  const session = host?.meetings ?? null;\n  return {\n    waiting: (snapshot?.lobby ?? []).filter((entry) => entry.state === \"knocking\"),\n    declined: (snapshot?.lobby ?? []).filter((entry) => entry.state === \"denied\"),\n    // No runtime means no host powers — `<LobbyPanel>` renders nothing rather\n    // than an admit button that would throw.\n    canAdmit: session !== null && (isHost || (snapshot !== null && snapshot.phase === \"in_call\" && mayAdmitNow(snapshot.participants.find((p) => p.identity === snapshot.localIdentity)?.role ?? \"none\", snapshot.participants, snapshot.livePolicy))),\n    admit: useCallback(\n      async (entry: LobbyEntry) => requireSession(session, \"admit\").admit(entry, true),\n      [session],\n    ),\n    deny: useCallback(\n      async (entry: LobbyEntry) => requireSession(session, \"deny\").admit(entry, false),\n      [session],\n    ),\n    admitAll: useCallback(\n      async () => requireSession(session, \"admitAll\").admitAll(),\n      [session],\n    ),\n    undeny: useCallback(\n      async (entry: LobbyEntry) => requireSession(session, \"undeny\").undeny(entry),\n      [session],\n    ),\n  };\n}\n\n/** Milliseconds left until `untilMs` (ticks every second); null when there is no deadline, 0 once it passed. */\nexport function useCountdown(untilMs: number | null | undefined): number | null {\n  const [now, setNow] = useState(() => Date.now());\n  const active = typeof untilMs === \"number\" && untilMs > now;\n  useEffect(() => {\n    if (!active) return undefined;\n    setNow(Date.now());\n    const timer = setInterval(() => setNow(Date.now()), 1_000);\n    return () => clearInterval(timer);\n  }, [active, untilMs]);\n  if (typeof untilMs !== \"number\") return null;\n  return Math.max(0, untilMs - now);\n}\n\nexport interface UseKnockNoticeResult {\n  /** The oldest knocker the host has not yet acted on or dismissed; null = nothing to show. */\n  readonly knocker: LobbyEntry | null;\n  /** How many MORE are waiting behind it. */\n  readonly others: number;\n  admit: () => Promise<void>;\n  dismiss: () => void;\n}\n\n/**\n * THE KNOCK NOTICE (`wr-host-notified`): a host in the room is told, by name, the moment someone\n * knocks — not only by a dot on the People button. One notice per knock (identity + knock time),\n * so a person who asks again is announced again; dismissing or acting on it clears just that knock.\n */\nexport function useKnockNotice(): UseKnockNoticeResult {\n  const lobby = useLobby();\n  const [dismissed, setDismissed] = useState<readonly string[]>([]);\n  const keyOf = (entry: LobbyEntry): string => `${entry.identity}@${entry.knockedAt}`;\n  const open = lobby.canAdmit ? lobby.waiting.filter((entry) => !dismissed.includes(keyOf(entry))) : [];\n  const knocker = open[0] ?? null;\n  return {\n    knocker,\n    others: Math.max(0, open.length - 1),\n    admit: useCallback(async () => {\n      if (knocker === null) return;\n      setDismissed((list) => [...list, keyOf(knocker)]);\n      await lobby.admit(knocker);\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n    }, [knocker, lobby.admit]),\n    dismiss: useCallback(() => {\n      if (knocker !== null) setDismissed((list) => [...list, keyOf(knocker)]);\n      // eslint-disable-next-line react-hooks/exhaustive-deps\n    }, [knocker]),\n  };\n}\n\nexport interface UseWaitingResult {\n  /** This person's wait as the server last said it; null outside the waiting room. */\n  readonly waiting: MeetWaiting | null;\n  /** Stop waiting (the row becomes `withdrawn`). */\n  withdraw: () => Promise<void>;\n  /** Ask again after a denial or an expired knock — offered only when allowed. */\n  askAgain: () => Promise<void>;\n}\n\n/** S4: the waiting screens' one read (CORE-DESIGN §2.6). */\nexport function useWaiting(): UseWaitingResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const session = host?.meetings ?? null;\n  return {\n    waiting: snapshot?.waiting ?? null,\n    withdraw: useCallback(async () => requireSession(session, \"withdraw\").withdraw(), [session]),\n    askAgain: useCallback(async () => requireSession(session, \"askAgain\").askAgain(), [session]),\n  };\n}\n\nexport interface UseLeaveResult {\n  /** What Leave offers this person, in order (S8: role + the meeting's `host_leave_prompt`). */\n  readonly choices: readonly LeaveChoice[];\n  readonly policy: LeavePolicy;\n  /** The people a host may hand the run to (everyone else here, observers excluded). */\n  readonly candidates: readonly MeetParticipant[];\n  leave: () => Promise<void>;\n  /** End the meeting for everyone (server-decided; the room then ends for all, this tab too). */\n  endForAll: () => Promise<void>;\n  /** Hand the run's host powers to `person`, then leave. */\n  assignAndLeave: (person: MeetParticipant) => Promise<void>;\n}\n\n/** S8 `leave-or-end-choice` / `host-leave-assign`: the Leave control's one read. */\nexport function useLeave(): UseLeaveResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const session = host?.meetings ?? null;\n  const engine = host?.engine ?? null;\n  const policy = snapshot?.leavePolicy ?? DEFAULT_LEAVE_POLICY;\n  const participants = snapshot?.participants ?? [];\n  const me = participants.find((p) => p.isLocal);\n  const candidates = participants.filter((p) => !p.isLocal && !p.isAgent && p.role !== \"viewer\");\n  const choices = leaveChoices({ policy, role: me?.role ?? null, othersPresent: candidates.length > 0 });\n  return {\n    choices,\n    policy,\n    candidates,\n    leave: useCallback(async () => requireEngine(engine, \"leave\").leave(), [engine]),\n    endForAll: useCallback(async () => requireSession(session, \"endForAll\").hostLeave(\"end_for_all\"), [session]),\n    assignAndLeave: useCallback(\n      async (person: MeetParticipant) => {\n        await requireSession(session, \"assignAndLeave\").hostLeave({ assignTo: String(person.identity) });\n        await requireEngine(engine, \"leave\").leave();\n      },\n      [session, engine],\n    ),\n  };\n}\n\nexport interface UseRecordingResult {\n  readonly state: string;\n  readonly label: string | null;\n  readonly canStart: boolean;\n  readonly canStop: boolean;\n  readonly consentNotice: string | null;\n  start: () => Promise<void>;\n  stop: () => Promise<void>;\n}\n\nexport function useRecording(): UseRecordingResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  // 🚨 THE SERVER'S GRANT, not `isHost` (MRI-A11). aidream computes\n  // `can_record = is_host AND policy == host-controlled` and puts it on the\n  // token and the roster attribute; the policy half is why a host of an\n  // `always-on` meeting correctly gets NO control. The policy check below is\n  // kept as the package's own agreement with that rule, never as a substitute.\n  const canRecord = useCanRecord();\n  const meeting = snapshot?.meeting ?? null;\n  const state = snapshot?.recording ?? \"idle\";\n  // 🚨 NOT `state === \"idle\"` (MRI-A16). Once the durable states actually\n  // arrive, a meeting whose recording finished sits on `available`, and asking\n  // for `idle` made the Start control vanish for the rest of the session.\n  const canStart =\n    host !== null && canRecord && host.recording.canStart(meeting, true) && !isRecordingInFlight(state);\n\n  return {\n    state,\n    label: recordingLabel(state),\n    canStart,\n    // `stopping` is already stopping; the other in-flight states can be.\n    canStop: host !== null && canRecord && (state === \"recording\" || state === \"starting\"),\n    consentNotice: host?.recording.consentNotice(meeting) ?? null,\n    start: useCallback(async () => {\n      const live = requireHost(host, \"startRecording\");\n      if (meeting === null || live.identity.userId === null) return;\n      await live.recording.start({\n        meetingId: meeting.id,\n        roomName: meeting.roomName,\n        by: live.identity.userId,\n      });\n    }, [host, meeting]),\n    stop: useCallback(async () => {\n      const live = requireHost(host, \"stopRecording\");\n      if (meeting === null || live.identity.userId === null) return;\n      await live.recording.stop({ meetingId: meeting.id, by: live.identity.userId });\n    }, [host, meeting]),\n  };\n}\n\n/** One line of the transcript, as a panel renders it. */\nexport interface TranscriptLine {\n  readonly id: string;\n  /** Who said it, as the room knows them. Surfaces group by THIS, not by name. */\n  readonly identity: ParticipantIdentity;\n  readonly speaker: string;\n  readonly text: string;\n  readonly final: boolean;\n  /** `caption` is a live hint; `record` is the durable transcript (D16). */\n  readonly source: TranscriptSource;\n}\n\nexport interface UseMeetAiResult {\n  /** The note-taker's honest state, and the server's refusal if there was one. */\n  readonly noteTaker: NoteTakerStatus;\n  /** The sentence for that state. Never a bare enum, never a spinner. */\n  readonly noteTakerLabel: string;\n  /** True only for a host of a meeting whose AI is on. Guests get no control. */\n  readonly canControlNoteTaker: boolean;\n  /** Live-window notes, oldest first. */\n  readonly notes: readonly MeetingNote[];\n  readonly decisions: readonly MeetingNote[];\n  readonly actionItems: readonly MeetingNote[];\n  /** The wrap-up summary, once the meeting has produced one. */\n  readonly summary: MeetingNote | null;\n  /**\n   * The wrap-up pass ANNOUNCED itself into this room (MRI-A12). `null` means it\n   * has not been announced HERE — never that no summary exists. The ordinary\n   * ending path deletes the LiveKit room before the pass runs, so this is\n   * normally null and the summary is read on the post-meeting record.\n   */\n  readonly wrapUp: WrapUpAnnouncement | null;\n  readonly transcript: readonly TranscriptLine[];\n  readonly asking: boolean;\n  /** The answer SO FAR. It grows while the answer streams. */\n  readonly answer: string | null;\n  readonly coverage: MeetAnswerCoverage | null;\n  /** The server's phase while an answer is being built. */\n  readonly phase: string | null;\n  readonly error: { readonly message: string; readonly remedy: string } | null;\n  ask: (question: string) => Promise<void>;\n  startNoteTaker: () => Promise<void>;\n  stopNoteTaker: () => Promise<void>;\n}\n\n/**\n * THE MEETING ASSISTANT, as a surface needs it.\n *\n * Everything below is DATA, including every failure. There is no state in which\n * this hook returns a spinner with nothing behind it: the note-taker is in one\n * of five named states or the server refused with a sentence, and an answer is\n * either arriving (visibly, token by token) or has failed with a remedy.\n */\nexport function useMeetAi(): UseMeetAiResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const isHost = useIsHost();\n  const [asking, setAsking] = useState(false);\n  const [answer, setAnswer] = useState<string | null>(null);\n  const [coverage, setCoverage] = useState<MeetAnswerCoverage | null>(null);\n  const [phase, setPhase] = useState<string | null>(null);\n  const [error, setError] = useState<{ message: string; remedy: string } | null>(null);\n  const ai = host?.ai ?? null;\n  const meeting = snapshot?.meeting ?? null;\n  const participants = snapshot?.participants ?? [];\n  const notes = snapshot?.notes ?? [];\n  const wrapUp = snapshot?.wrapUp ?? null;\n\n  const status = useMemo(\n    () =>\n      noteTakerStatus({\n        meeting,\n        participants,\n        refusal: snapshot?.noteTakerRefusal ?? null,\n      }),\n    [meeting, participants, snapshot?.noteTakerRefusal],\n  );\n\n  const names = snapshot?.names ?? EMPTY_NAMES;\n  const transcript = useMemo(\n    () =>\n      readableTranscript(snapshot?.transcript ?? []).map((line) => ({\n        id: line.id,\n        identity: line.identity,\n        // 🚨 RESOLVED, not rendered raw (MRI-A16). A line stamped before its\n        // speaker's name was known — a durable row that beat the roster, a\n        // caption from someone who has since left — is re-attributed the moment\n        // anything learns the name, in BOTH lanes, so the host and the guest\n        // never read two different names for one speaker again (MRI-C8).\n        speaker: displayNameFor(names, line.identity, line.speaker),\n        text: line.text,\n        final: line.final,\n        source: line.source,\n      })),\n    [snapshot?.transcript, names],\n  );\n\n  const dispatchNoteTaker = useCallback(\n    async (run: () => Promise<unknown>) => {\n      setError(null);\n      try {\n        await run();\n      } catch (thrown) {\n        // THE SERVER'S SENTENCE REACHES THE SCREEN. A dispatch that failed and\n        // said nothing is a meeting everyone believes is being minuted.\n        setError({\n          message: (thrown as Error).message,\n          remedy:\n            (thrown as { remedy?: string }).remedy ??\n            \"The note-taker action could not be confirmed. Check its current state and try again.\",\n        });\n      }\n    },\n    [],\n  );\n\n  return {\n    noteTaker: status,\n    noteTakerLabel: noteTakerLabel(status),\n    // A guest cannot dispatch an agent, and neither can anyone in a meeting\n    // whose AI is off. The control is ABSENT for them, never disabled-looking.\n    canControlNoteTaker:\n      ai !== null && meeting !== null && meeting.aiEnabled && isHost && host?.identity.userId !== null,\n    notes: notes.filter((note) => note.kind === \"note\" && note.role === null),\n    // D20: the wrap-up is the authoritative post-meeting set. A window-written\n    // decision the wrap-up superseded stays in `notes` — the timeline — and is\n    // not listed a second time as a decision that was made.\n    decisions: notes.filter((note) => note.kind === \"decision\" && note.supersededBy === null),\n    actionItems: notes.filter(\n      (note) => note.kind === \"action-item\" && note.supersededBy === null,\n    ),\n    summary: activeWrapUpSummary(notes),\n    wrapUp,\n    transcript,\n    asking,\n    answer,\n    coverage,\n    phase,\n    error,\n    ask: useCallback(\n      async (question: string) => {\n        if (ai === null || meeting === null) return;\n        setAsking(true);\n        setError(null);\n        setAnswer(null);\n        setCoverage(null);\n        setPhase(null);\n        try {\n          const result = await ai.ask({\n            meetingId: meeting.id,\n            question,\n            // THE ANSWER RENDERS AS IT ARRIVES. Waiting for the last token to\n            // show the first is a spinner wearing an answer's clothes.\n            onText: (text) => setAnswer(text),\n            onPhase: (value) => setPhase(value),\n          });\n          setAnswer(result.text);\n          setCoverage(result.coverage);\n        } catch (thrown) {\n          setError({\n            message: (thrown as Error).message,\n            remedy:\n              (thrown as { remedy?: string }).remedy ??\n              \"The assistant could not answer. Nothing was changed by the attempt.\",\n          });\n        } finally {\n          setAsking(false);\n          setPhase(null);\n        }\n      },\n      [ai, meeting],\n    ),\n    startNoteTaker: useCallback(async () => {\n      if (ai === null || meeting === null) return;\n      await dispatchNoteTaker(() =>\n        ai.startNoteTaker({ meetingId: meeting.id, roomName: meeting.roomName }),\n      );\n    }, [ai, meeting, dispatchNoteTaker]),\n    stopNoteTaker: useCallback(async () => {\n      if (ai === null || meeting === null) return;\n      await dispatchNoteTaker(() => ai.stopNoteTaker({ meetingId: meeting.id }));\n    }, [ai, meeting, dispatchNoteTaker]),\n  };\n}\n\n/**\n * CAPTIONS FOR ME (`captions-toggle`, `captions-unavailable`).\n *\n * The toggle is the viewer's own: it never changes what anyone else sees. Turning it on asks the\n * server to make sure the note-taker (the speech-to-text agent) is in the room, and the state\n * is read from what is TRUE — the note-taker's real state and the server's refusal — never from\n * a timer: `unavailable` carries the server's own sentence.\n */\nexport interface UseCaptionsResult {\n  readonly on: boolean;\n  readonly state: \"off\" | \"starting\" | \"live\" | \"unavailable\";\n  /** Why captions are unavailable, in the server's words (or the note-taker's state). */\n  readonly reason: string | null;\n  readonly remedy: string | null;\n  readonly toggle: () => void;\n  /** Try again after `unavailable`: asks for captions afresh and restarts the start ceiling. */\n  readonly retry: () => void;\n}\n\nexport function useCaptions(): UseCaptionsResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const ai = useMeetAi();\n  const on = snapshot?.captionsOn === true;\n  const refusal = snapshot?.captionsRefusal ?? null;\n  const taker = ai.noteTaker;\n  const meeting = snapshot?.meeting ?? null;\n  const request = useCallback(() => {\n    if (host === null || meeting === null) return;\n    void host.ai.requestCaptions({ meetingId: meeting.id });\n  }, [host, meeting]);\n  const [timedOut, setTimedOut] = useState(false);\n  const timeoutSeconds = snapshot?.captionsStartTimeoutSeconds ?? 20;\n  const live = taker.state === \"transcribing\" && taker.present;\n  // The ceiling on \"Starting captions\": counts from the moment captions went on (or Try again),\n  // and ends the instant the note-taker is really transcribing.\n  const [attempt, setAttempt] = useState(0);\n  useEffect(() => {\n    setTimedOut(false);\n    if (!on || live) return undefined;\n    const id = setTimeout(() => setTimedOut(true), timeoutSeconds * 1000);\n    return () => clearTimeout(id);\n  }, [on, live, timeoutSeconds, attempt]);\n  const toggle = useCallback(() => {\n    if (host === null) return;\n    const next = !on;\n    host.store.patch({ captionsOn: next, captionsRefusal: null });\n    if (next && taker.state !== \"joining\" && taker.state !== \"transcribing\") request();\n  }, [host, on, taker.state, request]);\n  const retry = useCallback(() => {\n    if (host === null) return;\n    host.store.patch({ captionsOn: true, captionsRefusal: null });\n    setAttempt((n) => n + 1);\n    request();\n  }, [host, request]);\n\n  const view = resolveCaptionsState({\n    on,\n    takerState: taker.state,\n    takerPresent: taker.present,\n    refusal,\n    takerLabel: on ? noteTakerLabel(taker) : \"\",\n    timedOut,\n  });\n  return { on, state: view.state, reason: view.reason, remedy: view.remedy, toggle, retry };\n}\n\n/**\n * ENDING THE MEETING FOR EVERYONE — a host control with an honest failure.\n *\n * `POST /v1/meet/end` is served by MRI-A6. A server that has not landed it\n * answers 404, and this hook reports that as the sentence\n * `END_MEETING_NOT_SERVED` rather than pretending the meeting ended or leaving\n * a button that appears to do nothing.\n */\nexport interface UseEndMeetingResult {\n  readonly canEnd: boolean;\n  readonly ending: boolean;\n  readonly ended: boolean;\n  /** The honest sentence when the attempt did not end the meeting. */\n  readonly notice: string | null;\n  end: () => Promise<void>;\n}\n\nexport function useEndMeeting(): UseEndMeetingResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const isHost = useIsHost();\n  const [ending, setEnding] = useState(false);\n  const [notice, setNotice] = useState<string | null>(null);\n  const meeting = snapshot?.meeting ?? null;\n  const session = host?.meetings ?? null;\n\n  return {\n    canEnd: session !== null && isHost && meeting !== null && meeting.endedAt === null,\n    ending,\n    ended: meeting?.endedAt !== null && meeting?.endedAt !== undefined,\n    notice,\n    end: useCallback(async () => {\n      const live = requireSession(session, \"endForEveryone\");\n      setEnding(true);\n      setNotice(null);\n      try {\n        const result = await live.endForEveryone();\n        if (!result.served) {\n          // NOT A DEAD BUTTON AND NOT A LIE: the route is pinned in the\n          // package's contract and this server has not landed it yet (MRI-A6).\n          setNotice(END_MEETING_NOT_SERVED);\n        }\n      } catch (thrown) {\n        const remedy = (thrown as { remedy?: string }).remedy;\n        setNotice(\n          remedy !== undefined\n            ? `${(thrown as Error).message} ${remedy}`\n            : (thrown as Error).message,\n        );\n      } finally {\n        setEnding(false);\n      }\n    }, [session]),\n  };\n}\n\n/**\n * THE CONSENT NOTICE (D10) — a property of this package, never a prop.\n *\n * Returns the sentence every participant must see while an agent is in the\n * room, or `null` when none is. There is deliberately no way to turn it off:\n * the org's policy decides whether a note-taker may run, and it never decides\n * whether the people in the room are told about it.\n */\nexport function useConsentNotice(): string | null {\n  const snapshot = useMeetSnapshot();\n  const agent = noteTakerParticipant(snapshot?.participants ?? []);\n  if (agent === null) {\n    // Summoned and not in the room yet: everyone is told notes were started, and that it is joining.\n    const state = noteTakerStatus({ meeting: snapshot?.meeting ?? null, participants: [] }).state;\n    return state === \"joining\" ? \"AI notes started. The note-taker is joining this meeting.\" : null;\n  }\n  return (\n    `AI notes are on. ${agent.displayName} is in this meeting, transcribing what is said and ` +\n    \"writing notes everyone here can read.\"\n  );\n}\n\n/**\n * What the LOCAL participant is actually publishing, and why not when it is not.\n * Read this — never the roster's `micEnabled` — to decide whether to tell\n * someone they cannot be heard: the roster reflects the media plane, this\n * reflects the ATTEMPT, including one the browser refused outright (there is no\n * track to be un-muted in that case, so the roster would simply say `false`\n * with no reason attached).\n */\n/**\n * S6c — THE MEDIA SUPERVISOR'S REGIONS AND ACTIONS: permission per kind, autoplay\n * (`audioOutput`), the last device change, an offered new device. `enableAudio` must be called\n * from inside the person's click; `retry` turns the device on again through the one enable path.\n */\nexport function useMediaSupervisor(): {\n  readonly region: MediaRegionState;\n  /** This browser and operating system — which fix steps are the real ones. */\n  readonly where: { readonly browser: BrowserFamily; readonly os: OsFamily };\n  readonly enableAudio: () => Promise<void>;\n  readonly acceptOffer: () => Promise<void>;\n  readonly dismissOffer: () => void;\n  readonly dismissNotice: () => void;\n  readonly undoNotice: () => Promise<void>;\n  readonly retry: (kind: \"microphone\" | \"camera\") => Promise<void>;\n  /** The pre-join preview reports what it found (prompting / on / off / the refusal). */\n  readonly reportPreview: (kind: \"microphone\" | \"camera\", outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }) => void;\n} {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const engine = host?.engine ?? null;\n  return {\n    region: snapshot?.mediaRegion ?? IDLE_MEDIA_REGION,\n    where: useMemo(() => {\n      const platform = webMediaPlatform();\n      return { browser: platform?.browser ?? \"other\", os: platform?.os ?? \"other\" } as const;\n    }, []),\n    enableAudio: useCallback(async () => engine?.enableAudio(), [engine]),\n    acceptOffer: useCallback(async () => engine?.acceptDeviceOffer(), [engine]),\n    dismissOffer: useCallback(() => engine?.dismissDeviceOffer(), [engine]),\n    dismissNotice: useCallback(() => engine?.dismissDeviceNotice(), [engine]),\n    undoNotice: useCallback(async () => engine?.undoDeviceNotice(), [engine]),\n    retry: useCallback(\n      async (kind: \"microphone\" | \"camera\") =>\n        kind === \"microphone\" ? engine?.setMicrophoneEnabled(true) : engine?.setCameraEnabled(true),\n      [engine],\n    ),\n    reportPreview: useCallback(\n      (kind: \"microphone\" | \"camera\", outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }) => {\n        void engine?.previewDevice(kind, outcome);\n      },\n      [engine],\n    ),\n  };\n}\n\nexport function useLocalMedia(): LocalMediaState {\n  const snapshot = useMeetSnapshot();\n  return snapshot?.media ?? IDLE_MEDIA;\n}\n\n/**\n * The listen-only sentence, or `null` while the microphone is live. The remedy,\n * when the device was refused rather than declined, is on\n * `useLocalMedia().microphone.unavailable`.\n */\nexport function useListenOnlyNotice(): string | null {\n  return listenOnlyNotice(useLocalMedia());\n}\n\n/** Live reactions, already expired. Rendering stale confetti is the alternative. */\nexport function useReactions(): readonly { id: string; emoji: string }[] {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const store = host?.store ?? null;\n  useEffect(() => {\n    if (store === null) return undefined;\n    const timer = setInterval(() => store.expireReactions(Date.now()), REACTION_TTL_MS / 2);\n    return () => clearInterval(timer);\n  }, [store]);\n  return snapshot?.reactions ?? [];\n}\n\n/** A ticking duration for the call header. One timer, not one per component. */\nexport function useElapsed(startedAt: string | null): number {\n  const [now, setNow] = useState(() => Date.now());\n  useEffect(() => {\n    if (startedAt === null) return undefined;\n    const timer = setInterval(() => setNow(Date.now()), 1_000);\n    return () => clearInterval(timer);\n  }, [startedAt]);\n  if (startedAt === null) return 0;\n  return Math.max(0, now - Date.parse(startedAt));\n}\n\n/** Whether the local actor may moderate a given participant. One rank check. */\nexport function useCanModerate(target: MeetParticipant | undefined): boolean {\n  const snapshot = useMeetSnapshot();\n  const role = useRole();\n  const me = snapshot?.participants.find(\n    (participant) => participant.identity === snapshot.localIdentity,\n  );\n  // The EFFECTIVE role (token ∪ roster attribute — MRI-A11), not whichever of\n  // the two the roster happened to carry this tick.\n  return canModerateParticipant(me === undefined ? undefined : { ...me, role }, target);\n}\n\n/**\n * 🚨 EVERY HOST POWER, THROUGH THE SERVER (MRI-A11 → Meet wave 2).\n *\n * `canModerate` is the rank check — a host outranks a co-host outranks\n * everyone, and NOBODY may moderate themselves — so a surface renders a control\n * only where it would actually be honored. The act itself is a server call\n * (`core/in-room.ts`): through 0.7.x mute and remove were data packets nothing\n * listened to, which made them buttons that did nothing.\n *\n * `notice` is the server's last sentence (or refusal) for the actor — a control\n * that acted and said nothing is indistinguishable from one that did nothing.\n */\nexport interface UseHostControlsResult {\n  readonly isHost: boolean;\n  /** The host itself (not a co-host) — only the host hands the meeting over. */\n  readonly isOwner: boolean;\n  readonly notice: { readonly text: string; readonly failed: boolean } | null;\n  readonly busy: boolean;\n  clearNotice: () => void;\n  canModerate: (target: MeetParticipant) => boolean;\n  run: (request: ModerationRequest) => Promise<ModerationResult | null>;\n  mute: (target: MeetParticipant) => Promise<void>;\n  remove: (target: MeetParticipant) => Promise<void>;\n}\n\nexport function useHostControls(): UseHostControlsResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const role = useRole();\n  const me = snapshot?.participants.find(\n    (participant) => participant.identity === snapshot.localIdentity,\n  );\n  const actor = me === undefined ? undefined : { ...me, role };\n  const [busy, setBusy] = useState(false);\n  const inRoom = host?.inRoom ?? null;\n  const store = host?.store ?? null;\n  const notice = snapshot?.actionNotice ?? null;\n  const setNotice = useCallback(\n    (next: { text: string; failed: boolean } | null) =>\n      store?.patch({ actionNotice: next === null ? null : { ...next, at: Date.now() } }),\n    [store],\n  );\n\n  const run = useCallback(\n    async (request: ModerationRequest): Promise<ModerationResult | null> => {\n      if (inRoom === null) throw noRuntime(`moderate(${request.action})`);\n      setBusy(true);\n      try {\n        const result = await inRoom.moderate(request);\n        setNotice({ text: result.message, failed: false });\n        return result;\n      } catch (thrown) {\n        const error = thrown as { message?: string; remedy?: string };\n        setNotice({\n          text: [error.message, error.remedy].filter(Boolean).join(\" \"),\n          failed: true,\n        });\n        return null;\n      } finally {\n        setBusy(false);\n      }\n    },\n    [inRoom, setNotice],\n  );\n\n  return {\n    isHost: isHostRole(role),\n    isOwner: role === \"host\",\n    notice,\n    busy,\n    clearNotice: useCallback(() => setNotice(null), [setNotice]),\n    canModerate: useCallback(\n      (target: MeetParticipant) => canModerateParticipant(actor, target),\n      [actor],\n    ),\n    run,\n    mute: useCallback(\n      async (target: MeetParticipant) => {\n        await run({ action: \"mute\", identity: target.identity });\n      },\n      [run],\n    ),\n    remove: useCallback(\n      async (target: MeetParticipant) => {\n        await run({ action: \"remove\", identity: target.identity });\n      },\n      [run],\n    ),\n  };\n}\n\n/**\n * THE HAND QUEUE — raised hands in the order they went up (Meet wave 2).\n * First raised, first called on; a late joiner learns the order from each\n * client's re-announcement (`room.ts`).\n */\nexport function useHandQueue(): readonly MeetParticipant[] {\n  const snapshot = useMeetSnapshot();\n  return useMemo(\n    () =>\n      (snapshot?.participants ?? [])\n        .filter((participant) => participant.handRaised)\n        .sort((a, b) => (a.handRaisedAt ?? 0) - (b.handRaisedAt ?? 0)),\n    [snapshot?.participants],\n  );\n}\n\n/** This participant's noise suppression and background, and the setter. */\nexport interface UseMediaEffectsResult {\n  readonly effects: MediaEffects;\n  /** False = this browser cannot run a background effect; the control is absent. */\n  readonly backgroundsSupported: boolean;\n  set: (next: Partial<MediaEffects>) => Promise<void>;\n}\n\nexport function useMediaEffects(): UseMediaEffectsResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const engine = host?.engine ?? null;\n  return {\n    effects: snapshot?.effects ?? DEFAULT_EFFECTS,\n    backgroundsSupported: engine?.supportsVideoEffects() ?? false,\n    set: useCallback(\n      async (next: Partial<MediaEffects>) => requireEngine(engine, \"setEffects\").setEffects(next),\n      [engine],\n    ),\n  };\n}\n\n/** What a host last did to THIS participant, and a way to dismiss it. */\nexport function useModerationNotice(): { notice: ModerationNotice | null; dismiss: () => void } {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  return {\n    notice: snapshot?.moderationNotice ?? null,\n    dismiss: useCallback(() => host?.store.patch({ moderationNotice: null }), [host]),\n  };\n}\n\n/**\n * A live microphone level, 0..1, for a meter. Reads the given stream through an\n * `AnalyserNode`; returns 0 while there is none. One animation frame loop,\n * closed with the stream.\n */\nexport function useAudioLevel(stream: MediaStream | null): number {\n  const [level, setLevel] = useState(0);\n  useEffect(() => {\n    if (stream === null || stream.getAudioTracks().length === 0) {\n      setLevel(0);\n      return undefined;\n    }\n    const meter = createStreamLevelMeter(\n      stream,\n      (next) => {\n        const peak = next / 100;\n        setLevel((previous) => (Math.abs(previous - peak) > 0.02 ? peak : previous));\n      },\n      { measure: \"peak\", fftSize: 512, smoothing: 0 },\n    );\n    return () => meter.stop();\n  }, [stream]);\n  return level;\n}\n\n/**\n * THE KEYBOARD SHORTCUTS (Meet wave 2) — Google Meet's own chords, so nobody\n * relearns anything: ⌘/Ctrl+D mute, ⌘/Ctrl+E camera, ⌘/Ctrl+Alt+H hand,\n * ⌘/Ctrl+Alt+C chat, ⌘/Ctrl+Alt+P people, Shift+? the shortcuts sheet. Never\n * fires while the person is typing in a field.\n */\nexport const MEET_SHORTCUTS: readonly {\n  readonly id: \"mic\" | \"camera\" | \"hand\" | \"chat\" | \"people\" | \"help\";\n  readonly keys: string;\n  readonly label: string;\n}[] = [\n  { id: \"mic\", keys: \"⌘/Ctrl + D\", label: \"Mute or unmute your microphone\" },\n  { id: \"camera\", keys: \"⌘/Ctrl + E\", label: \"Turn your camera on or off\" },\n  { id: \"hand\", keys: \"⌘/Ctrl + Alt + H\", label: \"Raise or lower your hand\" },\n  { id: \"chat\", keys: \"⌘/Ctrl + Alt + C\", label: \"Open or close chat\" },\n  { id: \"people\", keys: \"⌘/Ctrl + Alt + P\", label: \"Open or close people\" },\n  { id: \"help\", keys: \"Shift + ?\", label: \"Show keyboard shortcuts\" },\n];\n\nexport function useMeetShortcuts(\n  handlers: Partial<Record<(typeof MEET_SHORTCUTS)[number][\"id\"], () => void>>,\n): void {\n  const ref = useRef(handlers);\n  ref.current = handlers;\n  useEffect(() => {\n    const target = (globalThis as { window?: Window }).window;\n    if (target === undefined) return undefined;\n    const onKey = (event: KeyboardEvent) => {\n      const element = event.target as HTMLElement | null;\n      const typing =\n        element !== null &&\n        (element.isContentEditable ||\n          element.tagName === \"INPUT\" ||\n          element.tagName === \"TEXTAREA\" ||\n          element.tagName === \"SELECT\");\n      const mod = event.metaKey || event.ctrlKey;\n      const key = event.key.toLowerCase();\n      let id: (typeof MEET_SHORTCUTS)[number][\"id\"] | null = null;\n      if (mod && !event.altKey && !event.shiftKey && key === \"d\") id = \"mic\";\n      else if (mod && !event.altKey && !event.shiftKey && key === \"e\") id = \"camera\";\n      else if (mod && event.altKey && (event.code === \"KeyH\" || key === \"h\")) id = \"hand\";\n      else if (mod && event.altKey && (event.code === \"KeyC\" || key === \"c\")) id = \"chat\";\n      else if (mod && event.altKey && (event.code === \"KeyP\" || key === \"p\")) id = \"people\";\n      else if (!mod && !typing && event.key === \"?\") id = \"help\";\n      if (id === null) return;\n      const handler = ref.current[id];\n      if (handler === undefined) return;\n      // ⌘D is \"bookmark\" and ⌘E is \"search\" in browsers: the meeting wins while\n      // it is on screen, exactly as it does in Meet.\n      event.preventDefault();\n      handler();\n    };\n    target.addEventListener(\"keydown\", onKey);\n    return () => target.removeEventListener(\"keydown\", onKey);\n  }, []);\n}\n\nexport function useMeeting(): MeetingRecord | null {\n  return useMeetSnapshot()?.meeting ?? null;\n}\n\nexport function useMeetingId(): MeetingId | null {\n  return useMeetSnapshot()?.meeting?.id ?? null;\n}\n\n/* ------------------------------------------------------ the meeting record */\n\n/**\n * THE MEETING AFTER THE MEETING (MRI-D2).\n *\n * A durable link outlives the room (R3), and until this hook existed it\n * resolved to a pre-join screen for a room nobody could enter — the summary,\n * decisions, action items, live notes, transcript and recording were reachable\n * only from SQL. This loads all of it from durable rows, states what the reader\n * is not allowed to see instead of rendering emptiness, and keeps the Q&A box\n * working against the record: `/intelligence/ask` reads the same durable rows\n * and answers a signed-in member long after the room closed.\n *\n * It is deliberately independent of the room store: nothing here needs a\n * LiveKit connection, a token, or a joined participant.\n */\nexport interface UseMeetingRecordResult {\n  readonly loading: boolean;\n  readonly record: MeetingRecordBundle | null;\n  /** A failure that stopped the WHOLE record loading. Partial refusals are in\n   *  `record.restrictions` — this is null whenever a record exists. */\n  readonly failure: { readonly message: string; readonly remedy: string } | null;\n  /** Q&A against the durable record. Streams, exactly as it does in-room. */\n  readonly asking: boolean;\n  readonly answer: string | null;\n  readonly coverage: MeetAnswerCoverage | null;\n  readonly askError: { readonly message: string; readonly remedy: string } | null;\n  ask: (question: string) => Promise<void>;\n  reload: () => void;\n}\n\n/**\n * 🚨 ONE RECORD PER READER PER TAB (0.7.79) — the bundle lives in a shared\n * cache (`core/record-cache.ts`), not in this hook. The first view of a\n * meeting reads; a wake from sleep, a remount, an Undo and every second view\n * render the kept record and read NOTHING. A member's record is kept current\n * by ONE change-feed channel per meeting (notes, transcript, attendance and\n * recordings, applied row by row), held while any view is mounted and a grace\n * after. `reload` and a reconnect read again; an older answer never paints over\n * a newer one. One cache per tab, on `globalThis`, so a dual-loaded graph\n * still shares it.\n */\nconst RECORD_CACHE_KEY = Symbol.for(\"@ai-matrx/meet/meeting-record-cache\");\n\nexport function meetingRecordCache(): MeetingRecordCache {\n  const holder = globalThis as unknown as Record<symbol, MeetingRecordCache | undefined>;\n  let cache = holder[RECORD_CACHE_KEY];\n  if (cache === undefined) {\n    cache = createMeetingRecordCache();\n    holder[RECORD_CACHE_KEY] = cache;\n  }\n  return cache;\n}\n\nconst rowIdOf = (row: Record<string, unknown>) => (typeof row[\"id\"] === \"string\" ? row[\"id\"] : undefined);\n\nexport function useMeetingRecord(meeting: MeetingRecord | null): UseMeetingRecordResult {\n  const host = useMeetHost();\n  const repository = host?.repository ?? null;\n  const ai = host?.ai ?? null;\n  const readerId = host?.identity.userId ?? null;\n  const [asking, setAsking] = useState(false);\n  const [answer, setAnswer] = useState<string | null>(null);\n  const [coverage, setCoverage] = useState<MeetAnswerCoverage | null>(null);\n  const [askError, setAskError] = useState<{ message: string; remedy: string } | null>(null);\n\n  const meetingId = meeting?.id ?? null;\n\n  const api = host?.api ?? null;\n  const tokens = host?.tokens ?? null;\n  const roomName = meeting?.roomName ?? null;\n  const manager = useRealtimeManager();\n  const cache = meetingRecordCache();\n  // Who is reading is part of the question: a member's record and a guest's\n  // share of it are two different answers.\n  const key =\n    repository !== null && meetingId !== null\n      ? `${readerId ?? `guest:${roomName ?? \"-\"}`}|${meetingId}`\n      : null;\n  const state = useSyncExternalStore(\n    cache.subscribe,\n    () => cache.state(key),\n    () => cache.state(null),\n  );\n\n  // The read itself, built from this render's host and meeting. Held in a ref\n  // so the cache can call the latest one (Retry, a reconnect) without the view\n  // re-running its effects.\n  const readRef = useRef<() => Promise<MeetingRecordAnswer>>(() => Promise.reject(new Error(\"not ready\")));\n  readRef.current = async (): Promise<MeetingRecordAnswer> => {\n    if (repository === null || meeting === null || meetingId === null) throw new Error(\"No meeting to read.\");\n    // 🚨 TWO READERS, TWO DOORS, ONE BUNDLE (MRF-1).\n    //\n    // A signed-in member reads the record DIRECT from Supabase under RLS, as\n    // they always have. A guest has no database at all — `anon` holds no grant\n    // on the four org-scoped tables and widening it is forbidden (MRI-A10) — so\n    // they read what the organization shares through `GET /v1/meet/record`,\n    // authorized by the pass this device kept from the meeting. Both produce\n    // the same `MeetingRecordBundle`, which is what keeps the two readers\n    // looking at one product instead of two.\n    if (readerId === null && api !== null && tokens !== null && roomName !== null) {\n      return {\n        kind: \"bundle\",\n        bundle: await loadGuestMeetingRecord({\n          api,\n          repository,\n          meetingId,\n          meeting,\n          roomToken: tokens.remembered(roomName),\n        }),\n      };\n    }\n    const parts = await loadMeetingRecordParts(repository, meetingId, { userId: readerId });\n    // A SIGNED-IN OUTSIDER IS NOT A STRANGER (2026-10-01). The database\n    // answers members and invitees; a person from another organization\n    // the host admitted — or a guest who later made an account — reads\n    // the guest share through the server, with their session as the pass.\n    if (api !== null && parts.restrictions.some((part) => part.part === \"notes\")) {\n      const viaServer = await loadGuestMeetingRecord({\n        api,\n        repository,\n        meetingId,\n        meeting,\n        roomToken: null,\n        session: true,\n      });\n      if (viaServer.restrictions.length < parts.restrictions.length) return { kind: \"bundle\", bundle: viaServer };\n    }\n    return { kind: \"parts\", meeting, parts };\n  };\n\n  // Mount and wake: read unless this reader's record of this meeting is kept.\n  useEffect(() => {\n    if (key === null) return;\n    void cache.ensure(key, () => readRef.current());\n  }, [cache, key]);\n\n  // The meeting row moved (a rename, it ended): the kept record is assembled\n  // again around it — nothing is read.\n  useEffect(() => {\n    if (key !== null && meeting !== null) cache.setMeeting(key, meeting);\n  }, [cache, key, meeting]);\n\n  // Live: ONE channel per meeting per reader, however many views hold it. A\n  // guest has no database and no change feed; their record is what the\n  // server shared.\n  useEffect(() => {\n    if (key === null || manager === null || repository === null || meetingId === null || readerId === null) {\n      return undefined;\n    }\n    const repo = repository;\n    const binding = (\n      table: string,\n      apply: (row: Record<string, unknown> | null, removedId: string | undefined) => void,\n    ) => ({\n      event: \"*\" as const,\n      schema: repo.schema,\n      table,\n      filter: `meeting_id=eq.${meetingId}`,\n      rowId: rowIdOf,\n      onChange: ({ row, payload }: { row: Record<string, unknown> | null; payload: { eventType?: string } }) => {\n        if (row === null) return;\n        const gone = payload.eventType === \"DELETE\";\n        apply(gone ? null : row, gone ? rowIdOf(row) : undefined);\n      },\n    });\n    return cache.hold(\n      key,\n      () => {\n        const handle = manager.open({\n          topic: meetingTopic(meetingId),\n          postgresChanges: [\n            binding(repo.tables.notes, (row, removedId) =>\n              cache.apply(key, { part: \"notes\", row: row && repo.projectNote(row), removedId }),\n            ),\n            binding(repo.tables.transcripts, (row, removedId) =>\n              cache.apply(key, { part: \"transcript\", row: row && repo.projectSegment(row), removedId }),\n            ),\n            binding(repo.tables.participants, (row, removedId) =>\n              cache.apply(key, { part: \"attendance\", row: row && repo.projectAttendee(row), removedId }),\n            ),\n            binding(repo.tables.recordings, (row, removedId) =>\n              // An archived recording is off the record (the read filters it the same way).\n              row !== null && row[\"deleted_at\"] != null\n                ? cache.apply(key, { part: \"recording\", row: null, removedId: rowIdOf(row) })\n                : cache.apply(key, { part: \"recording\", row: row && repo.projectRecording(row), removedId }),\n            ),\n          ],\n          // Realtime has no replay: a socket that blipped reads the record again.\n          onBackfill: async () => {\n            await cache.ensure(key, () => readRef.current(), { force: true });\n          },\n        });\n        return () => handle.close();\n      },\n      manager,\n    );\n  }, [cache, key, manager, repository, meetingId, readerId]);\n\n  return {\n    loading: state.loading && state.failure === null,\n    record: state.record,\n    failure: state.failure,\n    asking,\n    answer,\n    coverage,\n    askError,\n    ask: useCallback(\n      async (question: string) => {\n        if (ai === null || meetingId === null) return;\n        setAsking(true);\n        setAskError(null);\n        setAnswer(null);\n        setCoverage(null);\n        try {\n          const result = await ai.ask({\n            meetingId,\n            question,\n            onText: (text) => setAnswer(text),\n          });\n          setAnswer(result.text);\n          setCoverage(result.coverage);\n        } catch (thrown) {\n          // A guest gets the server's own 403 here (\"a guest can read the notes\n          // behind the link, but cannot ask the live assistant about a finished\n          // meeting. Sign in to do that.\"). It is rendered verbatim.\n          setAskError({\n            message: (thrown as Error).message,\n            remedy:\n              (thrown as { remedy?: string }).remedy ??\n              \"The assistant could not answer. Nothing was changed by the attempt.\",\n          });\n        } finally {\n          setAsking(false);\n        }\n      },\n      [ai, meetingId],\n    ),\n    reload: useCallback(() => {\n      if (key !== null) void cache.ensure(key, () => readRef.current(), { force: true });\n    }, [cache, key]),\n  };\n}\n\n/**\n * EVERY MEETING THIS ORGANIZATION HAS, newest first — including the ended ones\n * (MRI-D2). A list that shows only live meetings is a list that empties itself\n * the moment the work is done, and it is what left every wrap-up unreachable.\n */\nexport interface UseMeetingsResult {\n  readonly loading: boolean;\n  readonly meetings: readonly MeetingRecord[];\n  readonly hasMore: boolean;\n  readonly failure: { readonly message: string; readonly remedy: string } | null;\n  reload: () => void;\n}\n\nexport function useMeetings(\n  limit = 25,\n  /**\n   * The page's own organization filter. Absent/null = ALL the person's\n   * organizations, which is the default on every visit. It is never the host's\n   * active organization (active-org-is-never-a-list-filter.md).\n   */\n  organizationFilter: OrganizationId | null = null,\n): UseMeetingsResult {\n  const host = useMeetHost();\n  const repository = host?.repository ?? null;\n  const organizationId = organizationFilter;\n  const [meetings, setMeetings] = useState<readonly MeetingRecord[]>([]);\n  const [hasMore, setHasMore] = useState(false);\n  const [loading, setLoading] = useState(true);\n  const [failure, setFailure] = useState<{ message: string; remedy: string } | null>(null);\n  const [nonce, setNonce] = useState(0);\n\n  useEffect(() => {\n    if (repository === null) return undefined;\n    let live = true;\n    setLoading(true);\n    setFailure(null);\n    void repository\n      .listMeetings({ organizationId, limit })\n      .then((page) => {\n        if (!live) return;\n        setMeetings(page.items);\n        setHasMore(page.hasMore);\n        setLoading(false);\n      })\n      .catch((thrown: unknown) => {\n        if (!live) return;\n        setFailure({\n          message: (thrown as Error).message,\n          remedy:\n            (thrown as { remedy?: string }).remedy ??\n            \"The meetings could not be listed. Reload the page; nothing was changed.\",\n        });\n        setLoading(false);\n      });\n    return () => {\n      live = false;\n    };\n  }, [repository, organizationId, limit, nonce]);\n\n  return {\n    loading: loading && failure === null,\n    meetings,\n    hasMore,\n    failure,\n    reload: useCallback(() => setNonce((value) => value + 1), []),\n  };\n}\n\n\n/* ------------------------------------- what guests may read of this meeting */\n\n/**\n * THE HOST'S CHOICE FOR ONE MEETING (MRF-1).\n *\n * Arman ruled on 2026-09-12 that guest access to the post-meeting record is a\n * configuration and never a question: the system's default, the organization's\n * override, and this — a host deciding for the meeting in front of them,\n * because they are the only person who knows who was in the room and what was\n * said in it.\n *\n * `setting` is what the host chose (`default` means \"use my organization's\");\n * `effective` is what that resolves to RIGHT NOW, which is the only honest way\n * to render \"use my organization's setting\" — a label that does not say what\n * the organization's setting IS makes the host guess.\n *\n * The write is the SERVER's decision and it re-checks host power. This hook\n * never renders a control for a non-host; the component does that, and the\n * server refuses one anyway.\n */\nexport interface UseGuestRecordAccessResult {\n  readonly setting: GuestRecordAccessSetting;\n  /** Null until the server has said what `default` means for this meeting. */\n  readonly effective: GuestRecordAccessResolution | null;\n  readonly saving: boolean;\n  readonly error: { readonly message: string; readonly remedy: string } | null;\n  choose: (setting: GuestRecordAccessSetting) => Promise<void>;\n}\n\nexport function useGuestRecordAccess(\n  meeting: MeetingRecord | null,\n): UseGuestRecordAccessResult {\n  const host = useMeetHost();\n  const api = host?.api ?? null;\n  const stored = guestRecordAccessSetting(meeting);\n  // The row's own value is the truth until a write of ours succeeds; this is\n  // the optimistic half, and it is reset by the row arriving again.\n  const [chosen, setChosen] = useState<GuestRecordAccessSetting | null>(null);\n  const [effective, setEffective] = useState<GuestRecordAccessResolution | null>(null);\n  const [saving, setSaving] = useState(false);\n  const [error, setError] = useState<{ message: string; remedy: string } | null>(null);\n\n  useEffect(() => {\n    setChosen(null);\n  }, [stored, meeting?.id]);\n\n  return {\n    setting: chosen ?? stored,\n    effective,\n    saving,\n    error,\n    choose: useCallback(\n      async (next: GuestRecordAccessSetting) => {\n        if (api === null || meeting === null) return;\n        setSaving(true);\n        setError(null);\n        try {\n          const result = await setGuestRecordAccess({\n            api,\n            meetingId: meeting.id,\n            organizationId: meeting.organizationId,\n            access: next,\n          });\n          setChosen(result.setting);\n          setEffective(result.effective);\n        } catch (thrown) {\n          // The server's own sentence, rendered. A host who is not a host of\n          // this meeting reads why, not a generic failure.\n          setError({\n            message: (thrown as Error).message,\n            remedy:\n              (thrown as { remedy?: string }).remedy ??\n              \"Nothing was changed. Reload the page and try again.\",\n          });\n        } finally {\n          setSaving(false);\n        }\n      },\n      [api, meeting],\n    ),\n  };\n}\n\n\n/** What the meeting's rules (read live) mean for THIS person right now. */\nexport interface UseLivePolicyResult {\n  readonly canChat: boolean;\n  readonly chatMode: ChatMode;\n  readonly micLocked: boolean;\n  readonly cameraLocked: boolean;\n  /** Whole minutes before the time limit ends the meeting; null with no limit. */\n  readonly minutesLeft: number | null;\n  /** True from `timeLimitWarningMinutes` before the end. */\n  readonly timeWarning: boolean;\n  /** rec-consent-gate: the consent step to show, or null. */\n  readonly consent: \"ok_or_leave\" | \"view_only_until_agree\" | null;\n  readonly agree: () => void;\n}\n\nexport function useLivePolicy(): UseLivePolicyResult {\n  const snapshot = useMeetSnapshot();\n  const role = useRole();\n  const [now, setNow] = useState(() => Date.now());\n  const limited = (snapshot?.livePolicy.timeLimitMinutes ?? 0) > 0;\n  useEffect(() => {\n    if (!limited) return undefined;\n    const timer = setInterval(() => setNow(Date.now()), 1000);\n    return () => clearInterval(timer);\n  }, [limited]);\n  const policy = snapshot?.livePolicy ?? DEFAULT_LIVE_POLICY;\n  const left = minutesLeft(policy, snapshot?.sessionStartedAt ?? null, now);\n  const host = useMeetHost();\n  const pending = consentPending(policy, role, snapshot?.recording === \"recording\", snapshot?.recordingConsentGiven === true);\n  const viewOnly = pending && policy.recordingConsent === \"view_only_until_agree\";\n  const store = host?.store ?? null;\n  return {\n    canChat: canChatUnder(policy, role),\n    chatMode: policy.chatMode,\n    micLocked: isLockedFor(policy, role, \"microphone\") || viewOnly,\n    cameraLocked: isLockedFor(policy, role, \"camera\") || viewOnly,\n    consent: pending ? (policy.recordingConsent === \"ok_or_leave\" ? \"ok_or_leave\" : \"view_only_until_agree\") : null,\n    // The person's agreement is recorded by the SERVER (per run); the screen follows at once and\n    // takes it back if the server did not save it.\n    agree: () => {\n      store?.patch({ recordingConsentGiven: true });\n      void host?.meetings.acknowledgeConsent().catch(() => store?.patch({ recordingConsentGiven: false }));\n    },\n    minutesLeft: left,\n    timeWarning: left !== null && left <= policy.timeLimitWarningMinutes,\n  };\n}\n","/**\n * THE MEETING RECORD — what a meeting IS once the room is gone (MRI-D2).\n *\n * 🚨 THE DEFECT THIS EXISTS TO KILL. Through 2026-09-08 a meeting produced a\n * wrap-up summary, decisions, owner-assigned action items, five windows of live\n * notes, thirty-two transcript segments and a recording — and then had NO\n * SURFACE AT ALL. `/meet/<slug>` fell back to `<PreJoin>` on an ended meeting,\n * so the durable link that R3 promises would outlive the meeting resolved to a\n * screen offering to join a room that no longer exists. Everything the campaign\n * built after the room closed was reachable only from SQL.\n *\n * Three rules hold this file together:\n *\n * 1. **Every read is INDEPENDENT and every refusal is NAMED.** The transcript,\n *    the notes, the attendance list and the recording live in four RLS-guarded\n *    tables, and a guest holding the link can read NONE of them (only\n *    `meet_meeting_by_slug` is granted to `anon`). One `Promise.all` would turn\n *    a permission boundary into a blank page. Known guest restrictions never issue private reads; each authenticated read that is refused\n *    becomes a `MeetingRecordRestriction` with a sentence — the reader is told\n *    what exists and why they cannot see it, which is the difference between a\n *    record they can ask for and a product that looks broken.\n * 2. **A partial record is still a record.** A failed transcript read never\n *    hides the summary somebody CAN read.\n * 3. **Nothing here computes meaning.** Grouping, ordering and formatting only.\n *    The summary, decisions and action items are durable rows written by the\n *    wrap-up mandate (D5/D18); this module never re-derives them from the\n *    transcript, because two sources for one fact is how they start to disagree.\n */\n\nimport { formatDurationMs } from \"@ai-matrx/kit/format\";\nimport type { MeetApi } from \"./api\";\nimport { MeetError } from \"./errors\";\nimport { displayNameFor, learnNames, type NameBook } from \"./names\";\nimport type { MeetRepository } from \"./repository\";\nimport { MEET_ROUTES, MEETING_PASS_HEADER, type RoomToken } from \"./tokens\";\nimport type {\n  MeetingAttendee,\n  MeetingId,\n  MeetingNote,\n  MeetIdentity,\n  MeetingRecord,\n  OrganizationId,\n  ParticipantIdentity,\n  RecordingRecord,\n  TranscriptSegment,\n} from \"./types\";\n\n/** One thing the reader could not see, and the honest reason. Never a blank. */\nexport interface MeetingRecordRestriction {\n  /** Which part of the record: `transcript`, `notes`, `attendance`, `recording`. */\n  readonly part: \"transcript\" | \"notes\" | \"attendance\" | \"recording\";\n  readonly message: string;\n  readonly remedy: string;\n}\n\n/** One visible access state, made from restrictions that share one remedy. */\nexport interface MeetingRecordRestrictionNotice {\n  readonly parts: readonly MeetingRecordRestriction[\"part\"][];\n  readonly message: string;\n  readonly remedy: string;\n}\n\n/** A run of consecutive lines by one speaker — how a person reads a transcript. */\nexport interface TranscriptBlock {\n  readonly id: string;\n  /** Who spoke. Blocks break on THIS, never on the rendered name (MRI-A16). */\n  readonly identity: ParticipantIdentity;\n  readonly speaker: string;\n  /** ISO of the first line in the block. */\n  readonly startedAt: string;\n  readonly lines: readonly TranscriptSegment[];\n}\n\nexport interface MeetingRecordBundle {\n  readonly meeting: MeetingRecord;\n  readonly attendees: readonly MeetingAttendee[];\n  /** The wrap-up summary: `kind='note'` with `metadata.role='summary'` (D5). */\n  readonly summary: MeetingNote | null;\n  /** D20: the AUTHORITATIVE set — window rows the wrap-up superseded are out. */\n  readonly decisions: readonly MeetingNote[];\n  readonly actionItems: readonly MeetingNote[];\n  /** The live-notes windows, in window order (D3). */\n  readonly liveNotes: readonly MeetingNote[];\n  readonly transcript: readonly TranscriptSegment[];\n  /** The most recent recording attempt, whatever state it reached. */\n  readonly recording: RecordingRecord | null;\n  /** What this reader could NOT see. Rendered; never swallowed. */\n  readonly restrictions: readonly MeetingRecordRestriction[];\n  /**\n   * Identity → name, learned from everything this read COULD see: the durable\n   * attendance rows and the transcript's own `speaker` column. It is what stops\n   * a raw LiveKit token reaching the screen when one of those reads was refused\n   * (MRI-A16).\n   */\n  readonly names: NameBook;\n}\n\n/**\n * The current wrap-up summary.  Repairs preserve the prior durable row for\n * history, then mark it `superseded_by`; every current-facing projection must\n * therefore make the same distinction as decisions and action items.\n */\nexport function activeWrapUpSummary(notes: readonly MeetingNote[]): MeetingNote | null {\n  return notes.find((note) => note.role === \"summary\" && note.supersededBy === null) ?? null;\n}\n\n/**\n * The sentence a reader gets when the database refuses them a part of the\n * record. It is deliberately about TENANCY, not about them: `meet_notes`,\n * `meet_transcript_segments`, `meet_participants` and `meet_recordings` have no\n * `anon` policy at all, so a link-follower with no session reaches exactly the\n * meeting row and nothing else. That is the correct posture and it must be\n * SAID, not rendered as emptiness.\n */\nconst RESTRICTION_REMEDY =\n  \"Open it from the meeting link in the browser you attended with, or ask the host to share it.\";\n\nconst PART_LABEL: Readonly<Record<MeetingRecordRestriction[\"part\"], string>> = {\n  transcript: \"The transcript of this meeting is not readable from this account.\",\n  notes: \"The notes, decisions and action items are not readable from this account.\",\n  attendance: \"Who attended is not readable from this account.\",\n  recording: \"The recording is not readable from this account.\",\n};\n\n/** A refusal is DATA. A transport wobble is not, and is re-thrown as itself. */\nfunction restrictionFor(\n  part: MeetingRecordRestriction[\"part\"],\n  error: unknown,\n): MeetingRecordRestriction {\n  const code = (error as { code?: string }).code;\n  const denied =\n    code === \"forbidden\" || code === \"session-unavailable\" || code === \"not-found\";\n  return {\n    part,\n    message: denied\n      ? PART_LABEL[part]\n      : `${PART_LABEL[part]} (${(error as Error).message ?? \"the read failed\"})`,\n    remedy: denied\n      ? RESTRICTION_REMEDY\n      : (error as { remedy?: string }).remedy ??\n        \"This is a transient read failure, not a permission decision. Reload the page.\",\n  };\n}\n\n/**\n * The four durable reads behind a record, as the database returned them, plus\n * what the reader could not see. `assembleMeetingRecord` turns them into the\n * bundle; a cache that keeps them can apply a realtime row to one part and\n * assemble again, without reading the other three (0.7.79).\n */\nexport interface MeetingRecordParts {\n  readonly attendees: readonly MeetingAttendee[];\n  /** Every note row (all kinds, superseded included), oldest first. */\n  readonly notes: readonly MeetingNote[];\n  readonly transcript: readonly TranscriptSegment[];\n  /** Newest first; archived recordings are not here. */\n  readonly recordings: readonly RecordingRecord[];\n  readonly restrictions: readonly MeetingRecordRestriction[];\n}\n\n/**\n * Load the record parts the reader may request; state all restrictions.\n *\n * `meeting` is passed in when the caller already resolved it (the slug route\n * does, through the `anon`-granted RPC) — re-reading it through the table would\n * fail for exactly the reader who most needs the page to work.\n */\nexport async function loadMeetingRecord(\n  repository: MeetRepository,\n  meetingId: MeetingId,\n  meeting: MeetingRecord,\n  reader: Pick<MeetIdentity, \"userId\"> = { userId: null },\n): Promise<MeetingRecordBundle> {\n  return assembleMeetingRecord(meeting, await loadMeetingRecordParts(repository, meetingId, reader));\n}\n\n/** The four reads, each with its own verdict (see `loadMeetingRecord`). */\nexport async function loadMeetingRecordParts(\n  repository: MeetRepository,\n  meetingId: MeetingId,\n  reader: Pick<MeetIdentity, \"userId\"> = { userId: null },\n): Promise<MeetingRecordParts> {\n  const restrictions: MeetingRecordRestriction[] = [];\n\n  async function attempt<T>(\n    part: MeetingRecordRestriction[\"part\"],\n    run: () => Promise<T>,\n    empty: T,\n  ): Promise<T> {\n    // No anonymous policy exists for these four tables. State the known\n    // restriction without probing private data or generating expected 401s.\n    if (reader.userId === null) {\n      restrictions.push(restrictionFor(part, { code: \"session-unavailable\" }));\n      return empty;\n    }\n    try {\n      return await run();\n    } catch (error) {\n      restrictions.push(restrictionFor(part, error));\n      return empty;\n    }\n  }\n\n  // Four independent reads, four independent verdicts. Deliberately NOT\n  // `Promise.all` over a single try/catch — see rule 1 in the header.\n  const [attendees, notes, transcript, recordings] = await Promise.all([\n    attempt<readonly MeetingAttendee[]>(\"attendance\", () => repository.attendees(meetingId), []),\n    attempt<readonly MeetingNote[]>(\"notes\", () => repository.notes(meetingId), []),\n    attempt<readonly TranscriptSegment[]>(\n      \"transcript\",\n      () => repository.transcript(meetingId),\n      [],\n    ),\n    attempt<readonly RecordingRecord[]>(\n      \"recording\",\n      () => repository.recordings(meetingId),\n      [],\n    ),\n  ]);\n  return { attendees, notes, transcript, recordings, restrictions };\n}\n\n/** The bundle a reader sees, from the parts. Grouping and ordering only (rule 3). */\nexport function assembleMeetingRecord(\n  meeting: MeetingRecord,\n  parts: MeetingRecordParts,\n): MeetingRecordBundle {\n  const { attendees, notes, transcript, recordings, restrictions } = parts;\n  return {\n    meeting,\n    attendees,\n    summary: activeWrapUpSummary(notes),\n    // 🚨 D20: THE WRAP-UP IS THE AUTHORITATIVE POST-MEETING SET. A window row the\n    // wrap-up superseded is still in `notes` and still in the timeline below —\n    // it is simply not listed a second time as a decision that was made.\n    decisions: notes.filter((note) => note.kind === \"decision\" && note.supersededBy === null),\n    actionItems: notes.filter(\n      (note) => note.kind === \"action-item\" && note.supersededBy === null,\n    ),\n    liveNotes: notes\n      .filter((note) => note.kind === \"note\" && note.role === null)\n      // Window order, then creation order for the notes of one window.\n      .slice()\n      .sort((left, right) => {\n        const a = left.window ?? Number.MAX_SAFE_INTEGER;\n        const b = right.window ?? Number.MAX_SAFE_INTEGER;\n        return a === b ? left.createdAt.localeCompare(right.createdAt) : a - b;\n      }),\n    transcript,\n    // `recordings` is newest first; the record shows the latest attempt,\n    // including a failed one — a recording that failed is a fact the reader\n    // needs, not a row to hide.\n    recording: recordings[0] ?? null,\n    restrictions,\n    names: learnNames(learnNames({}, attendees), transcript.map((line) => ({\n      identity: line.identity,\n      displayName: line.speaker,\n    }))),\n  };\n}\n\n/**\n * 🚨 **A READ THAT WAS REFUSED IS NOT AN EMPTY RESULT (MRI-A16).**\n *\n * On production 2026-09-09 a guest's record view said *\"No wrap-up was written\n * for this meeting\"* directly underneath a panel that had just told them, in\n * the same screen, that the notes are not readable from their account — and\n * *\"Nothing was recorded as a decision\"* beside a decision that exists\n * (MRI-C8). The page asserted an absence it had no way to know, which is worse\n * than saying nothing: a person who reads \"no wrap-up was written\" stops\n * looking for one.\n *\n * So no surface writes its own empty sentence any more. It asks here, and gets\n * either its absence sentence — earned, because the read SUCCEEDED and returned\n * nothing — or the refusal, said plainly.\n */\nexport const REFUSED_ABSENCE = \"This record is not shared with guests.\";\n\n/** Was this part of the record refused to this reader? */\nexport function wasRefused(\n  bundle: MeetingRecordBundle,\n  part: MeetingRecordRestriction[\"part\"],\n): boolean {\n  return bundle.restrictions.some((restriction) => restriction.part === part);\n}\n\n/**\n * The sentence to show where a part of the record has nothing in it. NEVER an\n * absence claim over a read that was refused.\n */\nexport function absenceSentence(\n  bundle: MeetingRecordBundle,\n  part: MeetingRecordRestriction[\"part\"],\n  absence: string,\n): string {\n  return wasRefused(bundle, part) ? REFUSED_ABSENCE : absence;\n}\n\n/**\n * 🚨 **\"NO WRAP-UP WAS WRITTEN\" IS A CLAIM, AND FOR ~33 SECONDS IT WAS FALSE.**\n *\n * On production 2026-09-09 the HOST's record view said *\"No wrap-up was written\n * for this meeting\"* between 04:46:42 — the flip from the room to the record —\n * and 04:47:15, when the wrap-up landed. The read was permitted and genuinely\n * empty, so this is not the refusal class above; it is the OTHER way a screen\n * lies, by reading \"not here yet\" as \"never happened\". A person who reads *\"no\n * wrap-up was written\"* closes the tab.\n *\n * The meeting row already knows the difference, and it is not a guess: the\n * wrap-up is a durable job, `enqueue_wrap_up` stamps\n * `metadata.note_taker.intelligence.wrap_up` when it queues it, and the graph\n * action stamps `state: \"failed\"` when the pass refuses TERMINALLY. So:\n *\n * - a summary exists → `written`;\n * - the notes read was refused → `refused` (never an absence claim);\n * - the job is marked failed → `failed`, in the server's own words;\n * - the job is queued or running → `in-progress`, with a refresh affordance;\n * - nothing ever queued one → `absent`, which is the only EARNED absence.\n *\n * There is no timeout that flips `in-progress` into `absent`. A wrap-up that is\n * genuinely stuck says it is still being written — which is TRUE — rather than\n * inventing a verdict this browser has no way to reach.\n */\nexport type WrapUpStatus =\n  | { readonly state: \"written\" }\n  | { readonly state: \"in-progress\"; readonly message: string; readonly canRefresh: true }\n  | { readonly state: \"failed\"; readonly message: string }\n  /** Nobody spoke: a normal outcome, said plainly (not an alert). */\n  | { readonly state: \"empty\"; readonly message: string }\n  | { readonly state: \"refused\"; readonly message: string }\n  | { readonly state: \"absent\"; readonly message: string };\n\n/** What `metadata.note_taker` holds, as far as this file cares. */\nfunction noteTakerMetadata(meeting: MeetingRecord): Record<string, unknown> {\n  const raw = (meeting.metadata as Record<string, unknown>)[\"note_taker\"];\n  return typeof raw === \"object\" && raw !== null && !Array.isArray(raw)\n    ? (raw as Record<string, unknown>)\n    : {};\n}\n\nconst WRAP_UP_IN_PROGRESS =\n  \"The wrap-up is being written… The summary, the decisions and the action items are \" +\n  \"produced from the whole transcript once the meeting ends, which takes a moment longer \" +\n  \"than the meeting does.\";\n\nconst WRAP_UP_ABSENT =\n  \"No wrap-up was written for this meeting. A summary is produced from the transcript \" +\n  \"when the meeting ends and the note-taker was in the room.\";\n\n/** Where the wrap-up actually is. Never \"absent\" over a job that is running. */\nexport function wrapUpStatus(bundle: MeetingRecordBundle): WrapUpStatus {\n  if (bundle.summary !== null) return { state: \"written\" };\n  if (wasRefused(bundle, \"notes\")) return { state: \"refused\", message: REFUSED_ABSENCE };\n\n  const noteTaker = noteTakerMetadata(bundle.meeting);\n  const intelligenceRaw = noteTaker[\"intelligence\"];\n  const intelligence: Record<string, unknown> =\n    typeof intelligenceRaw === \"object\" && intelligenceRaw !== null && !Array.isArray(intelligenceRaw)\n      ? (intelligenceRaw as Record<string, unknown>)\n      : {};\n  const wrapUpRaw = intelligence[\"wrap_up\"];\n  const wrapUp: Record<string, unknown> =\n    typeof wrapUpRaw === \"object\" && wrapUpRaw !== null && !Array.isArray(wrapUpRaw)\n      ? (wrapUpRaw as Record<string, unknown>)\n      : {};\n\n  if (wrapUp[\"state\"] === \"empty\") {\n    const reason = wrapUp[\"reason\"];\n    return {\n      state: \"empty\",\n      message:\n        typeof reason === \"string\" && reason.trim().length > 0\n          ? reason.trim()\n          : \"No one spoke in this meeting, so there is no summary.\",\n    };\n  }\n\n  if (wrapUp[\"state\"] === \"failed\") {\n    const reason = wrapUp[\"reason\"];\n    return {\n      state: \"failed\",\n      // THE SERVER'S OWN SENTENCE, verbatim. It already names the remedy, and a\n      // house sentence over it would hide the one thing worth reading.\n      message:\n        typeof reason === \"string\" && reason.trim().length > 0\n          ? reason.trim()\n          : \"The wrap-up pass failed and no summary was written. It is not retried \" +\n            \"automatically; a host can end the meeting again to re-queue it.\",\n    };\n  }\n\n  const queued =\n    typeof wrapUp[\"run_id\"] === \"string\" ||\n    typeof intelligence[\"wrap_up_run_id\"] === \"string\" ||\n    wrapUp[\"state\"] === \"queued\" ||\n    wrapUp[\"state\"] === \"running\";\n  // A meeting the note-taker actually attended will get a wrap-up even if this\n  // browser loaded the record before the enqueue stamp landed — that race is\n  // the whole defect, so `ended + the note-taker was there` is enough.\n  const attended =\n    noteTaker[\"state\"] === \"ended\" ||\n    noteTaker[\"state\"] === \"transcribing\" ||\n    noteTaker[\"state\"] === \"handoff_pending\";\n\n  if (hasEnded(bundle.meeting) && (queued || attended)) {\n    return { state: \"in-progress\", message: WRAP_UP_IN_PROGRESS, canRefresh: true };\n  }\n  return { state: \"absent\", message: WRAP_UP_ABSENT };\n}\n\n/**\n * GROUP THE TRANSCRIPT THE WAY A PERSON READS IT: consecutive lines by one\n * speaker become one block with one timestamp. Reading thirty-two rows each\n * re-stamped with a name and a clock is how a transcript becomes unreadable.\n */\nexport function groupTranscript(\n  segments: readonly TranscriptSegment[],\n  names: NameBook = {},\n): readonly TranscriptBlock[] {\n  const blocks: TranscriptBlock[] = [];\n  for (const segment of segments) {\n    const last = blocks[blocks.length - 1];\n    // 🚨 GROUPED BY IDENTITY, not by the rendered name (MRI-A16). Two people\n    // whose names nobody ever learned both render \"Unnamed guest\", and merging\n    // their lines into one block would put words in the wrong mouth — the exact\n    // failure the honest placeholder exists to avoid.\n    if (last !== undefined && last.identity === segment.identity) {\n      blocks[blocks.length - 1] = { ...last, lines: [...last.lines, segment] };\n      continue;\n    }\n    blocks.push({\n      id: segment.id,\n      identity: segment.identity,\n      // One resolution, shared with the live rail — so the record and the room\n      // can never disagree about who said something.\n      speaker: displayNameFor(names, segment.identity, segment.speaker),\n      startedAt: segment.startedAt,\n      lines: [segment],\n    });\n  }\n  return blocks;\n}\n\n/**\n * WHAT THE RECORDING IS DOING, in a sentence — including the two states people\n * hit most and understand least. `processing` is not \"broken\" and `failed` is\n * never silence: both say what happened and what to do.\n */\nexport function recordingNotice(recording: RecordingRecord | null): string | null {\n  if (recording === null) return null;\n  switch (recording.state) {\n    case \"available\":\n      if (recording.retention?.phase !== \"warning\") return null;\n      return `This recording expires on ${retentionDueDate(recording.retention.dueAt)}. The transcript and notes remain available.`;\n    case \"expired\":\n      return \"This recording has expired. The transcript and notes remain available.\";\n    case \"processing\":\n    case \"stopping\":\n      return \"The recording is still being processed. It appears here on its own once the file lands — nothing is lost while it is being written.\";\n    case \"recording\":\n    case \"starting\":\n      return \"This recording is still being written. It becomes playable once the meeting's egress finishes.\";\n    case \"failed\":\n      return recording.failureReason !== null && recording.failureReason.length > 0\n        ? `The recording failed: ${recording.failureReason}`\n        : \"The recording failed and no file was produced. The transcript below was written separately and is unaffected.\";\n    default:\n      return null;\n  }\n}\n\nfunction retentionDueDate(value: string): string {\n  const dueAt = new Date(value);\n  return Number.isNaN(dueAt.getTime()) ? \"its scheduled retention date\" : dueAt.toLocaleString();\n}\n\n/** Only an `available` recording has a file to play. Nothing else pretends to. */\nexport function playableRecordingFileId(recording: RecordingRecord | null): string | null {\n  if (recording === null) return null;\n  return recording.state === \"available\" ? recording.fileId : null;\n}\n\n/**\n * A MEETING IS OVER WHEN THE SERVER SAYS SO. `ended_at` is stamped by\n * `POST /v1/meet/end` or by the auto-end evaluation (MRI-A6) — never by a\n * client noticing the room is empty.\n */\nexport function hasEnded(meeting: MeetingRecord | null): boolean {\n  return meeting !== null && meeting.endedAt !== null;\n}\n\n/**\n * \"Thursday, 8 September 2026, 4:21 PM · 19 minutes\". One shape everywhere.\n *\n * THE SPAN IS `formatDurationMs`'s (2026-09-12). This body used to divide by\n * `60_000` and pluralise \"minute\" itself — a duration formatter living in a\n * PACKAGE, found the day `aidream/apps/shared` became a scan root. `@ai-matrx/\n * meet` already depends on `@ai-matrx/kit`, and `style: \"long\"` is precisely\n * this voice (\"19 minutes\", \"1 minute\"). Three things improve by adopting it:\n * a 40-second meeting read \"0 minutes\" and now reads \"40 seconds\" (the\n * confident zero the package refuses), a 19-minute-35-second meeting read\n * \"20 minutes\" and now reads \"19 minutes\" (prose asserts at-least, so it\n * floors), and a 90-minute meeting reads \"1 hour\" instead of \"90 minutes\".\n */\nexport function meetingWhen(meeting: MeetingRecord, locale?: string): string {\n  const start = meeting.startedAt ?? meeting.scheduledFor;\n  if (start === null) return \"Time not recorded\";\n  const startedAt = new Date(start);\n  if (Number.isNaN(startedAt.getTime())) return \"Time not recorded\";\n  const when = startedAt.toLocaleString(locale, {\n    weekday: \"long\",\n    year: \"numeric\",\n    month: \"long\",\n    day: \"numeric\",\n    hour: \"numeric\",\n    minute: \"2-digit\",\n  });\n  if (meeting.endedAt === null || meeting.startedAt === null) return when;\n  const endedAt = new Date(meeting.endedAt);\n  if (Number.isNaN(endedAt.getTime())) return when;\n  const elapsedMs = endedAt.getTime() - startedAt.getTime();\n  return `${when} · ${formatDurationMs(elapsedMs, { style: \"long\" })}`;\n}\n\n/* ═══════════════════════════════════════════════════════════════════════════\n * MRF-1 — WHAT A GUEST MAY READ, AND HOW THEY READ IT\n *\n * 🚨 THE DEFECT THIS CLOSES. Everything above this line is correct and was\n * still the wrong product: a guest who attended a meeting, was admitted by the\n * host, spoke, and was transcribed got FOUR refusal sentences where the record\n * should have been. `anon` has no grant on the four org-scoped tables and\n * widening it is forbidden (MRI-A10) — a meeting link is not organization\n * membership — so the honest refusals were the only thing this file could say.\n *\n * Arman ruled on 2026-09-12 that guest access to the record is a CONFIGURATION\n * and never a question: a system default, an organization override, and a\n * per-meeting setting a host chooses. The server resolves it and serves the\n * shared subset at `GET /api/v1/meet/record`, authorized by the room token this\n * device already holds. So this half does three things and no more:\n *\n * 1. reads that route and turns its answer into the SAME `MeetingRecordBundle`\n *    the member lane produces — so one screen renders both readers and they can\n *    never drift into two products;\n * 2. states every part the level does NOT share as a `MeetingRecordRestriction`\n *    with the server's own sentence, which is what keeps \"not shared\" and\n *    \"nothing happened\" different things on screen;\n * 3. gives a host the control that sets it.\n *\n * What it does NOT do is decide anything. The level, the refusals and the\n * remedies are the server's words; a client that computed its own would be a\n * second authority on who may read a transcript.\n * ═══════════════════════════════════════════════════════════════════════════ */\n\n\n/** How much of a finished meeting a GUEST may read. Pinned with the server. */\nexport type GuestRecordAccess = \"none\" | \"summary\" | \"full\";\n\n/** Widest last. The ORDER is the comparison, exactly as it is on the server. */\nexport const GUEST_RECORD_ACCESS_LEVELS: readonly GuestRecordAccess[] = [\n  \"none\",\n  \"summary\",\n  \"full\",\n];\n\n/**\n * What a HOST may choose for one meeting. `default` is not a fourth level — it\n * is the absence of a per-meeting choice, and it is the only way to un-choose.\n */\nexport type GuestRecordAccessSetting = \"default\" | GuestRecordAccess;\n\nexport const GUEST_RECORD_ACCESS_CHOICES: readonly GuestRecordAccessSetting[] = [\n  \"default\",\n  \"summary\",\n  \"full\",\n  \"none\",\n];\n\n/** `meet_meetings.metadata.guest_record_access`. No DDL; a setting on a row. */\nexport const GUEST_RECORD_ACCESS_METADATA_KEY = \"guest_record_access\";\n\n/** What a host chose for THIS meeting, read from the row they already have. */\nexport function guestRecordAccessSetting(\n  meeting: MeetingRecord | null,\n): GuestRecordAccessSetting {\n  const raw = (meeting?.metadata as Record<string, unknown> | undefined)?.[\n    GUEST_RECORD_ACCESS_METADATA_KEY\n  ];\n  return GUEST_RECORD_ACCESS_LEVELS.includes(raw as GuestRecordAccess)\n    ? (raw as GuestRecordAccess)\n    : \"default\";\n}\n\n/** The sentence on the host's control. Plain English, never a token. */\nexport function guestRecordAccessLabel(setting: GuestRecordAccessSetting): string {\n  switch (setting) {\n    case \"default\":\n      return \"Use my organization's setting\";\n    case \"summary\":\n      return \"Summary, decisions and action items\";\n    case \"full\":\n      return \"Everything, including the transcript\";\n    case \"none\":\n      return \"Nothing — keep the record internal\";\n  }\n}\n\n/** What each choice actually means for the people who were in the room. */\nexport function guestRecordAccessExplanation(setting: GuestRecordAccessSetting): string {\n  switch (setting) {\n    case \"default\":\n      return \"Guests who attended read whatever your organization shares by default. An administrator sets that once, for every meeting nobody thinks about.\";\n    case \"summary\":\n      return \"Guests who attended read the wrap-up summary, the decisions, the action items, the notes taken as it happened, and who was here. They do not get the word-for-word transcript or the recording.\";\n    case \"full\":\n      return \"Guests who attended read everything this meeting produced, including the word-for-word transcript of what each person said.\";\n    case \"none\":\n      return \"Guests who attended are told plainly that this meeting's record is kept inside your organization. They see nothing of it.\";\n  }\n}\n\n/** What came back from the server, so a surface never has to infer a level. */\nexport interface GuestRecordAccessResolution {\n  readonly level: GuestRecordAccess;\n  /** `meeting` when a host chose for this one; `organization` otherwise. */\n  readonly source: \"meeting\" | \"organization\";\n}\n\n/** What the parts of the record the level does not share are called, and why. */\nconst NOT_SHARED: Readonly<Record<MeetingRecordRestriction[\"part\"], string>> = {\n  transcript:\n    \"The word-for-word transcript of this meeting is not shared with guests.\",\n  notes: \"The notes, decisions and action items are not shared with guests.\",\n  attendance: \"Who attended is not shared with guests.\",\n  recording: \"The recording of this meeting is not shared with guests.\",\n};\n\nconst NOT_SHARED_REMEDY =\n  \"The organization that held this meeting decided how much of its record guests can read. \" +\n  \"If you need more, ask whoever invited you — they can send it to you, or change the \" +\n  \"setting for this meeting.\";\n\nconst RESTRICTION_PART_NAME: Readonly<Record<MeetingRecordRestriction[\"part\"], string>> = {\n  attendance: \"attendance\",\n  notes: \"notes and decisions\",\n  transcript: \"word-for-word transcript\",\n  recording: \"recording\",\n};\n\nfunction joinPartNames(parts: readonly MeetingRecordRestriction[\"part\"][]): string {\n  const names = parts.map((part) => RESTRICTION_PART_NAME[part]);\n  if (names.length < 2) return names[0] ?? \"this part of the record\";\n  if (names.length === 2) return `${names[0]} and ${names[1]}`;\n  return `${names.slice(0, -1).join(\", \")}, and ${names[names.length - 1]}`;\n}\n\n/**\n * Repeated policy refusals are one access state, not four alarming cards.\n *\n * The individual rows remain durable data for absence handling in their own\n * sections. This projection groups only rows with the exact same remedy, so a\n * distinct transport or integrity failure remains visible on its own.\n */\nexport function summarizeMeetingRecordRestrictions(\n  restrictions: readonly MeetingRecordRestriction[],\n): readonly MeetingRecordRestrictionNotice[] {\n  const grouped = new Map<string, MeetingRecordRestriction[]>();\n  for (const restriction of restrictions) {\n    const rows = grouped.get(restriction.remedy) ?? [];\n    rows.push(restriction);\n    grouped.set(restriction.remedy, rows);\n  }\n  return [...grouped.values()].map((rows) => {\n    if (rows.length === 1) {\n      const row = rows[0]!;\n      return { parts: [row.part], message: row.message, remedy: row.remedy };\n    }\n    return {\n      parts: rows.map((row) => row.part),\n      message: `Some parts of this meeting record are not available to this reader: ${joinPartNames(rows.map((row) => row.part))}.`,\n      remedy: rows[0]!.remedy,\n    };\n  });\n}\n\n/**\n * Read the record the server shares with THIS guest.\n *\n * `roomToken` is the pass this device kept from the meeting\n * (`TokenClient.remembered`). It is presented in a header, never appended to\n * the URL. A guest with no pass, an expired pass, or a level of `none` gets the\n * server's refusal — as restrictions on a real bundle, so the screen says what\n * it cannot show instead of collapsing into an error page.\n */\nexport async function loadGuestMeetingRecord(args: {\n  api: MeetApi;\n  repository: MeetRepository;\n  meetingId: MeetingId;\n  meeting: MeetingRecord;\n  roomToken: RoomToken | null;\n  /**\n   * A SIGNED-IN reader the database refused (from another organization, or a\n   * guest who later created an account). Their session stands in for the\n   * pass: the server reads their `user:<id>` admission or the attendance they\n   * claimed, and shares what guests may read (2026-10-01).\n   */\n  session?: boolean;\n  /**\n   * THE SESSION-AWARE RECORD (CORE-DESIGN §2.3): one run of a series. Omitted = the server's\n   * default (a one-off meeting's whole record; a series' latest ended run).\n   */\n  sessionId?: string | null;\n}): Promise<MeetingRecordBundle> {\n  const { api, repository, meetingId, meeting, roomToken } = args;\n  const session = args.session === true;\n\n  if (roomToken?.meetingPass == null && !session) {\n    // NOT A GUESS AND NOT A FETCH. This browser has no pass for this meeting,\n    // which the server would answer with the same sentence — asking it first\n    // would only add a round trip and a 403 in the console.\n    return refusedBundle(\n      meeting,\n      \"This meeting's record is only readable by the people who were in it.\",\n      \"Open the meeting from the link you were invited with, in the same browser you used \" +\n        \"to attend — that is what identifies you to this meeting. Signing in with an \" +\n        \"account in the organization that held the meeting also works.\",\n    );\n  }\n\n  let response: Response;\n  try {\n    response = await api.request({\n      path:\n        `${MEET_ROUTES.record}?meeting_id=${encodeURIComponent(meetingId)}` +\n        (args.sessionId ? `&session_id=${encodeURIComponent(args.sessionId)}` : \"\"),\n      method: \"GET\",\n      // A GUEST HAS NO SESSION AND IS STILL A FIRST-CLASS READER (D6).\n      requireAuth: session,\n      operation: \"meet.record\",\n      headers:\n        roomToken?.meetingPass != null ? { [MEETING_PASS_HEADER]: roomToken.meetingPass } : {},\n    });\n  } catch (error) {\n    // A transport wobble is not a permission decision and must not read as one.\n    return refusedBundle(\n      meeting,\n      `This meeting's record could not be read (${(error as Error).message}).`,\n      (error as { remedy?: string }).remedy ??\n        \"This is a connection failure, not a decision about you. Reload the page.\",\n    );\n  }\n\n  if (!response.ok) {\n    const refusal = await readRefusal(response);\n    return refusedBundle(meeting, refusal.message, refusal.remedy);\n  }\n\n  const body = (await response.json()) as Record<string, unknown>;\n  const payload = (\n    typeof body[\"data\"] === \"object\" && body[\"data\"] !== null ? body[\"data\"] : body\n  ) as GuestRecordPayload;\n\n  const rows = (key: keyof GuestRecordPayload): Record<string, unknown>[] =>\n    Array.isArray(payload[key]) ? (payload[key] as Record<string, unknown>[]) : [];\n\n  const attendees = rows(\"attendees\").map((row) => repository.projectAttendee(row));\n  const notes = rows(\"notes\").map((row) => repository.projectNote(row));\n  const transcript = rows(\"transcript\").map((row) => repository.projectSegment(row));\n  const recordings = rows(\"recordings\").map((row) => repository.projectRecording(row));\n\n  // 🚨 THE RESTRICTIONS COME FROM `shared`, NOT FROM AN EMPTY ARRAY. A level of\n  // `summary` and a meeting where nobody spoke both produce zero transcript\n  // rows, and telling the reader they are the same thing is the MRI-A16 defect.\n  const shared = (payload.shared ?? {}) as Record<string, boolean>;\n  const restrictions: MeetingRecordRestriction[] = [];\n  for (const part of [\"attendance\", \"notes\", \"transcript\", \"recording\"] as const) {\n    if (shared[part] === false) {\n      restrictions.push({ part, message: NOT_SHARED[part], remedy: NOT_SHARED_REMEDY });\n    }\n  }\n\n  return {\n    meeting,\n    attendees,\n    summary: activeWrapUpSummary(notes),\n    decisions: notes.filter((note) => note.kind === \"decision\" && note.supersededBy === null),\n    actionItems: notes.filter(\n      (note) => note.kind === \"action-item\" && note.supersededBy === null,\n    ),\n    liveNotes: notes\n      .filter((note) => note.kind === \"note\" && note.role === null)\n      .slice()\n      .sort((left, right) => {\n        const a = left.window ?? Number.MAX_SAFE_INTEGER;\n        const b = right.window ?? Number.MAX_SAFE_INTEGER;\n        return a === b ? left.createdAt.localeCompare(right.createdAt) : a - b;\n      }),\n    transcript,\n    recording: recordings[0] ?? null,\n    restrictions,\n    names: learnNames(\n      learnNames({}, attendees),\n      transcript.map((line) => ({ identity: line.identity, displayName: line.speaker })),\n    ),\n  };\n}\n\n/** The row shapes the route returns — the same snake_case the tables use. */\ninterface GuestRecordPayload {\n  readonly access?: GuestRecordAccess;\n  readonly access_source?: \"meeting\" | \"organization\";\n  readonly shared?: Record<string, boolean>;\n  readonly attendees?: unknown;\n  readonly notes?: unknown;\n  readonly transcript?: unknown;\n  readonly recordings?: unknown;\n  readonly recording_notice?: string;\n}\n\n/**\n * THE SERVER'S OWN WORDS, verbatim. Every meet refusal carries\n * `{message, remedy}`, and a house sentence written over it would hide the one\n * thing worth reading — including the difference between \"your pass expired,\n * open the link again\" and \"this record is not shared with guests\".\n */\nasync function readRefusal(\n  response: Response,\n): Promise<{ message: string; remedy: string }> {\n  try {\n    const body = (await response.json()) as Record<string, unknown>;\n    const detail = (\n      typeof body[\"detail\"] === \"object\" && body[\"detail\"] !== null ? body[\"detail\"] : body\n    ) as Record<string, unknown>;\n    const message = detail[\"message\"];\n    const remedy = detail[\"remedy\"];\n    if (typeof message === \"string\" && message.length > 0) {\n      return {\n        message,\n        remedy:\n          typeof remedy === \"string\" && remedy.length > 0\n            ? remedy\n            : \"Ask whoever hosted the meeting for what you need.\",\n      };\n    }\n  } catch {\n    /* falls through to the status sentence below */\n  }\n  return {\n    message: `This meeting's record could not be read (the server answered ${response.status}).`,\n    remedy:\n      \"This is not a decision about you — it is a failure to reach the record. Reload the \" +\n      \"page; if it repeats, tell whoever hosted the meeting.\",\n  };\n}\n\n/** A real bundle whose every part is refused, with ONE reason said once. */\nfunction refusedBundle(\n  meeting: MeetingRecord,\n  message: string,\n  remedy: string,\n): MeetingRecordBundle {\n  return {\n    meeting,\n    attendees: [],\n    summary: null,\n    decisions: [],\n    actionItems: [],\n    liveNotes: [],\n    transcript: [],\n    recording: null,\n    // Every empty collection below is a refusal, never evidence of absence.\n    // The record renderer asks its own part before it writes an empty-state\n    // sentence, so omitting attendance here made a denied roster read as\n    // “Nobody attended.” `summarizeMeetingRecordRestrictions` still presents\n    // this shared server reason once at the top of the record.\n    restrictions: ([\"attendance\", \"notes\", \"transcript\", \"recording\"] as const).map(\n      (part) => ({ part, message, remedy }),\n    ),\n    names: {},\n  };\n}\n\n/**\n * A HOST chooses what guests may read of THIS meeting.\n *\n * Host power is the SERVER's decision and it re-checks it; this function exists\n * so the control has one call to make, and it returns what the choice RESOLVES\n * to so the screen never has to guess what \"my organization's setting\" means\n * today.\n */\nexport async function setGuestRecordAccess(args: {\n  api: MeetApi;\n  meetingId: MeetingId;\n  organizationId: OrganizationId;\n  access: GuestRecordAccessSetting;\n}): Promise<{\n  readonly setting: GuestRecordAccessSetting;\n  readonly effective: GuestRecordAccessResolution;\n}> {\n  const response = await args.api.request({\n    path: MEET_ROUTES.recordAccess,\n    method: \"POST\",\n    requireAuth: true,\n    operation: \"meet.record.access\",\n    body: {\n      meeting_id: args.meetingId,\n      organization_id: args.organizationId,\n      access: args.access,\n    },\n  });\n  if (!response.ok) {\n    const refusal = await readRefusal(response);\n    throw new MeetError(\"forbidden\", refusal.message, refusal.remedy);\n  }\n  const body = (await response.json()) as Record<string, unknown>;\n  const payload = (\n    typeof body[\"data\"] === \"object\" && body[\"data\"] !== null ? body[\"data\"] : body\n  ) as {\n    setting?: GuestRecordAccessSetting;\n    effective?: GuestRecordAccessResolution;\n  };\n  return {\n    setting: payload.setting ?? args.access,\n    effective: payload.effective ?? { level: \"summary\", source: \"organization\" },\n  };\n}\n\n/** What a guest is told when the level shares nothing. Rendered, never hidden. */\nexport const GUEST_RECORD_NOT_SHARED = NOT_SHARED;\n","/**\n * ONE MEETING RECORD PER READER PER TAB — read once, kept current by one\n * ref-counted channel (0.7.79).\n *\n * 🚨 THE DEFECT THIS CLOSES. `useMeetingRecord` held the bundle in its own\n * component state and read all four parts (`meet_participants`, `meet_notes`,\n * `meet_transcript_segments`, `meet_recordings`) in a mount effect. A host that\n * hides a view without unmounting its data — a board tile asleep under React\n * `<Activity>`, which tears every effect down and runs it again on wake — read\n * the whole record again on every wake, on a Remove + Undo, and once more for\n * every second view of the same meeting (the record tab, the meeting's agent\n * surface, five \"meeting notes\" tiles). The view owned the data.\n *\n * THE SHAPE. One entry per (reader, meeting). The first view reads; every later\n * view — the same view after a wake or a remount included — renders the entry\n * and reads nothing. A read already in flight is joined. A forced read (Retry,\n * a reconnect) supersedes it, and an answer that lands after a newer read was\n * asked is DROPPED (the late-answer guard), so an old answer can never paint\n * over a newer one.\n *\n * LIVE WHILE HELD. A member's entry (a direct read, kept as its four parts) is\n * patched row by row from the database's change feed for the four tables, then\n * assembled again — one row, never four reads. The channel opens on the first\n * holder and closes `MEETING_RECORD_GRACE_MS` after the last one lets go, so a\n * wake or an Undo inside the grace costs nothing. Past the grace nothing\n * watched the meeting, so the entry is marked stale and the next view reads it\n * once. A guest's record arrives through the server as a finished bundle; it\n * has no change feed and is kept as it is.\n *\n * Framework-free on purpose: `react/hooks.ts` is one reader of it.\n */\n\nimport { assembleMeetingRecord, type MeetingRecordBundle, type MeetingRecordParts } from \"./record\";\nimport type { MeetingRecord } from \"./types\";\n\n/** How long a meeting's channel and kept record outlive the last view of it. */\nexport const MEETING_RECORD_GRACE_MS = 60_000;\n\nexport interface MeetingRecordFailure {\n  readonly message: string;\n  readonly remedy: string;\n}\n\nexport interface MeetingRecordState {\n  readonly loading: boolean;\n  readonly record: MeetingRecordBundle | null;\n  /** A failure that stopped the WHOLE record loading (never kept as an answer). */\n  readonly failure: MeetingRecordFailure | null;\n}\n\n/** What a read produced: the four parts (patchable), or a finished bundle (a guest's). */\nexport type MeetingRecordAnswer =\n  | { readonly kind: \"parts\"; readonly meeting: MeetingRecord; readonly parts: MeetingRecordParts }\n  | { readonly kind: \"bundle\"; readonly bundle: MeetingRecordBundle };\n\n/** One changed row, already projected by the repository. `null` + `removedId` = gone. */\nexport type MeetingRecordChange =\n  | { readonly part: \"transcript\"; readonly row: MeetingRecordParts[\"transcript\"][number] | null; readonly removedId?: string | undefined }\n  | { readonly part: \"notes\"; readonly row: MeetingRecordParts[\"notes\"][number] | null; readonly removedId?: string | undefined }\n  | { readonly part: \"attendance\"; readonly row: MeetingRecordParts[\"attendees\"][number] | null; readonly removedId?: string | undefined }\n  | { readonly part: \"recording\"; readonly row: MeetingRecordParts[\"recordings\"][number] | null; readonly removedId?: string | undefined };\n\nexport interface MeetingRecordCache {\n  /** The kept state for `key` (stable until it changes). */\n  state(key: string | null): MeetingRecordState;\n  subscribe(listener: () => void): () => void;\n  /**\n   * Read unless the entry is kept and current (or a read is in flight — joined).\n   * `force` reads anyway and supersedes a read in flight. Never rejects: a\n   * failure is in the state.\n   */\n  ensure(key: string, read: () => Promise<MeetingRecordAnswer>, options?: { force?: boolean }): Promise<void>;\n  /** The meeting row moved (a rename, it ended): assemble again — no read. */\n  setMeeting(key: string, meeting: MeetingRecord): void;\n  /** Apply one changed row from the change feed — no read. */\n  apply(key: string, change: MeetingRecordChange): void;\n  /**\n   * Hold the live half: `open` on the first holder, its close a grace after the\n   * last. `owner` is what the channel runs on (the realtime manager): a new\n   * owner means the old one's channels are gone, so it opens again.\n   */\n  hold(key: string, open: () => () => void, owner?: unknown): () => void;\n  /** Tests only. */\n  reset(): void;\n}\n\ninterface Entry {\n  state: MeetingRecordState;\n  meeting: MeetingRecord | null;\n  parts: MeetingRecordParts | null;\n  fresh: boolean;\n  seq: number;\n  inflight: Promise<void> | null;\n  holders: number;\n  close: (() => void) | null;\n  owner: unknown;\n  grace: ReturnType<typeof setTimeout> | null;\n}\n\nconst INITIAL: MeetingRecordState = { loading: true, record: null, failure: null };\n\nfunction upsert<T extends { readonly id: string }>(\n  rows: readonly T[],\n  row: T | null,\n  removedId: string | undefined,\n  order: (a: T, b: T) => number,\n): readonly T[] {\n  const id = row?.id ?? removedId;\n  if (id === undefined) return rows;\n  const rest = rows.filter((existing) => existing.id !== id);\n  return row === null ? rest : [...rest, row].sort(order);\n}\n\nconst byId = (a: { id: string }, b: { id: string }) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0);\nconst ascending = (a: string | null, b: string | null) =>\n  a === b ? 0 : a === null ? 1 : b === null ? -1 : a < b ? -1 : 1;\n\nexport function createMeetingRecordCache(\n  options: { graceMs?: number } = {},\n): MeetingRecordCache {\n  const graceMs = options.graceMs ?? MEETING_RECORD_GRACE_MS;\n  const entries = new Map<string, Entry>();\n  const listeners = new Set<() => void>();\n  const notify = () => {\n    for (const listener of listeners) listener();\n  };\n  const entryOf = (key: string): Entry => {\n    let entry = entries.get(key);\n    if (!entry) {\n      entry = {\n        state: INITIAL,\n        meeting: null,\n        parts: null,\n        fresh: false,\n        seq: 0,\n        inflight: null,\n        holders: 0,\n        close: null,\n        owner: null,\n        grace: null,\n      };\n      entries.set(key, entry);\n    }\n    return entry;\n  };\n  const assemble = (entry: Entry) => {\n    if (entry.meeting === null || entry.parts === null) return;\n    entry.state = { loading: false, failure: null, record: assembleMeetingRecord(entry.meeting, entry.parts) };\n    notify();\n  };\n\n  return {\n    state: (key) => (key === null ? INITIAL : (entries.get(key)?.state ?? INITIAL)),\n    subscribe(listener) {\n      listeners.add(listener);\n      return () => {\n        listeners.delete(listener);\n      };\n    },\n    ensure(key, read, { force = false } = {}) {\n      const entry = entryOf(key);\n      if (!force) {\n        if (entry.inflight !== null) return entry.inflight;\n        if (entry.fresh) return Promise.resolve();\n      }\n      const seq = ++entry.seq;\n      if (entry.state.failure !== null) {\n        // Retrying after a failure says it is loading again; a kept record stays on screen.\n        entry.state = { ...entry.state, loading: true, failure: null };\n        notify();\n      }\n      const request = read().then(\n        (answer) => {\n          if (seq !== entry.seq) return; // a newer read was asked: this answer is old\n          entry.fresh = true;\n          if (answer.kind === \"parts\") {\n            entry.meeting = answer.meeting;\n            entry.parts = answer.parts;\n            assemble(entry);\n          } else {\n            entry.meeting = answer.bundle.meeting;\n            entry.parts = null;\n            entry.state = { loading: false, failure: null, record: answer.bundle };\n            notify();\n          }\n        },\n        (thrown: unknown) => {\n          if (seq !== entry.seq) return;\n          // A failure is never kept as the answer: the next view (or Retry) asks again.\n          entry.fresh = false;\n          entry.state = {\n            loading: false,\n            record: entry.state.record,\n            failure: {\n              message: (thrown as Error)?.message ?? String(thrown),\n              remedy:\n                (thrown as { remedy?: string })?.remedy ??\n                \"The meeting record could not be read. Reload the page; nothing was changed.\",\n            },\n          };\n          notify();\n        },\n      );\n      const tracked = request.finally(() => {\n        if (entry.inflight === tracked) entry.inflight = null;\n      });\n      entry.inflight = tracked;\n      return tracked;\n    },\n    setMeeting(key, meeting) {\n      const entry = entries.get(key);\n      if (!entry || entry.meeting === meeting) return;\n      if (entry.parts !== null) {\n        entry.meeting = meeting;\n        assemble(entry);\n      } else if (entry.state.record !== null) {\n        entry.meeting = meeting;\n        entry.state = { ...entry.state, record: { ...entry.state.record, meeting } };\n        notify();\n      }\n    },\n    apply(key, change) {\n      const entry = entries.get(key);\n      const parts = entry?.parts;\n      if (!entry || !parts) return;\n      // A part this reader was refused stays refused: a row it cannot read is not news to it.\n      const refused = parts.restrictions.some((r) => r.part === change.part);\n      if (refused) return;\n      switch (change.part) {\n        case \"transcript\":\n          entry.parts = {\n            ...parts,\n            transcript: upsert(parts.transcript, change.row, change.removedId, (a, b) =>\n              ascending(a.startedAt, b.startedAt) || byId(a, b),\n            ),\n          };\n          break;\n        case \"notes\":\n          entry.parts = {\n            ...parts,\n            notes: upsert(parts.notes, change.row, change.removedId, (a, b) =>\n              ascending(a.createdAt, b.createdAt) || byId(a, b),\n            ),\n          };\n          break;\n        case \"attendance\":\n          entry.parts = {\n            ...parts,\n            attendees: upsert(parts.attendees, change.row, change.removedId, (a, b) =>\n              ascending(a.joinedAt, b.joinedAt) || byId(a, b),\n            ),\n          };\n          break;\n        case \"recording\":\n          entry.parts = {\n            ...parts,\n            // Newest first, as the read orders them.\n            recordings: upsert(parts.recordings, change.row, change.removedId, (a, b) =>\n              ascending(b.startedAt, a.startedAt) || byId(a, b),\n            ),\n          };\n          break;\n      }\n      assemble(entry);\n    },\n    hold(key, open, owner = null) {\n      const entry = entryOf(key);\n      if (entry.grace !== null) {\n        clearTimeout(entry.grace);\n        entry.grace = null;\n      }\n      if (entry.close !== null && entry.owner !== owner) {\n        entry.close();\n        entry.close = null;\n      }\n      if (entry.close === null) {\n        entry.close = open();\n        entry.owner = owner;\n      }\n      entry.holders += 1;\n      let released = false;\n      return () => {\n        if (released) return;\n        released = true;\n        entry.holders -= 1;\n        if (entry.holders > 0) return;\n        entry.grace = setTimeout(() => {\n          entry.grace = null;\n          if (entry.holders > 0) return;\n          entry.close?.();\n          entry.close = null;\n          // Nothing watched the meeting from here on: the next view reads it once.\n          entry.fresh = false;\n        }, graceMs);\n      };\n    },\n    reset() {\n      for (const entry of entries.values()) {\n        if (entry.grace !== null) clearTimeout(entry.grace);\n        entry.close?.();\n      }\n      entries.clear();\n      notify();\n    },\n  };\n}\n","/**\n * The caption button's honest state (D7: nothing fails silently). Pure, so the \"Starting captions\n * forever\" defect is provable without a socket: once the start ceiling\n * (`captions_start_timeout_seconds`) passes with no note-taker transcribing, the state is\n * `unavailable` with a plain sentence and a retry — never an endless \"starting\".\n */\nexport const CAPTIONS_TIMEOUT_REASON = \"Captions are unavailable right now.\";\n\nexport type CaptionsViewState = \"off\" | \"starting\" | \"live\" | \"unavailable\";\n\nexport interface CaptionsStateInput {\n  readonly on: boolean;\n  readonly takerState: string;\n  readonly takerPresent: boolean;\n  readonly refusal: { readonly reason: string; readonly remedy: string } | null;\n  readonly takerLabel: string;\n  /** True once the start ceiling passed while still starting. */\n  readonly timedOut: boolean;\n}\n\nexport interface CaptionsView {\n  readonly state: CaptionsViewState;\n  readonly reason: string | null;\n  readonly remedy: string | null;\n}\n\nexport function resolveCaptionsState(i: CaptionsStateInput): CaptionsView {\n  if (!i.on) return { state: \"off\", reason: null, remedy: null };\n  if (i.takerState === \"transcribing\" && i.takerPresent) return { state: \"live\", reason: null, remedy: null };\n  if (i.takerState === \"joining\" && !i.timedOut) return { state: \"starting\", reason: null, remedy: null };\n  if (i.refusal !== null && i.refusal.reason.length > 0) {\n    return { state: \"unavailable\", reason: i.refusal.reason, remedy: i.refusal.remedy.length > 0 ? i.refusal.remedy : null };\n  }\n  if (i.takerState === \"ended\" || i.takerState === \"handoff_pending\") {\n    return { state: \"unavailable\", reason: i.takerLabel, remedy: null };\n  }\n  if (i.timedOut) return { state: \"unavailable\", reason: CAPTIONS_TIMEOUT_REASON, remedy: null };\n  return { state: \"starting\", reason: null, remedy: null };\n}\n","/**\n * THE STAGE — who is big, who is small, and who is not rendered at all.\n *\n * This is pure arithmetic on purpose: layout is the part of a meeting UI that\n * everyone re-derives inside a component and gets subtly wrong, and it is\n * trivially testable once it stops living in JSX.\n *\n * R5 SCALE HONESTY lives here. A 200-person meeting does not render 200 video\n * tiles — every browser dies, and LiveKit's adaptive stream cannot save a\n * layout that asked for 200 subscriptions. The grid PAGES, and the ordering is\n * deliberate rather than \"whatever the roster map iterated\":\n *\n *   1. a screen share (or an explicit pin) owns the stage;\n *   2. then the active speakers, most recent first;\n *   3. then anyone with a hand raised — they are asking to be seen;\n *   4. then cameras on before cameras off (an avatar tile is cheap);\n *   5. then stable by join time, so tiles do not shuffle every time someone\n *      breathes. Shuffling tiles is the single most disorienting thing a\n *      meeting UI can do.\n */\n\nimport { isObserverRole, type MeetParticipant, type ParticipantIdentity, type StageLayout } from \"./types\";\n\nexport interface StageArgs {\n  readonly participants: readonly MeetParticipant[];\n  readonly layout: StageLayout;\n  readonly pinned: ParticipantIdentity | null;\n  readonly activeSpeakers: readonly ParticipantIdentity[];\n  /**\n   * The participant a HOST spotlighted for everyone (Meet wave 2). A local pin\n   * outranks it on this screen; a screen share outranks both.\n   */\n  readonly spotlight?: ParticipantIdentity | null | undefined;\n  /** How many tiles this viewport can honestly render. Default 12. */\n  readonly pageSize?: number;\n  readonly page?: number;\n}\n\nexport interface Stage {\n  /** The large tile, when the layout has one. */\n  readonly feature: MeetParticipant | null;\n  /** What actually renders as a tile, already paged. */\n  readonly tiles: readonly MeetParticipant[];\n  /** Everyone not on this page. Rendered as \"+N others\", never dropped silently. */\n  readonly overflow: number;\n  readonly page: number;\n  readonly pageCount: number;\n  /** True when a screen share, not a person, is the reason for the big tile. */\n  readonly presenting: boolean;\n}\n\nexport const DEFAULT_PAGE_SIZE = 12;\n\nexport function orderParticipants(\n  participants: readonly MeetParticipant[],\n  activeSpeakers: readonly ParticipantIdentity[],\n): readonly MeetParticipant[] {\n  const speakerRank = new Map<ParticipantIdentity, number>();\n  activeSpeakers.forEach((identity, index) => speakerRank.set(identity, index));\n\n  return [...participants].sort((a, b) => {\n    const speakerA = speakerRank.get(a.identity) ?? Number.MAX_SAFE_INTEGER;\n    const speakerB = speakerRank.get(b.identity) ?? Number.MAX_SAFE_INTEGER;\n    if (speakerA !== speakerB) return speakerA - speakerB;\n    if (a.handRaised !== b.handRaised) return a.handRaised ? -1 : 1;\n    if (a.cameraEnabled !== b.cameraEnabled) return a.cameraEnabled ? -1 : 1;\n    // STABLE from here down. Join time, then identity — never Math.random,\n    // never map order, both of which reshuffle the grid on every event.\n    if (a.joinedAt !== b.joinedAt) return a.joinedAt < b.joinedAt ? -1 : 1;\n    return a.identity < b.identity ? -1 : 1;\n  });\n}\n\nexport function computeStage(args: StageArgs): Stage {\n  const pageSize = Math.max(1, args.pageSize ?? DEFAULT_PAGE_SIZE);\n  // A SILENT OBSERVER (MD-16) watches; it is never a tile — not on anyone's stage, its own included.\n  const ordered = orderParticipants(\n    args.participants.filter((participant) => !isObserverRole(participant.role)),\n    args.activeSpeakers,\n  );\n\n  const sharer = ordered.find((participant) => participant.screenSharing) ?? null;\n  const pinnedParticipant =\n    args.pinned === null\n      ? null\n      : ordered.find((participant) => participant.identity === args.pinned) ?? null;\n\n  // A SCREEN SHARE OUTRANKS A PIN, deliberately: someone presenting is the\n  // reason everyone is looking, and a stale pin hiding a live demo is the\n  // complaint this rule exists to prevent.\n  const spotlit =\n    args.spotlight == null\n      ? null\n      : ordered.find((participant) => participant.identity === args.spotlight) ?? null;\n\n  const feature =\n    sharer !== null\n      ? sharer\n      : pinnedParticipant !== null && args.layout !== \"grid\"\n        ? pinnedParticipant\n        : spotlit !== null\n          ? spotlit\n          : args.layout === \"grid\"\n            ? null\n            : ordered[0] ?? null;\n\n  const rest =\n    feature === null\n      ? ordered\n      : ordered.filter((participant) => participant.identity !== feature.identity);\n\n  const pageCount = Math.max(1, Math.ceil(rest.length / pageSize));\n  const page = Math.min(Math.max(0, args.page ?? 0), pageCount - 1);\n  const tiles = rest.slice(page * pageSize, page * pageSize + pageSize);\n\n  return {\n    feature,\n    tiles,\n    overflow: rest.length - tiles.length,\n    page,\n    pageCount,\n    presenting: sharer !== null,\n  };\n}\n\n/** Column count for a grid of N tiles — the shape that keeps tiles squarest. */\nexport function gridColumns(count: number): number {\n  if (count <= 1) return 1;\n  if (count <= 4) return 2;\n  if (count <= 9) return 3;\n  if (count <= 16) return 4;\n  return 5;\n}\n","/**\n * `<MeetingSkinRoot>` — the meeting page's one entry (CORE-DESIGN §5.3, S1).\n *\n * Everything that is not a look lives here, once, for every skin: the inert\n * guard, the observation root (S0), watching the room and the meeting's durable\n * feed, seeding the store with the row the consumer resolved, and the ended\n * meeting's record (a skin-external surface). It then renders the viewer's\n * skin — only `meet` until S9 adds the switcher.\n */\n\nimport { useEffect, type ReactNode } from \"react\";\nimport { isLivePhase } from \"../core/phase\";\nimport { hasEnded } from \"../core/record\";\nimport { asMeetingId, type MeetingRecord, type RoomName } from \"../core/types\";\nimport { InertNotice, MeetSkinRoom } from \"../skins/meet/components\";\nimport { MeetingRecordView } from \"./record\";\nimport { MeetRoot } from \"./root\";\nimport { useMeetHost, useMeetSnapshot, type MeetHost } from \"./provider\";\n\nexport interface MeetingSkinRootProps {\n  roomName: RoomName;\n  meetingId?: string;\n  slug?: string;\n  /**\n   * The meeting the host already resolved, when it has one (MRI-D2).\n   *\n   * 🚨 THIS IS WHAT MAKES AN ENDED MEETING WORK FOR A GUEST. Only\n   * `meet_meeting_by_slug` is granted to `anon`; the `meet_meetings` TABLE is\n   * not, so the durable-feed backfill — a table read — is refused for a\n   * link-follower and `snapshot.meeting` stays null for them forever. A\n   * consumer that resolved the slug through the RPC passes the row here, and\n   * the record renders for exactly the reader who has nothing else.\n   */\n  meeting?: MeetingRecord;\n  onLeave?: () => void;\n  /**\n   * A HOST-PROVIDED control for the in-meeting header (matrx-frontend puts its\n   * Intelligence icon for the meeting's AI jobs here). Rendered in the header\n   * row of the live room only. The package never inspects it.\n   */\n  headerControls?: ReactNode;\n  /**\n   * HR-360 wave 2 (MD-16): join as a SILENT OBSERVER — no camera, no microphone, no tile.\n   * The server decides whether this person may (the host, a co-host, or someone named).\n   */\n  observe?: boolean;\n}\n\nexport function MeetingSkinRoot(props: MeetingSkinRootProps): ReactNode {\n  // THE GUARD, not a throw. See <InertNotice>.\n  const host = useMeetHost();\n  // THE OBSERVATION ROOT (S0): one per tab, around every screen this renders.\n  if (host === null) {\n    return (\n      <MeetRoot meeting={props.meeting}>\n        <div className=\"mx-meet\">\n          <InertNotice what=\"This meeting\" />\n        </div>\n      </MeetRoot>\n    );\n  }\n  return (\n    <MeetRoot meeting={props.meeting}>\n      <MeetingSkinRootBody {...props} host={host} />\n    </MeetRoot>\n  );\n}\n\nfunction MeetingSkinRootBody({\n  roomName,\n  meetingId,\n  slug,\n  meeting: given,\n  onLeave,\n  headerControls,\n  observe,\n  host,\n}: MeetingSkinRootProps & { host: MeetHost }): ReactNode {\n  const snapshot = useMeetSnapshot();\n  const phase = snapshot?.phase ?? \"resolving\";\n\n  useEffect(() => {\n    host.meetings.watch(roomName);\n  }, [host, roomName]);\n\n  // 🚨 THE ONE WAY INTO PRE-JOIN WITHOUT A CLICK (CORE-DESIGN §3.1): this meeting's screen\n  // mounted, so its link resolved — `resolving` → `prejoin`. A tab still showing ANOTHER\n  // room's ending (a previous meeting's `left`, a finished call) starts this one fresh.\n  useEffect(() => {\n    const now = host.store.snapshot();\n    if (now.phase !== \"resolving\" && now.roomName !== null && now.roomName !== roomName && now.call === null) {\n      host.store.dispatch({ type: \"reset\" });\n    }\n    if (host.store.snapshot().phase !== \"resolving\") return;\n    // S6b — RELOAD-AFTER-OFFLINE: this tab was in (or dropped from) this call moments ago and the\n    // page reloaded (Chrome's own offline page reloading, a refresh). Straight back in — the\n    // server restores role, hand and admission from the person row; never the pre-join.\n    if (given?.linkRun?.reason == null && host.engine.resume(roomName)) return;\n    // THE LINK ALREADY SAID WHAT THIS RUN IS (CORE-DESIGN §2.3/§3.4): a run that has ended, or an\n    // occurrence that was canceled, goes straight to its own screen — a Join button that the gate\n    // is certain to refuse is never drawn. Anything else (open, not started, unknown) is pre-join.\n    const reason = given?.linkRun?.reason ?? null;\n    if (reason !== null && given?.linkRun !== undefined) {\n      const words = linkRunWords(given.linkRun);\n      host.store.patch({ failure: { message: words.message, remedy: words.remedy, reason } });\n      if (host.store.dispatch({ type: \"link_state\", reason })) return;\n    }\n    host.store.dispatch({ type: \"resolved\" });\n  }, [host, roomName, phase, given]);\n\n  // 🚨 THE RESOLVED ROW SEEDS THE SNAPSHOT, AND THAT IS THE WHOLE GUEST LANE\n  // (MRI-A12). `snapshot.meeting` is otherwise written only by the Postgres\n  // Changes subscription and its backfill — both read the `meet_meetings`\n  // TABLE, which `anon` cannot select. The consumer already resolved the row\n  // through `meet_meeting_by_slug` and hands it here. Written ONCE, only when\n  // the store has nothing: the durable feed's copy is the record.\n  useEffect(() => {\n    if (given === undefined) return;\n    if (host.store.snapshot().meeting !== null) return;\n    host.store.patch({ meeting: given, locked: given.locked });\n  }, [host, given]);\n\n  // THE DURABLE FEED. Transcript rows, notes and the meeting row arrive by\n  // Postgres Changes; the subscription's backfill re-reads on every reconnect.\n  const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;\n  useEffect(() => {\n    if (watchedId === null) return;\n    host.meetings.watchMeeting(asMeetingId(watchedId));\n  }, [host, watchedId]);\n\n  // 🚨 AN ENDED MEETING IS A RECORD, NOT A PRE-JOIN SCREEN (MRI-D2). The live\n  // snapshot wins when it has one; the resolved row is the fallback, and the\n  // only one a guest ever has.\n  const record = snapshot?.meeting ?? given ?? null;\n  if (hasEnded(record) && !isLivePhase(phase)) {\n    return <MeetingRecordView meeting={record as MeetingRecord} />;\n  }\n\n  return (\n    <MeetSkinRoom\n      roomName={roomName}\n      {...(meetingId !== undefined ? { meetingId } : {})}\n      {...(slug !== undefined ? { slug } : {})}\n      {...(onLeave !== undefined ? { onLeave } : {})}\n      {...(headerControls !== undefined ? { headerControls } : {})}\n      {...(observe === true ? { observe: true } : {})}\n    />\n  );\n}\n\n/** The sentence for a link whose run cannot be joined — the code decides the screen, this words it. */\nexport function linkRunWords(run: NonNullable<MeetingRecord[\"linkRun\"]>): { message: string; remedy: string } {\n  if (run.reason === \"cancelled\") {\n    return {\n      message: \"This occurrence of the meeting was canceled.\",\n      remedy: \"The series continues; open the same link at its next time.\",\n    };\n  }\n  if (run.nextStart === null) {\n    return {\n      message: \"This meeting has ended.\",\n      remedy: \"The link still opens its record: summary, notes and transcript. Nobody can rejoin.\",\n    };\n  }\n  const when = new Date(run.nextStart).toLocaleString(undefined, {\n    weekday: \"short\",\n    month: \"short\",\n    day: \"numeric\",\n    hour: \"numeric\",\n    minute: \"2-digit\",\n  });\n  return {\n    message: \"This run of the meeting has ended.\",\n    remedy: `The next one starts ${when}. Open the same link then.`,\n  };\n}\n","\"use client\";\n\n/**\n * THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to\n * build the rest — the whole meeting surface ships here, because per THE\n * ALL-INCLUSIVE LAW a package that withholds its components withholds its\n * product.\n *\n * The bar: FaceTime and Zoom raised by Apple's design team. Concretely, and\n * every one of these is enforced by the stylesheet or the canary:\n *\n * - `dvh`, never `vh` — iOS Safari's `vh` includes the collapsing toolbar, so a\n *   `100vh` stage puts the control bar under the browser chrome.\n * - Safe-area insets on the control bar, so the hang-up button is not under the\n *   home indicator.\n * - 44px touch targets, and 16px input text (anything smaller zooms iOS Safari\n *   on focus, which in a meeting looks like the app broke).\n * - Semantic tokens only. There is not one hardcoded color in the package.\n * - Real loading states and no dead ends: a control the actor cannot use is\n *   ABSENT, never disabled-looking, and never a button that will be refused.\n */\n\nimport { Select as ControlSelect } from \"@ai-matrx/design-system/controls\";\nimport { useEffect, useLayoutEffect, useRef, useState, type ReactNode } from \"react\";\nimport { type CallMode, type CameraPreview, type CollabPanel, GUEST_RECORD_ACCESS_CHOICES, MEET_SHORTCUTS, type MediaEffects, type MeetHost, type MeetParticipant, type MeetingRecord, OutboundLink, type ParticipantIdentity, type ParticipantRole, type ParticipantStanding, isLinkFollower, type RoomChatMessage, type RoomName, type UseHostControlsResult, type VideoEffect, avatarPaletteIndex, createCameraPreview, formatDurationMs, getInitials, gridColumns, guestRecordAccessExplanation, guestRecordAccessLabel, isNoteTaker, listenOnlyNotice, microphoneNoticeCode, participantAttributes, participantSummary, useAudioLevel, useConsentNotice, useCountdown, useKnockNotice, useDeviceSnapshot, useElapsed, useEndMeeting, useGuestRecordAccess, useHandQueue, useHostControls, useIsHost, useLivePolicy, useLobby, useWaiting, useLocalMedia, useMediaSupervisor, deviceChipLabel, deviceFixSteps, deviceNoticeCode, deviceUnavailableReason, useMediaEffects, useMeetAi, useMeetHost, useMeetShortcuts, useMeetSnapshot, useModerationNotice, useReactions, useRecording, useRequiredMeetHost, useRole, useRoom, useStage, useTrack, type UseLobbyResult, videoEffectsSupported, useMeetCore, MEET_REACTIONS, useCaptionTranslation, useCollabPanelRequest, isObserverRole, useCaptions, useMeetAppPanel, captureHeldOf, isRefusedPhase, useLeave, type HostLeavePrompt, type LeaveChoice } from \"../../react/facade\";\nimport { createSpeakingWhileMutedDetector } from \"../../react/facade\";\nimport { Alert, AlertDescription, Button, Checkbox, ErrorBox, Label, SegmentedControl, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@ai-matrx/design-system\";\nimport { ActivitiesControl, CaptionsControl, TakeNotesControl, BreakoutBanner, BreakoutsPanel, CaptionLanguageSettings, PollsPanel, QaPanel, WhiteboardPanel } from \"./collab\";\nimport { CameraIcon, CameraOffIcon, ChatIcon, ChevronUpIcon, HandIcon, MicIcon, MicOffIcon, PeopleIcon, PhoneOffIcon, RecordIcon, ScreenShareIcon, SettingsIcon, SignalIcon, SmileIcon, SpeakerIcon, SpotlightIcon, KeyboardIcon, FlagIcon, WifiLowIcon } from \"./icons\";\nimport { CheckIcon, LockIcon, MoreHorizontalIcon, PencilIcon, PinIcon, SearchIcon, SparklesIcon, XIcon } from \"@ai-matrx/design-system/icons\";\n\n/* ------------------------------------------------------------------ inert */\n\n/**\n * 🚨 A COMPONENT IN THIS FILE NEVER THROWS BECAUSE THE PROVIDER IS INERT.\n *\n * `<MeetProvider>` is deliberately inert until a Supabase client, an\n * organization and an identity are all real — which is every server render,\n * every signed-out visitor, and every moment before the active organization\n * hydrates. Through 0.2.0 the entry components called `useRequiredMeetHost()`\n * unconditionally, so the README's own three-line integration returned a 500 on\n * every route for those visitors, and the first real consumer had to guard OUR\n * components in ITS code (register MRI-D1, matrx-frontend 2026-09-08). That is\n * exactly the massage C22 forbids, and the defect was ours.\n *\n * The rule from 0.2.1 on: an entry component either renders its product or an\n * HONEST sentence — `<InertNotice>` below — and the ambient, always-mounted\n * ones (`<IncomingCallHost>`, `<CallButton>`, `<RecordingIndicator>`) render\n * NOTHING, because there is nothing truthful to say about a call surface on a\n * page with no runtime. Internal children (`<DevicePicker>`, `<HostMenu>`,\n * `<WaitingRoom>`) keep `useRequiredMeetHost()`: they are only ever rendered\n * BELOW one of these guards, so an absent host there is a package bug and must\n * be loud.\n */\nexport function InertNotice({ what }: { what: string }): ReactNode {\n  return (\n    <div className=\"mx-meet__empty\" role=\"status\">\n      <p className=\"mx-meet__empty-title\">{what} is not ready yet</p>\n      <p className=\"mx-meet__empty-body\">\n        Calls and meetings need a signed-in identity and an active organization. This will\n        appear as soon as they resolve.\n      </p>\n    </div>\n  );\n}\n\n/* ------------------------------------------------------------------ parts */\n\nexport function MeetAvatar({\n  name,\n  url,\n  size = 40,\n}: {\n  name: string;\n  url?: string | null;\n  size?: number;\n}): ReactNode {\n  const tint = avatarPaletteIndex(name);\n  if (url != null && url.length > 0) {\n    return (\n      <img\n        className=\"mx-meet__avatar\"\n        src={url}\n        alt=\"\"\n        width={size}\n        height={size}\n        style={{ width: size, height: size }}\n      />\n    );\n  }\n  return (\n    <span\n      className=\"mx-meet__avatar mx-meet__avatar--initials\"\n      style={{\n        width: size,\n        height: size,\n        fontSize: Math.round(size * 0.38),\n        background: `var(--mx-meet-avatar-${tint})`,\n      }}\n      aria-hidden=\"true\"\n    >\n      {getInitials(name)}\n    </span>\n  );\n}\n\nexport function ControlButton({\n  label,\n  active = false,\n  danger = false,\n  pressed,\n  onClick,\n  children,\n}: {\n  label: string;\n  active?: boolean;\n  danger?: boolean;\n  /** A toggle's state, for assistive tech and the harness (`aria-pressed`). */\n  pressed?: boolean | undefined;\n  onClick: () => void;\n  children: ReactNode;\n}): ReactNode {\n  return (\n    <button\n      type=\"button\"\n      className={[\n        \"mx-meet__control\",\n        active ? \"mx-meet__control--active\" : \"\",\n        danger ? \"mx-meet__control--danger\" : \"\",\n      ]\n        .filter(Boolean)\n        .join(\" \")}\n      // The accessible name is the STATE, not the icon: \"Unmute\" when muted.\n      aria-label={label}\n      title={label}\n      {...(pressed !== undefined ? { \"aria-pressed\": pressed } : {})}\n      onClick={onClick}\n    >\n      {children}\n    </button>\n  );\n}\n\n/**\n * The recording indicator. Rendered for EVERY participant, guests included —\n * there is no prop that hides it (R5). Consent is a property of the package.\n */\nexport function RecordingIndicator(): ReactNode {\n  const { state, label, canStart } = useRecording();\n  const snapshot = useMeetSnapshot();\n  const previous = useRef(state);\n  const [stoppedAt, setStoppedAt] = useState<number | null>(null);\n  // rec-auto-stop: everyone is told when a recording ends, whoever or whatever ended it.\n  useEffect(() => {\n    const was = previous.current;\n    previous.current = state;\n    if ((was === \"recording\" || was === \"starting\") && state !== \"recording\" && state !== \"starting\") {\n      setStoppedAt(Date.now());\n      const timer = setTimeout(() => setStoppedAt(null), 10_000);\n      return () => clearTimeout(timer);\n    }\n    return undefined;\n  }, [state]);\n  const meetingId = snapshot?.meeting?.id ?? null;\n  if (label === null && stoppedAt === null) return null;\n  return (\n    <>\n      {label !== null ? (\n        <span\n          className={`mx-meet__recording mx-meet__recording--${state}`}\n          role=\"status\"\n          aria-live=\"polite\"\n        >\n          <RecordIcon width={10} height={10} />\n          {label}\n        </span>\n      ) : null}\n      {stoppedAt !== null ? (\n        <span className=\"mx-meet__recording\" role=\"status\" data-meet-notice=\"recording-stopped\">\n          Recording stopped\n        </span>\n      ) : null}\n      {state === \"processing\" ? (\n        // rec-processing: the host is told it is being made ready (the indicator says Processing…).\n        <span className=\"mx-meet__recording\" role=\"status\" data-meet-notice=\"recording-processing\">\n          Your recording is being processed. A link appears here when it is ready.\n        </span>\n      ) : null}\n      {state === \"available\" && canStart && meetingId !== null ? (\n        <OutboundLink className=\"mx-meet__link\" href={`/meetings/${meetingId}`}>\n          View recording\n        </OutboundLink>\n      ) : null}\n    </>\n  );\n}\n\nexport function ConnectionDot({ quality }: { quality: string }): ReactNode {\n  if (quality === \"excellent\" || quality === \"good\" || quality === \"unknown\") return null;\n  // Only shown when it MEANS something. A permanent green dot teaches people\n  // to ignore the indicator that matters.\n  return (\n    <span className={`mx-meet__quality mx-meet__quality--${quality}`} title={`Connection ${quality}`}>\n      <WifiLowIcon width={14} height={14} />\n    </span>\n  );\n}\n\n/* ------------------------------------------------------------------- tile */\n\n/** Host, Co-host or Guest — and nothing at all for an ordinary participant. Guest is the\n *  STANDING of a link follower, never a role (CORE-DESIGN §2.1). */\nfunction RoleBadge({\n  role,\n  standing,\n}: {\n  role: ParticipantRole;\n  standing?: ParticipantStanding | null | undefined;\n}): ReactNode {\n  if (role === \"host\") return <span className=\"mx-meet__badge\">Host</span>;\n  if (role === \"cohost\") return <span className=\"mx-meet__badge\">Co-host</span>;\n  // MD-16: a silent observer is listed, and says so.\n  if (isObserverRole(role)) return <span className=\"mx-meet__badge\" data-meet-observing=\"\">Observing</span>;\n  if (isLinkFollower(standing)) return <span className=\"mx-meet__badge\">Guest</span>;\n  return null;\n}\n\nexport function ParticipantTile({\n  participant,\n  featured = false,\n}: {\n  participant: MeetParticipant;\n  featured?: boolean;\n}): ReactNode {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const queue = useHandQueue();\n  const [menu, setMenu] = useState(false);\n  const videoRef = useTrack(\n    participant.identity,\n    participant.screenSharing ? \"screen\" : \"camera\",\n  );\n  const showVideo = participant.cameraEnabled || participant.screenSharing;\n  const pinnedHere = snapshot?.pinned === participant.identity;\n  const spotlit = snapshot?.spotlight === participant.identity;\n  // S8: who presents is the SERVER's word (replicated room state, from the screen-share track),\n  // so everyone sees the same label — including when the presenter stops from the browser's bar.\n  const presenting = snapshot?.presenter === participant.identity;\n  const handPosition = participant.handRaised\n    ? queue.findIndex((entry) => entry.identity === participant.identity) + 1\n    : 0;\n\n  return (\n    <div\n      className={[\n        \"mx-meet__tile\",\n        featured ? \"mx-meet__tile--featured\" : \"\",\n        participant.speaking ? \"mx-meet__tile--speaking\" : \"\",\n      ]\n        .filter(Boolean)\n        .join(\" \")}\n      data-identity={participant.identity}\n      {...participantAttributes(participant)}\n      {...(presenting ? { \"data-meet-participant-presenting\": \"true\" } : {})}\n    >\n      {showVideo ? (\n        <video\n          ref={videoRef}\n          className=\"mx-meet__video\"\n          autoPlay\n          playsInline\n          muted={participant.isLocal}\n        />\n      ) : (\n        <div className=\"mx-meet__tile-placeholder\">\n          <MeetAvatar name={participant.displayName} url={participant.avatarUrl} size={featured ? 96 : 56} />\n        </div>\n      )}\n\n      {presenting ? (\n        <span className=\"mx-meet__tile-presenting\" role=\"status\">\n          {participant.isLocal ? \"You are presenting\" : `${participant.displayName} is presenting`}\n        </span>\n      ) : null}\n\n      {participant.handRaised ? (\n        <span className=\"mx-meet__tile-hand\" title={`Hand raised · ${ordinal(handPosition)} in line`}>\n          <HandIcon width={14} height={14} />\n          {handPosition > 0 ? handPosition : null}\n        </span>\n      ) : null}\n\n      <div className=\"mx-meet__tile-bar\">\n        <span className=\"mx-meet__tile-name\">\n          {spotlit ? (\n            <span title=\"Spotlighted for everyone\" className=\"mx-meet__tile-flag\">\n              <SpotlightIcon width={12} height={12} />\n            </span>\n          ) : null}\n          {participant.displayName}\n          {participant.isLocal ? \" (you)\" : \"\"}\n          {/* An agent is LABELED. An invisible listener is the thing nobody\n              should ever ship. */}\n          {participant.isAgent ? <span className=\"mx-meet__badge\">AI</span> : null}\n          {/* ONE role badge in this package (MRI-A11). */}\n          <RoleBadge role={participant.role} standing={participant.standing} />\n          {/* S6b: they dropped without leaving — say so, never a vanished tile. */}\n          {participant.reconnecting === true ? <span className=\"mx-meet__badge\">Reconnecting…</span> : null}\n          {/* `net-video-auto-off`: their network paused their video, not their choice. */}\n          {participant.reconnecting !== true && participant.videoPaused === true && !participant.isLocal ? (\n            <span className=\"mx-meet__badge\" data-meet-video-paused=\"\">Video paused to save audio</span>\n          ) : null}\n        </span>\n        {!participant.micEnabled ? <MicOffIcon width={14} height={14} /> : null}\n        <QualityBars quality={participant.quality} />\n      </div>\n\n      <div className={menu ? \"mx-meet__tile-actions mx-meet__tile-actions--open\" : \"mx-meet__tile-actions\"}>\n        <ControlButton\n          label={pinnedHere ? \"Unpin\" : `Pin ${participant.displayName} for me`}\n          active={pinnedHere}\n          onClick={() => host?.engine.pin(pinnedHere ? null : participant.identity)}\n        >\n          <PinIcon strokeWidth={1.75} width={16} height={16} />\n        </ControlButton>\n        <span className=\"mx-meet__anchor\">\n          <ControlButton\n            label={`More for ${participant.displayName}`}\n            active={menu}\n            onClick={() => setMenu(!menu)}\n          >\n            <MoreHorizontalIcon strokeWidth={1.75} width={16} height={16} />\n          </ControlButton>\n          {menu ? (\n            <PersonMenu participant={participant} onClose={() => setMenu(false)} placement=\"down\" />\n          ) : null}\n        </span>\n      </div>\n    </div>\n  );\n}\n\nfunction ordinal(position: number): string {\n  if (position <= 0) return \"\";\n  const suffix =\n    position % 100 >= 11 && position % 100 <= 13\n      ? \"th\"\n      : ({ 1: \"st\", 2: \"nd\", 3: \"rd\" } as Record<number, string>)[position % 10] ?? \"th\";\n  return `${position}${suffix}`;\n}\n\n/**\n * CONNECTION QUALITY, always legible (Meet wave 2). Four bars, like every phone:\n * a stable good connection is quiet (the bars are there, faint), and a poor or\n * lost one is loud. `unknown` draws nothing — a guess is not a reading.\n */\nexport function QualityBars({ quality }: { quality: string }): ReactNode {\n  if (quality === \"unknown\") return null;\n  const bars = quality === \"excellent\" ? 3 : quality === \"good\" ? 2 : quality === \"poor\" ? 1 : 0;\n  const label =\n    quality === \"lost\" ? \"Connection lost\" : quality === \"poor\" ? \"Poor connection\" : `Connection ${quality}`;\n  return (\n    <span className={`mx-meet__signal mx-meet__signal--${quality}`} title={label} aria-label={label} role=\"img\">\n      <SignalIcon bars={bars as 0 | 1 | 2 | 3} width={14} height={14} />\n    </span>\n  );\n}\n\n/** The reconnect banner's words per `connection` region value (S6b). */\nconst CONNECTION_BANNER: Record<string, string> = {\n  signal_reconnecting: \"Reconnecting…\",\n  reconnecting: \"Reconnecting…\",\n  offline: \"You're offline. Reconnecting when your internet is back…\",\n  server_unreachable: \"Can't reach the meeting server. Retrying…\",\n};\n\n/* ------------------------------------------------------------------ stage */\n\nexport function Stage({ pageSize }: { pageSize?: number }): ReactNode {\n  const stage = useStage(pageSize);\n  const columns = gridColumns(stage.tiles.length);\n\n  if (stage.feature === null && stage.tiles.length === 0) {\n    return (\n      <div className=\"mx-meet__stage mx-meet__stage--empty\">\n        <p className=\"mx-meet__empty-title\">Waiting for others to join</p>\n        <p className=\"mx-meet__empty-body\">\n          Share the meeting link and people can join from anywhere — no account needed.\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div className={`mx-meet__stage${stage.feature !== null ? \" mx-meet__stage--speaker\" : \"\"}`}>\n      {stage.feature !== null ? (\n        <ParticipantTile participant={stage.feature} featured />\n      ) : null}\n      <div\n        className=\"mx-meet__grid\"\n        style={{ \"--mx-meet-columns\": columns } as React.CSSProperties}\n      >\n        {stage.tiles.map((participant) => (\n          <ParticipantTile key={participant.identity} participant={participant} />\n        ))}\n      </div>\n      {stage.overflow > 0 ? (\n        <p className=\"mx-meet__overflow\">\n          +{stage.overflow} more {stage.overflow === 1 ? \"person\" : \"people\"} in this meeting\n        </p>\n      ) : null}\n    </div>\n  );\n}\n\n/* ------------------------------------------------------------- control bar */\n\ntype Panel = \"none\" | \"chat\" | \"people\" | \"ai\" | \"settings\" | \"polls\" | \"qa\" | \"breakouts\" | \"app\";\n\n\n/**\n * THE CONTROL BAR — one row, the same in the package's room and in any host\n * layout that composes it (the Board). Everything a person does in a meeting is\n * reachable from here or from the panels it opens, and every keyboard shortcut\n * is bound here, so a layout that renders this bar has all of it.\n */\nexport function ControlBar({ onLeave }: { onLeave?: () => void }): ReactNode {\n  const room = useRoom();\n  const recording = useRecording();\n  const [panel, setPanel] = useState<Panel>(\"none\");\n  const [chatTo, setChatTo] = useState<ParticipantIdentity | null>(null);\n  const [popover, setPopover] = useState<\"none\" | \"reactions\" | \"more\">(\"none\");\n  const [shortcuts, setShortcuts] = useState(false);\n  const snapshot = useMeetSnapshot();\n  const lobby = useLobby();\n  const controls = useHostControls();\n  const queue = useHandQueue();\n  const micUnavailable = useLocalMedia().microphone.unavailable;\n  const live = useLivePolicy();\n  const core = useMeetCore();\n  const [askPresentInstead, setAskPresentInstead] = useState(false);\n  const unread = useUnreadChat(panel === \"chat\");\n  // Meet wave 5: the shared whiteboard takes the stage while open; the panels stay.\n  const [whiteboard, setWhiteboard] = useState(false);\n  // HR-360 wave 2 (MD-15): the meeting's app panel, when the host app registered its key.\n  const app = useMeetAppPanel();\n  // The panel is why this meeting exists: it opens once, on arrival; the person may close it.\n  const appOpened = useRef(false);\n  useEffect(() => {\n    if (app === null || appOpened.current) return;\n    appOpened.current = true;\n    setPanel(\"app\");\n  }, [app]);\n\n  const toggle = (next: Panel) => setPanel(panel === next ? \"none\" : next);\n  const openActivity = (activity: CollabPanel) => {\n    if (activity === \"whiteboard\") setWhiteboard(true);\n    else setPanel(activity);\n  };\n  // A poll launched (for everyone else): open it, the way Zoom puts a poll in front of people.\n  useCollabPanelRequest((activity) => {\n    if (!controls.isHost) openActivity(activity);\n  });\n\n  // A per-person menu anywhere in the layout asked to message someone privately.\n  const privateChatAt = snapshot?.privateChatRequest?.at ?? null;\n  const meetStore = useMeetHost()?.store ?? null;\n  useEffect(() => {\n    const request = meetStore?.snapshot().privateChatRequest ?? null;\n    if (request === null) return;\n    setChatTo(request.to);\n    setPanel(\"chat\");\n    meetStore?.patch({ privateChatRequest: null });\n  }, [privateChatAt, meetStore]);\n\n  useMeetShortcuts({\n    mic: () => void room.toggleMicrophone(),\n    camera: () => void room.toggleCamera(),\n    hand: () => void room.toggleHand(),\n    chat: () => toggle(\"chat\"),\n    people: () => toggle(\"people\"),\n    help: () => setShortcuts(true),\n  });\n\n  const hasSpotlight = snapshot?.spotlight !== null && snapshot?.spotlight !== undefined;\n\n  return (\n    <>\n      <MeetingOverlays />\n      {shortcuts ? <ShortcutsSheet onClose={() => setShortcuts(false)} /> : null}\n      {panel === \"chat\" ? (\n        <ChatPanel onClose={() => setPanel(\"none\")} to={chatTo} onTo={setChatTo} />\n      ) : null}\n      {panel === \"people\" ? (\n        <PeoplePanel\n          onClose={() => setPanel(\"none\")}\n          onMessage={(identity) => {\n            setChatTo(identity);\n            setPanel(\"chat\");\n          }}\n        />\n      ) : null}\n      {panel === \"ai\" ? <AiPanel onClose={() => setPanel(\"none\")} /> : null}\n      {panel === \"settings\" ? <SettingsPanel onClose={() => setPanel(\"none\")} /> : null}\n      {panel === \"polls\" ? <PollsPanel onClose={() => setPanel(\"none\")} /> : null}\n      {panel === \"qa\" ? <QaPanel onClose={() => setPanel(\"none\")} /> : null}\n      {panel === \"breakouts\" ? <BreakoutsPanel onClose={() => setPanel(\"none\")} /> : null}\n      {whiteboard ? <WhiteboardPanel onClose={() => setWhiteboard(false)} /> : null}\n      {panel === \"app\" && app !== null ? (\n        <PanelShell title={app.title} onClose={() => setPanel(\"none\")}>\n          <div className=\"mx-meet__app-panel\" data-meet-app-panel={app.panel.key}>\n            <app.Component\n              recordId={app.panel.recordId}\n              organizationId={app.organizationId}\n              panelKey={app.panel.key}\n            />\n          </div>\n        </PanelShell>\n      ) : null}\n      <BreakoutBanner />\n      {panel !== \"people\" ? <KnockNotice onView={() => setPanel(\"people\")} /> : null}\n      <SpeakingWhileMutedNudge />\n\n      {/* The People panel says it inline, beside the row it acted on. */}\n      {controls.notice !== null && panel !== \"people\" ? (\n        <Toast text={controls.notice.text} failed={controls.notice.failed} onDone={controls.clearNotice} />\n      ) : null}\n\n      <div className=\"mx-meet__controls\">\n        {/* The label states the REFUSAL when there is one, so the control is\n            never a button that looks like it should work and doesn't. */}\n        {live.micLocked ? null : (\n          <ControlButton\n            label={\n              micUnavailable !== null\n                ? `Unmute — ${micUnavailable.remedy}`\n                : room.local?.micEnabled === true\n                  ? \"Mute (⌘D)\"\n                  : \"Unmute (⌘D)\"\n            }\n            active={room.local?.micEnabled === true}\n            onClick={() => void room.toggleMicrophone()}\n          >\n            {room.local?.micEnabled === true ? <MicIcon /> : <MicOffIcon />}\n          </ControlButton>\n        )}\n        <AudioSettingsControl />\n\n        {live.cameraLocked ? null : (\n          <ControlButton\n            label={room.local?.cameraEnabled === true ? \"Stop video (⌘E)\" : \"Start video (⌘E)\"}\n            active={room.local?.cameraEnabled === true}\n            onClick={() => void room.toggleCamera()}\n          >\n            {room.local?.cameraEnabled === true ? <CameraIcon /> : <CameraOffIcon />}\n          </ControlButton>\n        )}\n\n        <CaptionsControl />\n\n        {room.canShareScreen || (room.local?.screenSharing === true && core.share.state !== \"ended\") ? (\n          <span className=\"mx-meet__anchor\">\n            <ControlButton\n              label={room.local?.screenSharing === true ? \"Stop sharing\" : \"Share screen\"}\n              active={room.local?.screenSharing === true}\n              onClick={() => {\n                // `share-takeover`: with someone else presenting, one at a time, the press asks first.\n                if (room.local?.screenSharing !== true && room.otherPresenter !== null) setAskPresentInstead(true);\n                else void room.toggleScreenShare();\n              }}\n            >\n              <ScreenShareIcon />\n            </ControlButton>\n            {askPresentInstead && room.otherPresenter !== null ? (\n              <div className=\"mx-meet__confirm\" role=\"group\" aria-label=\"Someone else is presenting\" data-meet-notice=\"share-takeover\">\n                <span className=\"mx-meet__confirm-text\">{room.otherPresenter.name} is presenting</span>\n                <button\n                  type=\"button\"\n                  className=\"mx-meet__primary mx-meet__primary--small\"\n                  onClick={() => {\n                    setAskPresentInstead(false);\n                    void room.toggleScreenShare();\n                  }}\n                >\n                  {room.otherPresenter.rule === \"one_takeover\" ? \"Present instead\" : \"Share anyway\"}\n                </button>\n                <button type=\"button\" className=\"mx-meet__link\" onClick={() => setAskPresentInstead(false)}>\n                  Cancel\n                </button>\n              </div>\n            ) : null}\n          </span>\n        ) : null}\n\n        <span className=\"mx-meet__anchor\">\n          <ControlButton\n            label=\"Send a reaction\"\n            active={popover === \"reactions\"}\n            onClick={() => setPopover(popover === \"reactions\" ? \"none\" : \"reactions\")}\n          >\n            <SmileIcon />\n          </ControlButton>\n          {popover === \"reactions\" ? (\n            <Popover label=\"Reactions\" onClose={() => setPopover(\"none\")}>\n              <div className=\"mx-meet__emoji-bar\">\n                {MEET_REACTIONS.map((emoji) => (\n                  <button\n                    key={emoji}\n                    type=\"button\"\n                    className=\"mx-meet__emoji\"\n                    aria-label={`React ${emoji}`}\n                    onClick={() => void room.react(emoji)}\n                  >\n                    {emoji}\n                  </button>\n                ))}\n              </div>\n            </Popover>\n          ) : null}\n        </span>\n\n        <ControlButton\n          label={room.local?.handRaised === true ? \"Lower hand (⌘⌥H)\" : \"Raise hand (⌘⌥H)\"}\n          active={room.local?.handRaised === true}\n          onClick={() => void room.toggleHand()}\n        >\n          <HandIcon />\n        </ControlButton>\n\n        {app !== null ? (\n          <ControlButton label={app.title} active={panel === \"app\"} onClick={() => toggle(\"app\")}>\n            <FlagIcon />\n          </ControlButton>\n        ) : null}\n\n        <ControlButton label=\"Chat (⌘⌥C)\" active={panel === \"chat\"} onClick={() => toggle(\"chat\")}>\n          <ChatIcon />\n          {unread > 0 ? <span className=\"mx-meet__dot\" aria-hidden=\"true\" /> : null}\n        </ControlButton>\n\n        <ControlButton\n          label={\n            lobby.waiting.length > 0\n              ? `People — ${lobby.waiting.length} waiting`\n              : `People — ${(snapshot?.participants ?? []).length} in the meeting`\n          }\n          active={panel === \"people\"}\n          onClick={() => toggle(\"people\")}\n        >\n          <PeopleIcon />\n          {lobby.waiting.length > 0 || (controls.isHost && queue.length > 0) ? (\n            <span className=\"mx-meet__dot\" aria-hidden=\"true\" />\n          ) : null}\n        </ControlButton>\n\n        {/* Meet wave 5: polls, Q&A, whiteboard, breakout rooms — one door, Google\n            Meet's Activities. Absent when the organization turned them all off. */}\n        <ActivitiesControl\n          active={whiteboard ? \"whiteboard\" : panel === \"polls\" || panel === \"qa\" || panel === \"breakouts\" ? panel : null}\n          onOpen={openActivity}\n        />\n\n        <TakeNotesControl />\n\n        {/* The AI control appears only when the meeting's AI is on — never a\n            button that resolves to \"not configured\". */}\n        <AiControl active={panel === \"ai\"} onToggle={() => toggle(\"ai\")} />\n\n        {recording.canStart ? (\n          <ControlButton label=\"Start recording\" onClick={() => void recording.start()}>\n            <RecordIcon />\n          </ControlButton>\n        ) : null}\n        {recording.canStop ? (\n          <ControlButton label=\"Stop recording\" active onClick={() => void recording.stop()}>\n            <RecordIcon />\n          </ControlButton>\n        ) : null}\n\n        <span className=\"mx-meet__anchor\">\n          <ControlButton\n            label=\"More options\"\n            active={popover === \"more\" || panel === \"settings\"}\n            onClick={() => setPopover(popover === \"more\" ? \"none\" : \"more\")}\n          >\n            <MoreHorizontalIcon width={20} height={20} strokeWidth={1.75} />\n          </ControlButton>\n          {popover === \"more\" ? (\n            <Popover label=\"More options\" onClose={() => setPopover(\"none\")}>\n              <div className=\"mx-meet__menu\" role=\"menu\">\n                <MenuItem\n                  onSelect={() => {\n                    setPopover(\"none\");\n                    setPanel(\"settings\");\n                  }}\n                >\n                  <SettingsIcon width={16} height={16} /> Settings\n                </MenuItem>\n                <MenuItem\n                  onSelect={() => {\n                    setPopover(\"none\");\n                    setShortcuts(true);\n                  }}\n                >\n                  <KeyboardIcon width={16} height={16} /> Keyboard shortcuts\n                </MenuItem>\n                {!room.canShareScreen && room.sharingAllowed && room.local?.screenSharing !== true ? (\n                  // `share-unsupported-mobile`: the control is absent; the menu says where it lives.\n                  <p className=\"mx-meet__menu-note\" role=\"note\" data-meet-notice=\"share-unsupported\">\n                    <ScreenShareIcon width={16} height={16} /> Present from a computer\n                  </p>\n                ) : null}\n                {controls.isHost ? (\n                  <>\n                    <div className=\"mx-meet__menu-sep\" role=\"separator\" />\n                    <MenuItem\n                      onSelect={() => {\n                        setPopover(\"none\");\n                        void controls.run({ action: \"mute_all\" });\n                      }}\n                    >\n                      <MicOffIcon width={16} height={16} /> Mute everyone\n                    </MenuItem>\n                    <MenuItem\n                      onSelect={() => {\n                        setPopover(\"none\");\n                        void controls.run({\n                          action: \"set_av_lock\",\n                          value: snapshot?.livePolicy.avLock === \"both\" ? \"off\" : \"both\",\n                        });\n                      }}\n                    >\n                      <MicOffIcon width={16} height={16} />{\" \"}\n                      {snapshot?.livePolicy.avLock === \"both\"\n                        ? \"Turn on attendees' microphone and camera\"\n                        : \"Turn off attendees' microphone and camera\"}\n                    </MenuItem>\n                    <MenuItem\n                      onSelect={() => {\n                        setPopover(\"none\");\n                        void controls.run({ action: \"ask_all_unmute\" });\n                      }}\n                    >\n                      <MicIcon width={16} height={16} /> Ask everyone to unmute\n                    </MenuItem>\n                    <WaitingRoomRule />\n                    {queue.length > 0 ? (\n                      <MenuItem\n                        onSelect={() => {\n                          setPopover(\"none\");\n                          void controls.run({ action: \"lower_all_hands\" });\n                        }}\n                      >\n                        <HandIcon width={16} height={16} /> Lower all hands ({queue.length})\n                      </MenuItem>\n                    ) : null}\n                    {hasSpotlight ? (\n                      <MenuItem\n                        onSelect={() => {\n                          setPopover(\"none\");\n                          void controls.run({ action: \"spotlight\", identity: null });\n                        }}\n                      >\n                        <SpotlightIcon width={16} height={16} /> Remove spotlight\n                      </MenuItem>\n                    ) : null}\n                  </>\n                ) : null}\n              </div>\n            </Popover>\n          ) : null}\n        </span>\n\n        <LeaveControl onLeave={onLeave} />\n      </div>\n    </>\n  );\n}\n\n/** The words each profile's Leave uses (S8 §4.2 `host_leave_prompt`). The core decides the choices. */\nconst LEAVE_WORDS: Record<HostLeavePrompt, Record<LeaveChoice, string>> = {\n  leave_or_end: { leave: \"Leave call\", assign_and_leave: \"Assign a new host\", end_for_all: \"End call for everyone\" },\n  must_assign_or_end: { leave: \"Leave meeting\", assign_and_leave: \"Assign a new host\", end_for_all: \"End meeting for all\" },\n  leave_only: { leave: \"Leave\", assign_and_leave: \"Assign a new host\", end_for_all: \"End meeting\" },\n};\n\n/**\n * S8 `leave-or-end-choice` / `host-leave-assign`: Leave offers what the meeting's profile says\n * (Meet: Leave call · End call for everyone; Zoom: Assign a new host · End meeting for all;\n * Teams: Leave · End meeting). A non-host just leaves.\n */\nfunction LeaveControl({ onLeave }: { onLeave?: (() => void) | undefined }): ReactNode {\n  const leave = useLeave();\n  const [open, setOpen] = useState<\"none\" | \"menu\" | \"assign\" | \"confirm\">(\"none\");\n  const [failure, setFailure] = useState<string | null>(null);\n  const words = LEAVE_WORDS[leave.policy.hostLeavePrompt];\n  const run = (work: () => Promise<void>, leaving: boolean): void => {\n    setFailure(null);\n    void work()\n      .then(() => {\n        setOpen(\"none\");\n        if (leaving) onLeave?.();\n      })\n      .catch((error: unknown) => setFailure(error instanceof Error ? error.message : String(error)));\n  };\n  const leaveNow = (): void => run(leave.leave, true);\n  const endNow = (): void => run(leave.endForAll, false);\n  return (\n    <span className=\"mx-meet__anchor\">\n      <ControlButton\n        label=\"Leave\"\n        danger\n        active={open !== \"none\"}\n        onClick={() => {\n          if (leave.choices.length === 1 && leave.choices[0] === \"leave\") leaveNow();\n          else setOpen(open === \"none\" ? \"menu\" : \"none\");\n        }}\n      >\n        <PhoneOffIcon />\n      </ControlButton>\n      {open !== \"none\" ? (\n        <Popover label={open === \"assign\" ? words.assign_and_leave : \"Leave\"} onClose={() => setOpen(\"none\")}>\n          <div className=\"mx-meet__menu\" data-meet-leave-menu={leave.policy.hostLeavePrompt}>\n            {open === \"menu\"\n              ? leave.choices.map((choice) => (\n                  <button\n                    key={choice}\n                    type=\"button\"\n                    className={choice === \"end_for_all\" ? \"mx-meet__menu-item mx-meet__menu-item--danger\" : \"mx-meet__menu-item\"}\n                    onClick={() => {\n                      if (choice === \"leave\") leaveNow();\n                      else if (choice === \"assign_and_leave\") setOpen(\"assign\");\n                      else if (leave.policy.endConfirm) setOpen(\"confirm\");\n                      else endNow();\n                    }}\n                  >\n                    {words[choice]}\n                  </button>\n                ))\n              : null}\n            {open === \"assign\"\n              ? leave.candidates.map((person) => (\n                  <button\n                    key={String(person.identity)}\n                    type=\"button\"\n                    className=\"mx-meet__menu-item\"\n                    onClick={() => run(() => leave.assignAndLeave(person), true)}\n                  >\n                    {person.displayName}\n                  </button>\n                ))\n              : null}\n            {open === \"confirm\" ? (\n              <>\n                <button type=\"button\" className=\"mx-meet__menu-item mx-meet__menu-item--danger\" onClick={endNow}>\n                  {words.end_for_all}\n                </button>\n                <button type=\"button\" className=\"mx-meet__menu-item\" onClick={() => setOpen(\"menu\")}>\n                  Cancel\n                </button>\n              </>\n            ) : null}\n            {failure !== null ? (\n              <ErrorBox\n                className=\"mx-meet__menu-note\"\n                message={failure}\n                operation=\"Complete this meeting action\"\n                origin=\"meet/components\"\n              >\n                {failure}\n              </ErrorBox>\n            ) : null}\n          </div>\n        </Popover>\n      ) : null}\n    </span>\n  );\n}\n\n/** Messages that arrived while the chat panel was closed. */\nfunction useUnreadChat(open: boolean): number {\n  const snapshot = useMeetSnapshot();\n  const chat = snapshot?.chat ?? [];\n  const local = snapshot?.localIdentity ?? null;\n  const [seen, setSeen] = useState(0);\n  useEffect(() => {\n    if (open) setSeen(chat.length);\n  }, [open, chat.length]);\n  // The saved history read on join is not \"unread\" — only what arrives after it.\n  const loaded = snapshot?.chatLoaded === true;\n  const [baseline, setBaseline] = useState<number | null>(null);\n  useEffect(() => {\n    if (loaded && baseline === null) setBaseline(chat.length);\n  }, [loaded, baseline, chat.length]);\n  if (open) return 0;\n  const from = Math.max(seen, baseline ?? chat.length);\n  return chat.slice(from).filter((message) => message.identity !== local).length;\n}\n\n/**\n * A small floating surface anchored to its control. Escape and an outside click\n * close it. It is FIXED-positioned from the anchor's rectangle, because the\n * controls it hangs off live inside tiles that clip (`overflow: hidden`) and\n * inside a Board that pans — an absolutely positioned menu would be cut in half.\n */\nexport function Popover({\n  label,\n  onClose,\n  children,\n  placement = \"up\",\n}: {\n  label: string;\n  onClose: () => void;\n  children: ReactNode;\n  placement?: \"up\" | \"down\";\n}): ReactNode {\n  const ref = useRef<HTMLDivElement | null>(null);\n  // FIXED FROM THE FIRST FRAME. Hidden but in normal flow, the popover made its\n  // anchor as tall as the whole menu, so the anchor's measured bottom was the\n  // menu's bottom and the menu opened a full menu-height below its button\n  // (host menu: Make host / Report / Remove off-screen, 2026-09-27).\n  const [style, setStyle] = useState<React.CSSProperties>({\n    position: \"fixed\",\n    top: 0,\n    left: 0,\n    visibility: \"hidden\",\n  });\n  useLayoutEffect(() => {\n    const element = ref.current;\n    const anchor = element?.parentElement ?? null;\n    if (element === null || anchor === null) return;\n    const place = () => {\n      const rect = anchor.getBoundingClientRect();\n      const width = element.offsetWidth;\n      const height = element.offsetHeight;\n      const gutter = 8;\n      const left = Math.min(\n        Math.max(gutter, rect.left + rect.width / 2 - width / 2),\n        window.innerWidth - width - gutter,\n      );\n      const fitsBelow = rect.bottom + gutter + height <= window.innerHeight;\n      const fitsAbove = rect.top - gutter - height >= 0;\n      if (!fitsBelow && !fitsAbove) {\n        // NEITHER SIDE HOLDS IT (a tall host menu from a row mid-screen): pin it\n        // inside the viewport and let it scroll, so the last items — Make host,\n        // Remove from meeting — are never below the fold (2026-09-27).\n        const top = Math.max(gutter, window.innerHeight - height - gutter);\n        setStyle({\n          position: \"fixed\",\n          left,\n          top,\n          maxHeight: window.innerHeight - top - gutter,\n          overflowY: \"auto\",\n        });\n        return;\n      }\n      const down = placement === \"down\" ? fitsBelow || !fitsAbove : !fitsAbove && fitsBelow;\n      setStyle(\n        down\n          ? { position: \"fixed\", left, top: rect.bottom + gutter }\n          : { position: \"fixed\", left, bottom: window.innerHeight - rect.top + gutter },\n      );\n    };\n    place();\n    // Re-placed when the layout moves (a lobby row arriving, a panel scrolling),\n    // not only on window resize.\n    const frame = requestAnimationFrame(place);\n    const observer =\n      typeof ResizeObserver === \"undefined\" ? null : new ResizeObserver(() => place());\n    observer?.observe(document.body);\n    observer?.observe(element);\n    window.addEventListener(\"resize\", place);\n    window.addEventListener(\"scroll\", place, true);\n    return () => {\n      cancelAnimationFrame(frame);\n      observer?.disconnect();\n      window.removeEventListener(\"resize\", place);\n      window.removeEventListener(\"scroll\", place, true);\n    };\n  }, [placement]);\n  useEffect(() => {\n    const onKey = (event: KeyboardEvent) => {\n      if (event.key === \"Escape\") onClose();\n    };\n    const onPointer = (event: PointerEvent) => {\n      const anchor = ref.current?.parentElement ?? null;\n      if (anchor !== null && !anchor.contains(event.target as Node)) onClose();\n    };\n    window.addEventListener(\"keydown\", onKey);\n    window.addEventListener(\"pointerdown\", onPointer);\n    return () => {\n      window.removeEventListener(\"keydown\", onKey);\n      window.removeEventListener(\"pointerdown\", onPointer);\n    };\n  }, [onClose]);\n  return (\n    <div ref={ref} className=\"mx-meet__popover\" style={style} role=\"dialog\" aria-label={label}>\n      {children}\n    </div>\n  );\n}\n\nexport function MenuItem({\n  onSelect,\n  danger = false,\n  children,\n}: {\n  onSelect: () => void;\n  danger?: boolean;\n  children: ReactNode;\n}): ReactNode {\n  return (\n    <button\n      type=\"button\"\n      role=\"menuitem\"\n      className={danger ? \"mx-meet__menu-item mx-meet__menu-item--danger\" : \"mx-meet__menu-item\"}\n      onClick={onSelect}\n    >\n      {children}\n    </button>\n  );\n}\n\n/** `wr-policy-who-waits`: the meeting's `lobby_bypass` tiers, in the host's words. */\nconst LOBBY_BYPASS_CHOICES: readonly { readonly value: string; readonly label: string }[] = [\n  { value: \"everyone\", label: \"Everyone\" },\n  { value: \"org_and_invited\", label: \"Your organization and invited people\" },\n  { value: \"org\", label: \"Your organization\" },\n  { value: \"invited\", label: \"Invited people\" },\n  { value: \"host_only\", label: \"Only hosts\" },\n];\n\n/**\n * WHO SKIPS THE WAITING ROOM — a host's per-meeting rule (`lobby_bypass`, CORE-DESIGN §11\n * `wr-policy-who-waits`). Read and written through the meeting's own rules door; the join gate\n * applies it on the next knock. A refusal (an organization-locked rule) is said, never swallowed.\n */\nfunction WaitingRoomRule(): ReactNode {\n  const host = useRequiredMeetHost();\n  const [open, setOpen] = useState(false);\n  const [value, setValue] = useState<string | null>(null);\n  const [notice, setNotice] = useState<string | null>(null);\n  useEffect(() => {\n    let live = true;\n    void host.meetings\n      .meetingRule(\"lobby_bypass\")\n      .then((rule) => {\n        if (live) setValue(typeof rule === \"string\" ? rule : null);\n      })\n      .catch(() => undefined);\n    return () => {\n      live = false;\n    };\n  }, [host]);\n  const current = LOBBY_BYPASS_CHOICES.find((choice) => choice.value === value)?.label ?? null;\n  return (\n    <>\n      <MenuItem onSelect={() => setOpen(!open)}>\n        <LockIcon strokeWidth={1.75} width={16} height={16} /> Who can skip the waiting room\n        {current !== null ? <span className=\"mx-meet__menu-value\">{current}</span> : null}\n      </MenuItem>\n      {open ? (\n        <div role=\"group\" aria-label=\"Who can skip the waiting room\" data-meet-rule=\"lobby_bypass\">\n          {LOBBY_BYPASS_CHOICES.map((choice) => (\n            <button\n              key={choice.value}\n              type=\"button\"\n              role=\"menuitemradio\"\n              aria-checked={choice.value === value}\n              className=\"mx-meet__menu-item mx-meet__menu-item--sub\"\n              onClick={() => {\n                setNotice(null);\n                void host.meetings\n                  .setMeetingRule(\"lobby_bypass\", choice.value)\n                  .then(() => setValue(choice.value))\n                  .catch((error: unknown) => setNotice(error instanceof Error ? error.message : String(error)));\n              }}\n            >\n              {choice.value === value ? <CheckIcon strokeWidth={1.75} width={14} height={14} /> : null} {choice.label}\n            </button>\n          ))}\n          {notice !== null ? (\n            <p className=\"mx-meet__menu-note\" role=\"status\">\n              {notice}\n            </p>\n          ) : null}\n        </div>\n      ) : null}\n    </>\n  );\n}\n\n/** A transient sentence above the control bar. Stays 4 s, or until dismissed. */\nexport function Toast({ text, failed, onDone }: { text: string; failed: boolean; onDone: () => void }): ReactNode {\n  useEffect(() => {\n    const timer = setTimeout(onDone, failed ? 7000 : 4000);\n    return () => clearTimeout(timer);\n  }, [text, failed, onDone]);\n  return (\n    <div className={failed ? \"mx-meet__toast mx-meet__toast--failed\" : \"mx-meet__toast\"} role=\"status\">\n      <span>{text}</span>\n      <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Dismiss\" onClick={onDone}>\n        <XIcon strokeWidth={1.75} width={14} height={14} />\n      </button>\n    </div>\n  );\n}\n\n/**\n * S6c — WHAT THE MEDIA SUPERVISOR KNOWS, where the person is looking, in every layout: a chip per\n * unusable device (\"Mic blocked · Fix\") whose Fix opens this browser's real steps and a Try\n * again; \"Enable sound\" while the browser holds remote audio; an unplugged device and where the\n * meeting moved; a newly plugged device offered, never taken. Never a full-screen block.\n */\n/**\n * THE MICROPHONE'S ARROW (`device-switch-midcall`): every microphone, the one in use checked;\n * picking one moves the live call to it at once (and remembers it), mute state untouched.\n */\nfunction AudioSettingsControl(): ReactNode {\n  const host = useMeetHost();\n  const devices = useDeviceSnapshot();\n  const [open, setOpen] = useState(false);\n  const list = (devices?.devices.audioinput ?? []).filter((device) => device.deviceId.length > 0);\n  if (host === null || list.length < 2) return null;\n  const current = devices?.selected.audioinput ?? host.devices.resolve(\"audioinput\");\n  return (\n    <span className=\"mx-meet__anchor\">\n      <ControlButton\n        label=\"Audio settings\"\n        active={open}\n        onClick={() => {\n          if (!open) void host.devices.refresh();\n          setOpen(!open);\n        }}\n      >\n        <ChevronUpIcon />\n      </ControlButton>\n      {open ? (\n        <Popover label=\"Microphone\" onClose={() => setOpen(false)}>\n          <div className=\"mx-meet__menu\" role=\"menu\" aria-label=\"Microphone\">\n            {list.map((device) => (\n              <button\n                key={device.deviceId}\n                type=\"button\"\n                role=\"menuitemradio\"\n                aria-checked={device.deviceId === current}\n                className=\"mx-meet__menu-item\"\n                onClick={() => {\n                  setOpen(false);\n                  host.devices.select(\"audioinput\", device.deviceId);\n                  void host.engine.switchDevice(\"audioinput\", device.deviceId).catch(() => undefined);\n                }}\n              >\n                {device.deviceId === current ? <CheckIcon strokeWidth={1.75} width={16} height={16} /> : <span className=\"mx-meet__menu-gap\" />}\n                {device.label.length > 0 ? device.label : \"Microphone\"}\n              </button>\n            ))}\n          </div>\n        </Popover>\n      ) : null}\n    </span>\n  );\n}\n\n/**\n * \"YOU'RE MUTED\" (`speaking-while-muted`): while the person muted THEMSELVES, the microphone is\n * listened to locally (nothing is sent) and sustained speech brings a nudge with one-click Unmute.\n * The rule (threshold, hold, cooldown) is the core's detector; this only feeds it levels.\n */\nfunction SpeakingWhileMutedNudge(): ReactNode {\n  const room = useRoom();\n  const host = useMeetHost();\n  const devices = useDeviceSnapshot();\n  const microphone = useLocalMedia().microphone;\n  const mutedByMe = host !== null && room.local != null && room.local.micEnabled !== true && microphone.unavailable === null;\n  const mic = devices?.selected.audioinput ?? host?.devices.resolve(\"audioinput\") ?? null;\n  const stream = useMicrophoneStream(mutedByMe ? mic : \"off\");\n  const level = useAudioLevel(stream);\n  const latest = useRef(0);\n  latest.current = level;\n  const [shown, setShown] = useState(false);\n  const [detector] = useState(() => createSpeakingWhileMutedDetector());\n  useEffect(() => {\n    if (!mutedByMe) {\n      detector.reset();\n      setShown(false);\n      return undefined;\n    }\n    const timer = setInterval(() => {\n      if (detector.feed(latest.current, Date.now())) setShown(true);\n    }, 150);\n    return () => clearInterval(timer);\n  }, [mutedByMe, detector]);\n  useEffect(() => {\n    if (!shown) return undefined;\n    const timer = setTimeout(() => setShown(false), 8000);\n    return () => clearTimeout(timer);\n  }, [shown]);\n  if (!shown || !mutedByMe) return null;\n  return (\n    <div className=\"mx-meet__notice-bar\" role=\"status\" data-meet-notice=\"speaking-while-muted\">\n      <MicOffIcon width={16} height={16} />\n      <span>You're muted</span>\n      <button\n        type=\"button\"\n        className=\"mx-meet__primary mx-meet__primary--small\"\n        onClick={() => {\n          setShown(false);\n          void room.toggleMicrophone();\n        }}\n      >\n        Unmute\n      </button>\n    </div>\n  );\n}\n\nfunction MediaNotices(): ReactNode {\n  const media = useLocalMedia();\n  const { region, where, enableAudio, acceptOffer, dismissOffer, dismissNotice, undoNotice, retry } = useMediaSupervisor();\n  const [fixing, setFixing] = useState<\"microphone\" | \"camera\" | null>(null);\n  const chips = ([\"microphone\", \"camera\"] as const).flatMap((kind) => {\n    const reason = deviceUnavailableReason(media[kind], region.permission[kind]);\n    return reason === null ? [] : [{ kind, reason }];\n  });\n  const fixReason = fixing === null ? null : (chips.find((chip) => chip.kind === fixing)?.reason ?? null);\n  const notice = region.notice;\n  const offer = region.offer;\n  const name = (kind: \"microphone\" | \"camera\") => (kind === \"microphone\" ? \"Microphone\" : \"Camera\");\n  if (chips.length === 0 && region.audioOutput !== \"blocked\" && notice === null && offer === null) return null;\n  return (\n    <div className=\"mx-meet__media-notices\">\n      {region.audioOutput === \"blocked\" ? (\n        <ErrorBox\n          as=\"div\"\n          className=\"mx-meet__media-pill\"\n          data-meet-notice=\"audio-blocked\"\n          message=\"Sound is paused in this tab\"\n          operation=\"Enable meeting sound\"\n          origin=\"meet/MediaNotices\"\n        >\n          <span>Sound is paused in this tab</span>\n          <button type=\"button\" className=\"mx-meet__primary mx-meet__primary--small\" onClick={() => void enableAudio()}>\n            Enable sound\n          </button>\n        </ErrorBox>\n      ) : null}\n      {chips.map(({ kind, reason }) => (\n        <div key={kind} className=\"mx-meet__media-pill\" role=\"status\" data-meet-notice={deviceNoticeCode(kind, reason)}>\n          <span>{deviceChipLabel(kind, reason)}</span>\n          <button\n            type=\"button\"\n            className=\"mx-meet__primary mx-meet__primary--small\"\n            aria-label={kind === \"microphone\" ? \"Fix microphone\" : \"Fix camera\"}\n            aria-expanded={fixing === kind}\n            onClick={() => setFixing(fixing === kind ? null : kind)}\n          >\n            Fix\n          </button>\n        </div>\n      ))}\n      {fixing !== null && fixReason !== null ? (\n        <div className=\"mx-meet__popover mx-meet__fix-sheet\" role=\"dialog\" aria-label={`Fix ${name(fixing).toLowerCase()}`}>\n          <ol className=\"mx-meet__fix-steps\">\n            {deviceFixSteps(fixing, fixReason, where).map((step) => (\n              <li key={step}>{step}</li>\n            ))}\n          </ol>\n          <div className=\"mx-meet__fix-actions\">\n            <button\n              type=\"button\"\n              className=\"mx-meet__primary mx-meet__primary--small\"\n              onClick={() => {\n                const kind = fixing;\n                setFixing(null);\n                void retry(kind);\n              }}\n            >\n              Try again\n            </button>\n            <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Close\" onClick={() => setFixing(null)}>\n              <XIcon strokeWidth={1.75} width={14} height={14} />\n            </button>\n          </div>\n        </div>\n      ) : null}\n      {notice !== null ? (\n        <div\n          className=\"mx-meet__media-pill\"\n          role=\"status\"\n          data-meet-notice={notice.outcome === \"lost\" ? \"device-lost\" : \"device-switched\"}\n        >\n          <span>\n            {notice.outcome === \"switched\"\n              ? `${notice.from || name(notice.kind)} disconnected · switched to ${notice.to || \"the default\"}`\n              : `${notice.from || name(notice.kind)} disconnected`}\n          </span>\n          {notice.outcome === \"switched\" ? (\n            <button type=\"button\" className=\"mx-meet__link\" onClick={() => void undoNotice()}>\n              Undo\n            </button>\n          ) : null}\n          <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Dismiss\" onClick={dismissNotice}>\n            <XIcon strokeWidth={1.75} width={14} height={14} />\n          </button>\n        </div>\n      ) : null}\n      {offer !== null ? (\n        <div className=\"mx-meet__media-pill\" role=\"status\">\n          <span>{`New ${offer.kind}: ${offer.label || name(offer.kind)}`}</span>\n          <button type=\"button\" className=\"mx-meet__primary mx-meet__primary--small\" onClick={() => void acceptOffer()}>\n            Use it\n          </button>\n          <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Dismiss\" onClick={dismissOffer}>\n            <XIcon strokeWidth={1.75} width={14} height={14} />\n          </button>\n        </div>\n      ) : null}\n    </div>\n  );\n}\n\n/**\n * WHAT FLOATS OVER THE MEETING, in every layout (Meet wave 2): the reactions\n * everyone sends, and what a host just did to THIS person — \"the host is asking\n * you to unmute\" with the Unmute button right there, which is the whole point.\n */\nexport function MeetingOverlays(): ReactNode {\n  const reactions = useReactions();\n  const { notice, dismiss } = useModerationNotice();\n  const room = useRoom();\n  const live = useLivePolicy();\n  const snapshot = useMeetSnapshot();\n  const controls = useHostControls();\n  const isHostNow = useRole() === \"host\";\n  return (\n    <>\n      <ReactionOverlay reactions={reactions} />\n      <MediaNotices />\n      {snapshot !== null && snapshot.phase === \"in_call\" && snapshot.participants.length >= 2 &&\n      !snapshot.participants.some((p) => p.role === \"host\" || p.role === \"cohost\") ? (\n        // meeting-without-host: the call goes on; host-only controls are simply not on screen.\n        <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"host-absent\">\n          The host has left the meeting. Host controls are not available until a host is back.\n        </p>\n      ) : null}\n      {live.consent !== null ? (\n        <div className=\"mx-meet__sheet-backdrop\">\n          <div className=\"mx-meet__sheet\" role=\"alertdialog\" aria-label=\"This meeting is being recorded\" data-meet-notice=\"recording-consent\">\n            <h2 className=\"mx-meet__panel-title\">This meeting is being recorded</h2>\n            <p className=\"mx-meet__confirm-text\">\n              {live.consent === \"ok_or_leave\"\n                ? \"By staying you agree to be recorded. You can leave now if you do not agree.\"\n                : \"Until you agree to the recording you can watch and listen, but not use your microphone or camera.\"}\n            </p>\n            <div className=\"mx-meet__menu-actions\">\n              <button type=\"button\" className=\"mx-meet__send\" onClick={live.agree}>\n                {live.consent === \"ok_or_leave\" ? \"OK\" : \"I agree\"}\n              </button>\n              {live.consent === \"ok_or_leave\" ? (\n                <button type=\"button\" className=\"mx-meet__link\" onClick={() => void room.leave()}>\n                  Leave meeting\n                </button>\n              ) : null}\n            </div>\n          </div>\n        </div>\n      ) : null}\n      {snapshot?.canReclaim === true && !isHostNow ? (\n        <div className=\"mx-meet__notice-bar\" role=\"status\" data-meet-notice=\"host-reclaim\">\n          <span>You started this meeting. Take back the host?</span>\n          <button\n            type=\"button\"\n            className=\"mx-meet__primary mx-meet__primary--small\"\n            onClick={() => void controls.run({ action: \"reclaim_host\" })}\n          >\n            Reclaim host\n          </button>\n        </div>\n      ) : null}\n      {live.micLocked || live.cameraLocked ? (\n        <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"mic-locked\">\n          {live.micLocked && live.cameraLocked\n            ? \"Your microphone and camera are turned off by the organizer.\"\n            : live.micLocked\n              ? \"Your microphone is turned off by the organizer.\"\n              : \"Your camera is turned off by the organizer.\"}\n        </p>\n      ) : null}\n      {live.timeWarning && live.minutesLeft !== null && live.minutesLeft > 0 ? (\n        <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"time-warning\">\n          This meeting will end in {live.minutesLeft} {live.minutesLeft === 1 ? \"minute\" : \"minutes\"}.\n        </p>\n      ) : null}\n      {notice !== null && notice.kind !== \"removed\" ? (\n        // A host's request (\"the host is asking you to unmute\"), not an error:\n        // an assertive status, so it is announced at once without being filed\n        // as a failure (design-system error-box census).\n        <div className=\"mx-meet__notice-bar\" role=\"status\" aria-live=\"assertive\">\n          <span>{notice.text}</span>\n          {notice.kind === \"ask-unmute\" && room.local?.micEnabled !== true ? (\n            <button\n              type=\"button\"\n              className=\"mx-meet__primary mx-meet__primary--small\"\n              onClick={() => {\n                dismiss();\n                void room.toggleMicrophone();\n              }}\n            >\n              Unmute\n            </button>\n          ) : null}\n          <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Dismiss\" onClick={dismiss}>\n            <XIcon strokeWidth={1.75} width={14} height={14} />\n          </button>\n        </div>\n      ) : null}\n    </>\n  );\n}\n\n/** Every shortcut, on one sheet. Opened by Shift+? or from More options. */\nexport function ShortcutsSheet({ onClose }: { onClose: () => void }): ReactNode {\n  useEffect(() => {\n    const onKey = (event: KeyboardEvent) => {\n      if (event.key === \"Escape\") onClose();\n    };\n    window.addEventListener(\"keydown\", onKey);\n    return () => window.removeEventListener(\"keydown\", onKey);\n  }, [onClose]);\n  return (\n    <div className=\"mx-meet__sheet-backdrop\" onClick={onClose}>\n      <div\n        className=\"mx-meet__sheet\"\n        role=\"dialog\"\n        aria-label=\"Keyboard shortcuts\"\n        onClick={(event) => event.stopPropagation()}\n      >\n        <header className=\"mx-meet__panel-head\">\n          <h2 className=\"mx-meet__panel-title\">Keyboard shortcuts</h2>\n          <ControlButton label=\"Close\" onClick={onClose}>\n            <XIcon strokeWidth={1.75} width={16} height={16} />\n          </ControlButton>\n        </header>\n        <dl className=\"mx-meet__shortcuts\">\n          {MEET_SHORTCUTS.map((shortcut) => (\n            <div key={shortcut.id} className=\"mx-meet__shortcut\">\n              <dt>{shortcut.label}</dt>\n              <dd>\n                <kbd className=\"mx-meet__kbd\">{shortcut.keys}</kbd>\n              </dd>\n            </div>\n          ))}\n        </dl>\n      </div>\n    </div>\n  );\n}\n\n/**\n * The assistant control. It appears for every meeting whose AI is on, because\n * as of 0.3.0 the capability is the SERVER's: there is no host config that\n * could leave it unfilled, and a meeting with no Holder bound gets the server's\n * sentence in the panel rather than a control that never appears. A meeting\n * with `ai_enabled = false` gets NO control at all — absent, not disabled.\n */\nfunction AiControl({ active, onToggle }: { active: boolean; onToggle: () => void }): ReactNode {\n  const snapshot = useMeetSnapshot();\n  const meeting = snapshot?.meeting ?? null;\n  if (meeting === null || !meeting.aiEnabled) return null;\n  return (\n    <ControlButton label=\"Meeting assistant\" active={active} onClick={onToggle}>\n      <SparklesIcon width={20} height={20} strokeWidth={1.75} />\n    </ControlButton>\n  );\n}\n\n/* ----------------------------------------------------------------- panels */\n\nexport function PanelShell({\n  title,\n  onClose,\n  children,\n}: {\n  title: string;\n  onClose: () => void;\n  children: ReactNode;\n}): ReactNode {\n  // 🚨 A SIDE PANEL NEVER COVERS THE HEADER (verifier, 2026-09-29: People and\n  // Chat hid End and Invite). The panel is positioned against the room root, so\n  // it starts where the room's header ENDS — measured, because the header's\n  // height is the host's (its controls, a wrapped title, the safe area).\n  const ref = useRef<HTMLElement | null>(null);\n  useLayoutEffect(() => {\n    const panel = ref.current;\n    const root = panel?.closest(\".mx-meet\");\n    const header = root?.querySelector<HTMLElement>(\":scope > .mx-meet__header\") ?? null;\n    if (!panel || !header) return undefined;\n    const place = () => panel.style.setProperty(\"--mx-meet-panel-top\", `${header.offsetHeight}px`);\n    place();\n    if (typeof ResizeObserver === \"undefined\") return undefined;\n    const observer = new ResizeObserver(place);\n    observer.observe(header);\n    return () => observer.disconnect();\n  }, []);\n  return (\n    <aside ref={ref} className=\"mx-meet__panel\" aria-label={title}>\n      <header className=\"mx-meet__panel-head\">\n        <h2 className=\"mx-meet__panel-title\">{title}</h2>\n        <ControlButton label=\"Close panel\" onClick={onClose}>\n          <XIcon strokeWidth={1.75} width={16} height={16} />\n        </ControlButton>\n      </header>\n      <div className=\"mx-meet__panel-body\">{children}</div>\n    </aside>\n  );\n}\n\n/**\n * IN-MEETING CHAT (Meet wave 2). A message to everyone is SAVED with the\n * meeting — a late joiner scrolls up and reads it, and it is part of the record.\n * A private message goes to one person only and is never saved; the composer\n * says which of the two you are about to send.\n */\nexport function ChatPanel({\n  onClose,\n  to = null,\n  onTo,\n}: {\n  onClose: () => void;\n  to?: ParticipantIdentity | null;\n  onTo?: (identity: ParticipantIdentity | null) => void;\n}): ReactNode {\n  const snapshot = useMeetSnapshot();\n  const room = useRoom();\n  const live = useLivePolicy();\n  const host = useMeetHost();\n  // The composer waits for ONE fresh read of the meeting's rules, so a host's change a moment ago\n  // is never missed by a box that was drawn from an older answer.\n  const [rulesChecked, setRulesChecked] = useState(false);\n  useEffect(() => {\n    let alive = true;\n    const done = () => alive && setRulesChecked(true);\n    if (host === null) done();\n    else void host.meetings.readLivePolicy().then(done, done);\n    return () => {\n      alive = false;\n    };\n  }, [host]);\n  const [draft, setDraft] = useState(\"\");\n  const [recipient, setRecipient] = useState<ParticipantIdentity | null>(to);\n  const listRef = useRef<HTMLUListElement | null>(null);\n  const messages = snapshot?.chat ?? [];\n  const local = snapshot?.localIdentity ?? null;\n  const people = (snapshot?.participants ?? []).filter(\n    (participant) => !participant.isLocal && !participant.isAgent,\n  );\n  const recipientName =\n    recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;\n\n  useEffect(() => setRecipient(to), [to]);\n  useEffect(() => {\n    const list = listRef.current;\n    if (list !== null) list.scrollTop = list.scrollHeight;\n  }, [messages.length]);\n\n  const choose = (next: ParticipantIdentity | null) => {\n    setRecipient(next);\n    onTo?.(next);\n  };\n\n  return (\n    <PanelShell title=\"Chat\" onClose={onClose}>\n      <ul className=\"mx-meet__chat\" ref={listRef}>\n        {snapshot?.chatHistoryError != null ? (\n          <li className=\"mx-meet__panel-note\">{snapshot.chatHistoryError}</li>\n        ) : null}\n        {snapshot?.chatLoaded !== true && messages.length === 0 ? (\n          <li className=\"mx-meet__panel-note\">Reading earlier messages…</li>\n        ) : messages.length === 0 && snapshot?.chatHistoryError == null ? (\n          <li className=\"mx-meet__panel-note\">\n            No messages yet. Messages to everyone stay with the meeting, so people who join later\n            see them.\n          </li>\n        ) : null}\n        {messages.map((message) => (\n          <ChatLine key={message.id} message={message} local={local} people={people} />\n        ))}\n      </ul>\n      {!rulesChecked ? null : !live.canChat ? (\n        <p className=\"mx-meet__panel-note\" role=\"status\" data-meet-notice=\"chat-restricted\">\n          {live.chatMode === \"off\"\n            ? \"Chat is turned off for this meeting.\"\n            : \"Chat is limited to the host and co-hosts in this meeting.\"}\n        </p>\n      ) : (\n      <form\n        className=\"mx-meet__composer mx-meet__composer--chat\"\n        onSubmit={(event) => {\n          event.preventDefault();\n          const text = draft;\n          if (text.trim().length === 0) return;\n          setDraft(\"\");\n          if (recipient === null) void room.sendChat(text).catch(() => undefined);\n          else void room.sendPrivateChat(recipient, text);\n        }}\n      >\n        {people.length > 0 ? (\n          <ControlSelect\n            aria-label=\"Send to\"\n            value={recipient ?? \"\"}\n            onValueChange={(next) => choose(next === \"\" ? null : (next as ParticipantIdentity))}\n            options={[\n              { value: \"\", label: \"Everyone\" },\n              ...people.map((participant) => ({\n                value: participant.identity as string,\n                label: `${participant.displayName} (private)`,\n              })),\n            ]}\n          />\n        ) : null}\n        <div className=\"mx-meet__composer-row\">\n          <input\n            className=\"mx-meet__input\"\n            value={draft}\n            onChange={(event) => setDraft(event.target.value)}\n            placeholder={recipientName === null ? \"Message everyone\" : `Message ${recipientName} privately`}\n            aria-label={recipientName === null ? \"Message everyone\" : `Message ${recipientName} privately`}\n            maxLength={4000}\n          />\n          <button type=\"submit\" className=\"mx-meet__send\" disabled={draft.trim().length === 0}>\n            Send\n          </button>\n        </div>\n        {recipientName !== null ? (\n          <p className=\"mx-meet__panel-note\">Only {recipientName} sees this. Private messages are not saved.</p>\n        ) : null}\n      </form>\n      )}\n    </PanelShell>\n  );\n}\n\nfunction ChatLine({\n  message,\n  local,\n  people,\n}: {\n  message: RoomChatMessage;\n  local: ParticipantIdentity | null;\n  people: readonly MeetParticipant[];\n}): ReactNode {\n  const mine = message.identity === local;\n  const privateTo = message.to ?? null;\n  const counterpart =\n    privateTo === null\n      ? null\n      : mine\n        ? people.find((p) => p.identity === privateTo)?.displayName ?? \"them\"\n        : \"you\";\n  return (\n    <li\n      className={[\n        \"mx-meet__chat-line\",\n        privateTo !== null ? \"mx-meet__chat-line--private\" : \"\",\n        message.failed !== undefined ? \"mx-meet__chat-line--failed\" : \"\",\n      ]\n        .filter(Boolean)\n        .join(\" \")}\n    >\n      <span className=\"mx-meet__chat-meta\">\n        <strong>{mine ? \"You\" : message.displayName}</strong>\n        {counterpart !== null ? <span className=\"mx-meet__chat-private\">to {counterpart} · private</span> : null}\n        <time dateTime={message.at}>{clockOf(message.at)}</time>\n      </span>\n      <span className=\"mx-meet__chat-text\">{message.text}</span>\n      {message.failed !== undefined ? (\n        <span className=\"mx-meet__chat-failed\">{message.failed}</span>\n      ) : privateTo === null && message.saved === false ? (\n        <span className=\"mx-meet__chat-pending\">\n          {message.id.startsWith(\"pending-\") ? \"Sending…\" : \"Not saved — people who join later will not see this\"}\n        </span>\n      ) : null}\n    </li>\n  );\n}\n\nexport function PeoplePanel({\n  onClose,\n  onMessage,\n}: {\n  onClose: () => void;\n  onMessage?: (identity: ParticipantIdentity) => void;\n}): ReactNode {\n  const snapshot = useMeetSnapshot();\n  const controls = useHostControls();\n  const queue = useHandQueue();\n  const [query, setQuery] = useState(\"\");\n  const [menuFor, setMenuFor] = useState<ParticipantIdentity | null>(null);\n  // THE LOCAL ROW IS BADGED FROM THE EFFECTIVE ROLE (MRI-A11).\n  const myRole = useRole();\n  const local = snapshot?.localIdentity ?? null;\n  // MD-16: observers are listed — to everyone by default; to the hosts only when the\n  // organization's `meet.observers_visible_to` knob says so (the server sends it).\n  const observersHidden = snapshot?.grants.observersVisibleTo === \"hosts\" && !controls.isHost;\n  const everyone = (snapshot?.participants ?? []).filter(\n    (participant) =>\n      !observersHidden || !isObserverRole(participant.role) || participant.identity === local,\n  );\n  const needle = query.trim().toLowerCase();\n  const shown =\n    needle.length === 0\n      ? everyone\n      : everyone.filter((participant) => participant.displayName.toLowerCase().includes(needle));\n\n  return (\n    <PanelShell title={`People (${everyone.length})`} onClose={onClose}>\n      <LobbyPanel />\n\n      {queue.length > 0 ? (\n        <section className=\"mx-meet__section\" aria-label=\"Raised hands\">\n          <header className=\"mx-meet__section-head\">\n            <h3 className=\"mx-meet__section-title\">Raised hands · {queue.length}</h3>\n            {controls.isHost ? (\n              <button\n                type=\"button\"\n                className=\"mx-meet__link\"\n                onClick={() => void controls.run({ action: \"lower_all_hands\" })}\n              >\n                Lower all\n              </button>\n            ) : null}\n          </header>\n          <ol className=\"mx-meet__queue\">\n            {queue.map((participant) => (\n              <li key={participant.identity} className=\"mx-meet__person\">\n                <MeetAvatar name={participant.displayName} url={participant.avatarUrl} size={28} />\n                <span className=\"mx-meet__person-name\">\n                  {participant.displayName}\n                  {participant.identity === local ? <span className=\"mx-meet__you\"> (you)</span> : null}\n                </span>\n                {controls.isHost || participant.identity === local ? (\n                  <button\n                    type=\"button\"\n                    className=\"mx-meet__link\"\n                    onClick={() =>\n                      void controls.run({ action: \"lower_hand\", identity: participant.identity })\n                    }\n                  >\n                    Lower\n                  </button>\n                ) : null}\n              </li>\n            ))}\n          </ol>\n        </section>\n      ) : null}\n\n      {controls.isHost && everyone.length > 1 ? (\n        <div className=\"mx-meet__bulk\">\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void controls.run({ action: \"mute_all\" })}>\n            <MicOffIcon width={14} height={14} /> Mute all\n          </button>\n          <button\n            type=\"button\"\n            className=\"mx-meet__chip\"\n            onClick={() => void controls.run({ action: \"ask_all_unmute\" })}\n          >\n            <MicIcon width={14} height={14} /> Ask all to unmute\n          </button>\n        </div>\n      ) : null}\n\n      {everyone.length > 4 ? (\n        <label className=\"mx-meet__search\">\n          <SearchIcon strokeWidth={1.75} width={16} height={16} />\n          <input\n            className=\"mx-meet__input mx-meet__input--bare\"\n            value={query}\n            onChange={(event) => setQuery(event.target.value)}\n            placeholder=\"Search people\"\n            aria-label=\"Search people\"\n          />\n        </label>\n      ) : null}\n\n      {controls.notice !== null ? (\n        <p className={controls.notice.failed ? \"mx-meet__error\" : \"mx-meet__notice\"} role=\"status\">\n          {controls.notice.text}\n        </p>\n      ) : null}\n\n      <ul className=\"mx-meet__people\">\n        {shown.map((participant) => (\n          <li key={participant.identity} className=\"mx-meet__person\">\n            <MeetAvatar name={participant.displayName} url={participant.avatarUrl} size={32} />\n            <span className=\"mx-meet__person-name\">\n              {participant.displayName}\n              {participant.identity === local ? <span className=\"mx-meet__you\"> (you)</span> : null}\n              <RoleBadge\n                role={participant.identity === local ? myRole : participant.role}\n                standing={participant.standing}\n              />\n              {isNoteTaker(participant) ? (\n                <span className=\"mx-meet__badge\">Meeting assistant</span>\n              ) : null}\n              {snapshot?.spotlight === participant.identity ? (\n                <span className=\"mx-meet__badge\">Spotlight</span>\n              ) : null}\n              {snapshot?.presenter === participant.identity ? (\n                <span className=\"mx-meet__badge\" data-meet-presenting=\"true\">Presenting</span>\n              ) : null}\n            </span>\n            {participant.handRaised ? <HandIcon width={14} height={14} /> : null}\n            {!participant.micEnabled && !isNoteTaker(participant) ? (\n              <MicOffIcon width={14} height={14} />\n            ) : null}\n            <QualityBars quality={participant.quality} />\n            <span className=\"mx-meet__anchor\">\n              <ControlButton\n                label={`More for ${participant.displayName}`}\n                active={menuFor === participant.identity}\n                onClick={() => setMenuFor(menuFor === participant.identity ? null : participant.identity)}\n              >\n                <MoreHorizontalIcon strokeWidth={1.75} width={16} height={16} />\n              </ControlButton>\n              {menuFor === participant.identity ? (\n                <PersonMenu\n                  participant={participant}\n                  placement=\"down\"\n                  onClose={() => setMenuFor(null)}\n                  {...(onMessage !== undefined ? { onMessage } : {})}\n                />\n              ) : null}\n            </span>\n          </li>\n        ))}\n        {shown.length === 0 ? <li className=\"mx-meet__panel-note\">Nobody matches “{query}”.</li> : null}\n      </ul>\n\n      {/* MRF-1: a host decides what the guests in this list will be able to read\n          afterwards, WHILE the meeting is running — which is when they know. */}\n      {snapshot?.meeting !== null && snapshot?.meeting !== undefined ? (\n        <GuestRecordAccessControl meeting={snapshot.meeting} />\n      ) : null}\n    </PanelShell>\n  );\n}\n\n/**\n * EVERYTHING YOU CAN DO ABOUT ONE PERSON (Meet wave 2), in one menu — on their\n * tile and on their People row. An item appears only when it would be honored:\n * the rank ladder decides moderation (a co-host never sees \"Remove\" on the host),\n * only the host sees \"Make host\", and nobody sees a control that the server\n * would refuse. Removing someone and handing the meeting over NAME THEIR\n * CONSEQUENCE first, inline — never a browser dialog.\n */\nexport function PersonMenu({\n  participant,\n  onClose,\n  onMessage,\n  placement = \"down\",\n}: {\n  participant: MeetParticipant;\n  onClose: () => void;\n  onMessage?: (identity: ParticipantIdentity) => void;\n  placement?: \"up\" | \"down\";\n}): ReactNode {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const controls = useHostControls();\n  const [mode, setMode] = useState<\"menu\" | \"rename\" | \"report\" | \"remove\" | \"transfer\">(\"menu\");\n  const [text, setText] = useState(\"\");\n  const self = participant.identity === snapshot?.localIdentity;\n  const moderate = controls.canModerate(participant);\n  const pinned = snapshot?.pinned === participant.identity;\n  const spotlit = snapshot?.spotlight === participant.identity;\n  const hasAccount = participant.userId !== null;\n  // A refused act keeps its pane open WITH the server's sentence and live\n  // buttons — never a confirm that silently stays up (verifier, 2026-09-27).\n  const [refused, setRefused] = useState(false);\n  const act = (request: Parameters<UseHostControlsResult[\"run\"]>[0]) => {\n    setRefused(false);\n    void controls.run(request).then((result) => {\n      if (result !== null) onClose();\n      else setRefused(true);\n    });\n  };\n  const refusal =\n    refused && controls.notice?.failed === true ? (\n      <ErrorBox as=\"p\" className=\"mx-meet__error\" message={controls.notice.text} operation=\"Change this participant\" origin=\"meet/components\">\n        {controls.notice.text}\n      </ErrorBox>\n    ) : null;\n\n  if (mode === \"rename\" || mode === \"report\") {\n    const renaming = mode === \"rename\";\n    return (\n      <Popover label={renaming ? \"Rename\" : \"Report\"} onClose={onClose} placement={placement}>\n        <form\n          className=\"mx-meet__menu-form\"\n          onSubmit={(event) => {\n            event.preventDefault();\n            if (text.trim().length === 0) return;\n            act(\n              renaming\n                ? { action: \"rename\", identity: participant.identity, name: text.trim() }\n                : { action: \"report\", identity: participant.identity, reason: text.trim() },\n            );\n          }}\n        >\n          <label className=\"mx-meet__field\">\n            <span className=\"mx-meet__field-label\">\n              {renaming ? \"Name shown in this meeting\" : `What did ${participant.displayName} do?`}\n            </span>\n            {renaming ? (\n              <input\n                className=\"mx-meet__input\"\n                autoFocus\n                maxLength={80}\n                value={text}\n                onChange={(event) => setText(event.target.value)}\n              />\n            ) : (\n              <textarea\n                className=\"mx-meet__input\"\n                autoFocus\n                rows={3}\n                maxLength={1000}\n                value={text}\n                onChange={(event) => setText(event.target.value)}\n              />\n            )}\n          </label>\n          {refusal}\n          <div className=\"mx-meet__menu-actions\">\n            <button type=\"button\" className=\"mx-meet__link\" onClick={() => setMode(\"menu\")}>\n              Back\n            </button>\n            <button type=\"submit\" className=\"mx-meet__send\" disabled={text.trim().length === 0 || controls.busy}>\n              {renaming ? \"Rename\" : \"Report\"}\n            </button>\n          </div>\n        </form>\n      </Popover>\n    );\n  }\n\n  if (mode === \"remove\" || mode === \"transfer\") {\n    const removing = mode === \"remove\";\n    return (\n      <Popover label={removing ? \"Remove\" : \"Make host\"} onClose={onClose} placement={placement}>\n        <div className=\"mx-meet__menu-form\">\n          <p className=\"mx-meet__confirm-text\">\n            {removing\n              ? `Remove ${participant.displayName}? They leave immediately and cannot rejoin this meeting.`\n              : `Make ${participant.displayName} the host? They get every host control and own this meeting. You stay on as a co-host.`}\n          </p>\n          {refusal}\n          <div className=\"mx-meet__menu-actions\">\n            <button type=\"button\" className=\"mx-meet__link\" onClick={() => setMode(\"menu\")}>\n              Cancel\n            </button>\n            <button\n              type=\"button\"\n              className={removing ? \"mx-meet__send mx-meet__send--danger\" : \"mx-meet__send\"}\n              disabled={controls.busy}\n              onClick={() =>\n                act({ action: removing ? \"remove\" : \"transfer_host\", identity: participant.identity })\n              }\n            >\n              {removing ? \"Remove\" : \"Make host\"}\n            </button>\n          </div>\n        </div>\n      </Popover>\n    );\n  }\n\n  return (\n    <Popover label={`Options for ${participant.displayName}`} onClose={onClose} placement={placement}>\n      <div className=\"mx-meet__menu\" role=\"menu\">\n        <MenuItem\n          onSelect={() => {\n            host?.engine.pin(pinned ? null : participant.identity);\n            onClose();\n          }}\n        >\n          <PinIcon strokeWidth={1.75} width={16} height={16} /> {pinned ? \"Unpin\" : \"Pin for me\"}\n        </MenuItem>\n        {!self && !participant.isAgent && (onMessage !== undefined || host !== null) ? (\n          <MenuItem\n            onSelect={() => {\n              if (onMessage !== undefined) onMessage(participant.identity);\n              else\n                host?.store.patch({\n                  privateChatRequest: { to: participant.identity, at: Date.now() },\n                });\n              onClose();\n            }}\n          >\n            <ChatIcon width={16} height={16} /> Message privately\n          </MenuItem>\n        ) : null}\n        {controls.isHost ? (\n          <MenuItem onSelect={() => act({ action: \"spotlight\", identity: spotlit ? null : participant.identity })}>\n            <SpotlightIcon width={16} height={16} /> {spotlit ? \"Remove spotlight\" : \"Spotlight for everyone\"}\n          </MenuItem>\n        ) : null}\n        {moderate ? (\n          <>\n            <div className=\"mx-meet__menu-sep\" role=\"separator\" />\n            {participant.micEnabled ? (\n              <MenuItem onSelect={() => act({ action: \"mute\", identity: participant.identity })}>\n                <MicOffIcon width={16} height={16} /> Mute\n              </MenuItem>\n            ) : !participant.isAgent ? (\n              <MenuItem onSelect={() => act({ action: \"ask_unmute\", identity: participant.identity })}>\n                <MicIcon width={16} height={16} /> Ask to unmute\n              </MenuItem>\n            ) : null}\n            {participant.cameraEnabled ? (\n              <MenuItem onSelect={() => act({ action: \"stop_video\", identity: participant.identity })}>\n                <CameraOffIcon width={16} height={16} /> Stop video\n              </MenuItem>\n            ) : null}\n            {participant.screenSharing ? (\n              <MenuItem onSelect={() => act({ action: \"stop_screen\", identity: participant.identity })}>\n                <ScreenShareIcon width={16} height={16} /> Stop screen share\n              </MenuItem>\n            ) : null}\n            {participant.handRaised ? (\n              <MenuItem onSelect={() => act({ action: \"lower_hand\", identity: participant.identity })}>\n                <HandIcon width={16} height={16} /> Lower hand\n              </MenuItem>\n            ) : null}\n            {hasAccount && !participant.isAgent && participant.role !== \"cohost\" ? (\n              <MenuItem onSelect={() => act({ action: \"make_cohost\", identity: participant.identity })}>\n                <PeopleIcon width={16} height={16} /> Make co-host\n              </MenuItem>\n            ) : null}\n            {!participant.isAgent && participant.role !== \"cohost\" && participant.role !== \"host\" ? (\n              participant.role === \"presenter\" ? (\n                <MenuItem onSelect={() => act({ action: \"revoke_presenter\", identity: participant.identity })}>\n                  <ScreenShareIcon width={16} height={16} /> Remove presenter\n                </MenuItem>\n              ) : (\n                <MenuItem onSelect={() => act({ action: \"make_presenter\", identity: participant.identity })}>\n                  <ScreenShareIcon width={16} height={16} /> Make presenter\n                </MenuItem>\n              )\n            ) : null}\n            {!participant.isAgent ? (\n              <MenuItem\n                onSelect={() => {\n                  setText(participant.displayName);\n                  setMode(\"rename\");\n                }}\n              >\n                <PencilIcon strokeWidth={1.75} width={16} height={16} /> Rename\n              </MenuItem>\n            ) : null}\n          </>\n        ) : null}\n        {controls.isOwner && participant.role === \"cohost\" ? (\n          <MenuItem onSelect={() => act({ action: \"revoke_cohost\", identity: participant.identity })}>\n            <PeopleIcon width={16} height={16} /> Remove co-host\n          </MenuItem>\n        ) : null}\n        {controls.isOwner && !self && hasAccount && !participant.isAgent ? (\n          <MenuItem onSelect={() => setMode(\"transfer\")}>\n            <SpotlightIcon width={16} height={16} /> Make host\n          </MenuItem>\n        ) : null}\n        {self ? (\n          <MenuItem\n            onSelect={() => {\n              setText(participant.displayName);\n              setMode(\"rename\");\n            }}\n          >\n            <PencilIcon strokeWidth={1.75} width={16} height={16} /> Rename yourself\n          </MenuItem>\n        ) : null}\n        {!self && !participant.isAgent ? (\n          <MenuItem\n            onSelect={() => {\n              setText(\"\");\n              setMode(\"report\");\n            }}\n          >\n            <FlagIcon width={16} height={16} /> Report\n          </MenuItem>\n        ) : null}\n        {moderate && !participant.isAgent ? (\n          <MenuItem danger onSelect={() => setMode(\"remove\")}>\n            <XIcon strokeWidth={1.75} width={16} height={16} /> Remove from meeting\n          </MenuItem>\n        ) : null}\n      </div>\n    </Popover>\n  );\n}\n\n/* --------------------------------------------------------------- settings */\n\n/**\n * AUDIO, VIDEO AND EFFECTS (Meet wave 2) — the devices in use, a live\n * microphone level, a speaker test, noise suppression and the camera\n * background. Every change applies to the live meeting at once and is\n * remembered in this browser.\n */\nexport function SettingsPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const host = useRequiredMeetHost();\n  return (\n    <PanelShell title=\"Settings\" onClose={onClose}>\n      <DeviceSettings\n        onPick={(kind, deviceId) => {\n          host.devices.select(kind, deviceId);\n          void host.engine.switchDevice(kind, deviceId);\n        }}\n      />\n      <EffectsSettings />\n      <CaptionLanguageSettings />\n    </PanelShell>\n  );\n}\n\n/** Microphone (with a live level), speaker (with a test), camera. */\nfunction DeviceSettings({\n  onPick,\n}: {\n  onPick: (kind: \"audioinput\" | \"videoinput\" | \"audiooutput\", deviceId: string) => void;\n}): ReactNode {\n  const host = useRequiredMeetHost();\n  const devices = useDeviceSnapshot();\n  const microphone = devices?.selected.audioinput ?? host.devices.resolve(\"audioinput\");\n  const speaker = devices?.selected.audiooutput ?? host.devices.resolve(\"audiooutput\");\n  const stream = useMicrophoneStream(microphone);\n  const level = useAudioLevel(stream);\n  const [testing, setTesting] = useState(false);\n\n  useEffect(() => {\n    void host.devices.refresh();\n  }, [host]);\n\n  return (\n    <section className=\"mx-meet__section\" aria-label=\"Devices\">\n      <DevicePicker kind=\"audioinput\" label=\"Microphone\" onPick={onPick} />\n      <div className=\"mx-meet__meter\" role=\"meter\" aria-label=\"Microphone level\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(level * 100)}>\n        <span style={{ width: `${Math.min(100, Math.round(level * 160))}%` }} />\n      </div>\n      <DevicePicker kind=\"audiooutput\" label=\"Speaker\" onPick={onPick} />\n      <button\n        type=\"button\"\n        className=\"mx-meet__chip\"\n        disabled={testing}\n        onClick={() => {\n          setTesting(true);\n          void playTestSound(speaker).finally(() => setTesting(false));\n        }}\n      >\n        <SpeakerIcon width={14} height={14} /> {testing ? \"Playing…\" : \"Test speaker\"}\n      </button>\n      <DevicePicker kind=\"videoinput\" label=\"Camera\" onPick={onPick} />\n    </section>\n  );\n}\n\n/** Noise suppression and the camera background. */\nfunction EffectsSettings({ preview }: { preview?: CameraPreview | null }): ReactNode {\n  const effects = useMediaEffects();\n  const [error, setError] = useState<string | null>(null);\n  const fileRef = useRef<HTMLInputElement | null>(null);\n  // Pre-join there is no room driver yet, so the browser itself is asked.\n  const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();\n\n  const apply = (next: Partial<MediaEffects>) => {\n    setError(null);\n    void effects.set(next);\n    if (preview != null) {\n      const merged = { ...effects.effects, ...next };\n      void preview.setEffect(toVideoEffect(merged)).catch(() =>\n        setError(\"This browser could not run the background effect.\"),\n      );\n    }\n  };\n\n  return (\n    <section className=\"mx-meet__section\" aria-label=\"Effects\">\n      {/* Design-system controls, never native ones restyled here: the lobby\n          and settings must read as the same app as every other page. */}\n      <div className=\"mx-meet__check\">\n        <Checkbox\n          id=\"mx-meet-noise\"\n          checked={effects.effects.noiseSuppression}\n          onCheckedChange={(checked) => apply({ noiseSuppression: checked === true })}\n        />\n        <div className=\"mx-meet__check-text\">\n          <Label htmlFor=\"mx-meet-noise\">Noise suppression</Label>\n          <span className=\"mx-meet__hint\">Filters keyboards, fans and background chatter.</span>\n        </div>\n      </div>\n      {supported ? (\n        <div className=\"mx-meet__field\">\n          <Label>Background</Label>\n          <SegmentedControl\n            fullWidth\n            value={effects.effects.background}\n            onValueChange={(kind) => {\n              if (kind === \"image\") {\n                fileRef.current?.click();\n                return;\n              }\n              apply({ background: kind as MediaEffects[\"background\"] });\n            }}\n            data={[\n              { value: \"none\", label: \"None\" },\n              { value: \"blur\", label: \"Blur\" },\n              { value: \"image\", label: \"Picture…\" },\n            ]}\n          />\n          <input\n            ref={fileRef}\n            type=\"file\"\n            accept=\"image/*\"\n            hidden\n            onChange={(event) => {\n              const file = event.target.files?.[0];\n              event.target.value = \"\";\n              if (file === undefined) return;\n              void shrinkImage(file)\n                .then((url) => apply({ background: \"image\", backgroundImage: url }))\n                .catch(() => setError(\"That picture could not be read. Try a JPEG or PNG.\"));\n            }}\n          />\n          {error !== null ? <p className=\"mx-meet__error\">{error}</p> : null}\n        </div>\n      ) : null}\n    </section>\n  );\n}\n\nfunction toVideoEffect(effects: MediaEffects): VideoEffect {\n  if (effects.background === \"blur\") return { kind: \"blur\" };\n  if (effects.background === \"image\" && effects.backgroundImage !== null) {\n    return { kind: \"image\", imageUrl: effects.backgroundImage };\n  }\n  return { kind: \"none\" };\n}\n\n/**\n * A picked background, scaled to 1280 px wide as a JPEG data URL — small enough\n * to remember in this browser (a `blob:` URL dies with the tab), large enough\n * for a 720p camera.\n */\nasync function shrinkImage(file: File): Promise<string> {\n  const url = URL.createObjectURL(file);\n  try {\n    const image = new Image();\n    image.src = url;\n    await image.decode();\n    const scale = Math.min(1, 1280 / image.naturalWidth);\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = Math.round(image.naturalWidth * scale);\n    canvas.height = Math.round(image.naturalHeight * scale);\n    const context = canvas.getContext(\"2d\");\n    if (context === null) throw new Error(\"no 2d context\");\n    context.drawImage(image, 0, 0, canvas.width, canvas.height);\n    return canvas.toDataURL(\"image/jpeg\", 0.85);\n  } finally {\n    URL.revokeObjectURL(url);\n  }\n}\n\n/** A short two-tone chime through the chosen speaker. */\nasync function playTestSound(sinkId: string | null): Promise<void> {\n  const Context = (globalThis as { AudioContext?: typeof AudioContext }).AudioContext;\n  if (Context === undefined) return;\n  const context = new Context();\n  const destination = context.createMediaStreamDestination();\n  const gain = context.createGain();\n  gain.gain.value = 0.2;\n  gain.connect(destination);\n  for (const [frequency, start] of [\n    [660, 0],\n    [880, 0.25],\n  ] as const) {\n    const oscillator = context.createOscillator();\n    oscillator.frequency.value = frequency;\n    oscillator.connect(gain);\n    oscillator.start(context.currentTime + start);\n    oscillator.stop(context.currentTime + start + 0.22);\n  }\n  const audio = new Audio();\n  audio.srcObject = destination.stream;\n  const sinkable = audio as HTMLAudioElement & { setSinkId?: (id: string) => Promise<void> };\n  if (sinkId !== null && sinkId !== \"default\" && sinkable.setSinkId !== undefined) {\n    await sinkable.setSinkId(sinkId).catch(() => undefined);\n  }\n  await audio.play().catch(() => undefined);\n  await new Promise((resolve) => setTimeout(resolve, 700));\n  audio.pause();\n  await context.close();\n}\n\n/** A microphone stream for the level meter only — closed with the component. */\nfunction useMicrophoneStream(\n  deviceId: string | null | \"off\",\n  report?: (outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }) => void,\n  attempt = 0,\n): MediaStream | null {\n  const [stream, setStream] = useState<MediaStream | null>(null);\n  const reportRef = useRef(report);\n  reportRef.current = report;\n  useEffect(() => {\n    if (deviceId === \"off\") {\n      reportRef.current?.(\"off\");\n      return undefined;\n    }\n    let live = true;\n    let opened: MediaStream | null = null;\n    const media = (globalThis as { navigator?: Navigator }).navigator?.mediaDevices;\n    if (media === undefined) return undefined;\n    reportRef.current?.(\"prompting\");\n    void media\n      .getUserMedia({ audio: deviceId === null ? true : { deviceId: { exact: deviceId } } })\n      .then((next) => {\n        if (!live) {\n          next.getTracks().forEach((track) => track.stop());\n          return;\n        }\n        opened = next;\n        setStream(next);\n        reportRef.current?.(\"on\");\n      })\n      .catch((thrown: unknown) => {\n        setStream(null);\n        // A stale device id is not a missing microphone: the meeting's own join retries the default.\n        if (live) reportRef.current?.({ error: thrown });\n      });\n    return () => {\n      live = false;\n      opened?.getTracks().forEach((track) => track.stop());\n      setStream(null);\n    };\n  }, [deviceId, attempt]);\n  return stream;\n}\n\n/**\n * THE PRE-JOIN DEVICE CHECK, said plainly (P1 `perm-prompt-pending`, `perm-blocked-site`,\n * `device-none-found`, `device-busy`): while the browser is asking, what it is asking; when a\n * device is refused, why, the steps for THIS browser, and one Try again. Join is never blocked.\n */\nfunction PreviewStatus({ onRetry }: { onRetry: () => void }): ReactNode {\n  const { region, where } = useMediaSupervisor();\n  const [waited, setWaited] = useState(false);\n  const prompting = region.preview.microphone.state === \"prompting\" || region.preview.camera.state === \"prompting\";\n  useEffect(() => {\n    if (!prompting) {\n      setWaited(false);\n      return undefined;\n    }\n    // A browser that answers at once never flashes the explainer.\n    const timer = setTimeout(() => setWaited(true), 800);\n    return () => clearTimeout(timer);\n  }, [prompting]);\n  const refused = ([\"microphone\", \"camera\"] as const).flatMap((kind) => {\n    const preview = region.preview[kind];\n    const reason = region.permission[kind] === \"denied\"\n      ? \"denied\"\n      : preview.state === \"unavailable\" ? (preview.unavailable?.reason ?? \"failed\") : null;\n    return reason === null ? [] : [{ kind, reason }];\n  });\n  if (refused.length === 0) {\n    if (!prompting || !waited) return null;\n    return (\n      <p className=\"mx-meet__panel-note\" role=\"status\" data-meet-notice=\"permission-prompt\">\n        Allow camera and microphone when your browser asks\n      </p>\n    );\n  }\n  const first = refused[0]!;\n  const both = refused.length === 2 && refused[0]!.reason === refused[1]!.reason;\n  const label = both\n    ? deviceChipLabel(\"camera\", first.reason).replace(/^Camera/, \"Camera and mic\")\n    : refused.map((r) => deviceChipLabel(r.kind, r.reason)).join(\" · \");\n  return (\n    <div className=\"mx-meet__warning\" role=\"status\" data-meet-notice={deviceNoticeCode(first.kind, first.reason)}>\n      <strong>{label}</strong>\n      <ol className=\"mx-meet__fix-steps\">\n        {deviceFixSteps(first.kind, first.reason, where).map((step) => (\n          <li key={step}>{step}</li>\n        ))}\n      </ol>\n      <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onRetry}>\n        Try again\n      </Button>\n    </div>\n  );\n}\n\n/**\n * THE HOST IS TOLD WHEN SOMEONE KNOCKS (`wr-host-notified`): a notice naming the person, with\n * Admit and View, within moments of the knock — beside the count on the People button, not instead\n * of it. Absent for anyone who may not admit, and while the People panel (which lists them) is open.\n */\nexport function KnockNotice({ onView }: { onView: () => void }): ReactNode {\n  const { knocker, others, admit, dismiss } = useKnockNotice();\n  if (knocker === null) return null;\n  return (\n    <div className=\"mx-meet__notice-bar\" role=\"status\" data-meet-notice=\"knock-received\" data-meet-participant-name={knocker.displayName}>\n      <span>\n        {knocker.displayName} wants to join{others > 0 ? ` (+${others} more)` : \"\"}\n      </span>\n      <button type=\"button\" className=\"mx-meet__link\" onClick={() => void admit().catch(() => undefined)}>\n        Admit\n      </button>\n      <button\n        type=\"button\"\n        className=\"mx-meet__link\"\n        onClick={() => {\n          dismiss();\n          onView();\n        }}\n      >\n        View\n      </button>\n      <button type=\"button\" className=\"mx-meet__toast-close\" aria-label=\"Dismiss\" onClick={dismiss}>\n        <XIcon strokeWidth={1.75} width={14} height={14} />\n      </button>\n    </div>\n  );\n}\n\n/** The waiting room. Rendered for hosts only — a participant sees nothing. */\nexport function LobbyPanel(): ReactNode {\n  const lobby = useLobby();\n  if (!lobby.canAdmit || (lobby.waiting.length === 0 && lobby.declined.length === 0)) return null;\n  return (\n    <>\n      {lobby.waiting.length > 0 ? <WaitingList lobby={lobby} /> : null}\n      {lobby.declined.length > 0 ? <DeclinedList lobby={lobby} /> : null}\n    </>\n  );\n}\n\n/**\n * THE PEOPLE THE HOST DECLINED, with the one control that lifts it (`meet_undeny`, the door that\n * already exists — no new permission). Under the `until_lifted` rule nothing else lets them knock\n * again; under the others it lets them ask now instead of waiting.\n */\nfunction DeclinedList({ lobby }: { lobby: UseLobbyResult }): ReactNode {\n  return (\n    <section className=\"mx-meet__lobby\" aria-label=\"Declined requests\" data-meet-declined=\"\">\n      <header className=\"mx-meet__lobby-head\">\n        <h3 className=\"mx-meet__lobby-title\">Declined</h3>\n      </header>\n      <ul className=\"mx-meet__lobby-list\">\n        {lobby.declined.map((entry) => (\n          <li\n            key={entry.identity}\n            className=\"mx-meet__lobby-row\"\n            data-meet-declined-entry=\"\"\n            data-meet-participant-name={entry.displayName}\n          >\n            <MeetAvatar name={entry.displayName} url={entry.avatarUrl} size={32} />\n            <span className=\"mx-meet__person-name\">{entry.displayName}</span>\n            <button\n              type=\"button\"\n              className=\"mx-meet__link\"\n              aria-label={`Let ${entry.displayName} ask again`}\n              onClick={() => void lobby.undeny(entry)}\n            >\n              Let them ask again\n            </button>\n          </li>\n        ))}\n      </ul>\n    </section>\n  );\n}\n\nfunction WaitingList({ lobby }: { lobby: UseLobbyResult }): ReactNode {\n  return (\n    <section className=\"mx-meet__lobby\" aria-label=\"Waiting room\">\n      <header className=\"mx-meet__lobby-head\">\n        <h3 className=\"mx-meet__lobby-title\">\n          {lobby.waiting.length === 1\n            ? \"1 person is waiting\"\n            : `${lobby.waiting.length} people are waiting`}\n        </h3>\n        <button type=\"button\" className=\"mx-meet__link\" onClick={() => void lobby.admitAll()}>\n          Admit all\n        </button>\n      </header>\n      <ul className=\"mx-meet__lobby-list\">\n        {lobby.waiting.map((entry) => (\n          <li\n            key={entry.identity}\n            className=\"mx-meet__lobby-row\"\n            data-meet-lobby-entry=\"\"\n            data-meet-participant-name={entry.displayName}\n          >\n            <MeetAvatar name={entry.displayName} url={entry.avatarUrl} size={32} />\n            <span className=\"mx-meet__person-name\">\n              {entry.displayName}\n              {entry.userId === null ? <span className=\"mx-meet__badge\">Guest</span> : null}\n              {entry.flag === \"previously_removed\" ? (\n                // `mod-removed-bypass`: advice for the host, never a block — Admit stays.\n                <span className=\"mx-meet__badge mx-meet__badge--warn\" data-meet-notice=\"knock-flagged\">\n                  Previously removed\n                </span>\n              ) : null}\n            </span>\n            <ControlButton label={`Admit ${entry.displayName}`} onClick={() => void lobby.admit(entry)}>\n              <CheckIcon strokeWidth={1.75} width={16} height={16} />\n            </ControlButton>\n            <ControlButton\n              label={`Deny ${entry.displayName}`}\n              danger\n              onClick={() => void lobby.deny(entry)}\n            >\n              <XIcon strokeWidth={1.75} width={16} height={16} />\n            </ControlButton>\n          </li>\n        ))}\n      </ul>\n    </section>\n  );\n}\n\n/**\n * THE NOTE-TAKER'S STATE, on screen, with the server's own words.\n *\n * 🚨 NEVER A SPINNER. Every one of the five states (D9/MRI-A2) has a sentence,\n * and a refused dispatch shows the SERVER's `reason` and `remedy` verbatim —\n * \"no worker is registered under matrx-note-taker\", and what to do about it.\n * Through 0.2.1 a failed dispatch threw and the panel showed a remedy with no\n * state behind it; a person could not tell \"it refused\" from \"it is coming\".\n */\nfunction NoteTakerRow(): ReactNode {\n  const ai = useMeetAi();\n  const status = ai.noteTaker;\n  const duplicateError =\n    status.refusal !== null &&\n    ai.error !== null &&\n    status.refusal.reason === ai.error.message &&\n    status.refusal.remedy === ai.error.remedy;\n  return (\n    <section className=\"mx-meet__note-taker\" aria-label=\"Note-taker\">\n      <p className={`mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`}>\n        <span className=\"mx-meet__note-taker-dot\" aria-hidden=\"true\" />\n        {ai.noteTakerLabel}\n      </p>\n      {status.detail !== null ? (\n        <p className=\"mx-meet__panel-note\">{status.detail}</p>\n      ) : null}\n\n      {/* THE REFUSAL, VERBATIM. Not summarized, not replaced by a house\n          sentence, and not hidden behind a retry that would refuse again. */}\n      {status.refusal !== null ? (\n        <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={status.refusal} operation=\"Join this meeting\" origin=\"meet/components\">\n          <p className=\"mx-meet__refusal-reason\">{status.refusal.reason}</p>\n          {status.refusal.remedy.length > 0 ? (\n            <p className=\"mx-meet__refusal-remedy\">{status.refusal.remedy}</p>\n          ) : null}\n        </ErrorBox>\n      ) : null}\n\n      {ai.error !== null && !duplicateError ? (\n        <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={ai.error} operation=\"Run the meeting assistant\" origin=\"meet/components\">\n          <p className=\"mx-meet__refusal-reason\">{ai.error.message}</p>\n          <p className=\"mx-meet__refusal-remedy\">{ai.error.remedy}</p>\n        </ErrorBox>\n      ) : null}\n\n      {/* A control an actor cannot use is ABSENT (no dead ends). A guest and a\n          non-host see the STATE and no buttons at all. */}\n      {ai.canControlNoteTaker ? (\n        status.state === \"transcribing\" ||\n        status.state === \"joining\" ||\n        status.state === \"handoff_pending\" ? (\n          <button\n            type=\"button\"\n            className=\"mx-meet__link\"\n            onClick={() => void ai.stopNoteTaker()}\n          >\n            Dismiss the note-taker\n          </button>\n        ) : (\n          <button\n            type=\"button\"\n            className=\"mx-meet__primary\"\n            onClick={() => void ai.startNoteTaker()}\n          >\n            Start note-taker\n          </button>\n        )\n      ) : null}\n    </section>\n  );\n}\n\nexport function NoteList({\n  title,\n  notes,\n  empty,\n}: {\n  title: string;\n  notes: readonly { id: string; text: string; assigneeDisplayName?: string | null }[];\n  empty: string;\n}): ReactNode {\n  return (\n    <section className=\"mx-meet__note-group\" aria-label={title}>\n      <h3 className=\"mx-meet__note-group-title\">{title}</h3>\n      {notes.length === 0 ? (\n        <p className=\"mx-meet__panel-note\">{empty}</p>\n      ) : (\n        <ul className=\"mx-meet__notes\">\n          {notes.map((note) => (\n            <li key={note.id} className=\"mx-meet__note\">\n              {note.text}\n              {/* D18: a guest never gets an `assignee_user_id`, so the name is\n                  read from the row's metadata — an action item whose owner has\n                  no name is an action item nobody owns. */}\n              {note.assigneeDisplayName !== undefined &&\n              note.assigneeDisplayName !== null ? (\n                <span className=\"mx-meet__assignee\">{note.assigneeDisplayName}</span>\n              ) : null}\n            </li>\n          ))}\n        </ul>\n      )}\n    </section>\n  );\n}\n\n/**\n * THE MEETING ASSISTANT (R4). The note-taker's state, what the meeting has\n * decided so far, the wrap-up, and a question box whose answer arrives token by\n * token.\n *\n * Nothing on this panel is computed here: notes, decisions and action items are\n * durable rows delivered by Postgres Changes, and the answer is streamed from\n * `/intelligence/ask`, which builds it from those same rows. The captions this\n * client can see are never sent anywhere (D16).\n */\nexport function AiPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const ai = useMeetAi();\n  const [question, setQuestion] = useState(\"\");\n\n  return (\n    <PanelShell title=\"Meeting assistant\" onClose={onClose}>\n      <NoteTakerRow />\n\n      {ai.summary !== null ? (\n        <section className=\"mx-meet__note-group\" aria-label=\"Summary\">\n          <h3 className=\"mx-meet__note-group-title\">Summary</h3>\n          <p className=\"mx-meet__summary\">{ai.summary.text}</p>\n        </section>\n      ) : null}\n\n      {/*\n        THE WRAP-UP, ANNOUNCED IN THE ROOM (MRI-A12). It says the pass FINISHED,\n        which is the one thing the notes above cannot say for themselves — a\n        panel with no summary is otherwise indistinguishable from a summary that\n        is still being written. It is absent, never a placeholder, when nothing\n        was announced: on the ordinary ending path the room is deleted before the\n        pass runs, and the summary is read on the post-meeting record instead.\n      */}\n      {ai.wrapUp !== null ? (\n        <p className=\"mx-meet__wrap-up-notice\" role=\"status\">\n          The wrap-up is written — {ai.wrapUp.noteIds.length}{\" \"}\n          {ai.wrapUp.noteIds.length === 1 ? \"entry\" : \"entries\"} from{\" \"}\n          {ai.wrapUp.segmentCount}{\" \"}\n          {ai.wrapUp.segmentCount === 1 ? \"transcript line\" : \"transcript lines\"}.\n        </p>\n      ) : null}\n\n      <NoteList\n        title=\"Notes\"\n        notes={ai.notes}\n        empty=\"Notes appear here as the meeting goes on.\"\n      />\n      <NoteList\n        title=\"Decisions\"\n        notes={ai.decisions}\n        empty=\"Nothing has been decided yet.\"\n      />\n      <NoteList\n        title=\"Action items\"\n        notes={ai.actionItems}\n        empty=\"No action items yet.\"\n      />\n\n      {ai.transcript.length > 0 ? (\n        <section className=\"mx-meet__note-group\" aria-label=\"Transcript\">\n          <h3 className=\"mx-meet__note-group-title\">Transcript</h3>\n          <ul className=\"mx-meet__transcript\">\n            {ai.transcript.map((line) => (\n              <li\n                key={line.id}\n                className={\n                  line.final && line.source === \"record\"\n                    ? \"mx-meet__line\"\n                    : \"mx-meet__line mx-meet__line--interim\"\n                }\n              >\n                <strong>{line.speaker}</strong>\n                <span>{line.text}</span>\n              </li>\n            ))}\n          </ul>\n        </section>\n      ) : null}\n\n      <form\n        className=\"mx-meet__composer\"\n        onSubmit={(event) => {\n          event.preventDefault();\n          const asked = question;\n          setQuestion(\"\");\n          void ai.ask(asked);\n        }}\n      >\n        <input\n          className=\"mx-meet__input\"\n          value={question}\n          onChange={(event) => setQuestion(event.target.value)}\n          placeholder=\"Ask about this meeting\"\n          aria-label=\"Ask about this meeting\"\n        />\n        <button type=\"submit\" className=\"mx-meet__send\" disabled={ai.asking}>\n          {ai.asking ? \"Asking…\" : \"Ask\"}\n        </button>\n      </form>\n\n      {/* THE SERVER'S PHASE, not a spinner of our invention. */}\n      {ai.asking && ai.phase !== null ? (\n        <p className=\"mx-meet__panel-note\" role=\"status\">\n          {ai.phase}\n        </p>\n      ) : null}\n      {ai.answer !== null ? <p className=\"mx-meet__answer\">{ai.answer}</p> : null}\n      {/* WHAT THE ANSWER WAS BUILT FROM. The server measures it; a truncated\n          transcript is stated rather than quietly answered around. */}\n      {ai.answer !== null && ai.coverage !== null ? (\n        <p className=\"mx-meet__coverage\">\n          Answered from {ai.coverage.segmentsUsed} of {ai.coverage.segmentsTotal} transcript\n          lines\n          {ai.coverage.truncated ? \" (the oldest were left out)\" : \"\"}.\n        </p>\n      ) : null}\n      {/* THE REMEDY, not a shrug — and rendered by THIS hook instance, because\n          `useMeetAi()` holds its own ask state per component. */}\n      {ai.error !== null ? (\n        <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={ai.error} operation=\"Run the meeting assistant\" origin=\"meet/components\">\n          <p className=\"mx-meet__refusal-reason\">{ai.error.message}</p>\n          <p className=\"mx-meet__refusal-remedy\">{ai.error.remedy}</p>\n        </ErrorBox>\n      ) : null}\n    </PanelShell>\n  );\n}\n\n/**\n * LIVE CAPTIONS. The last few lines, over the stage, for anyone who reads\n * faster than they hear.\n *\n * They are HINTS (D16) — the durable segment replaces the line it captioned as\n * soon as the row lands — so an unsettled line renders differently from a\n * settled one and nothing downstream ever reads this list.\n */\nexport function Captions({ lines = 3 }: { lines?: number }): ReactNode {\n  const ai = useMeetAi();\n  const visible = ai.transcript.slice(-lines);\n  // Meet wave 5: a viewer who chose a language reads the translation, with the words\n  // as spoken beneath it until the translation lands.\n  const translation = useCaptionTranslation(visible);\n  // Captions are the VIEWER's own choice (Meet's CC button); nothing renders until they turn them on.\n  const captions = useCaptions();\n  if (!captions.on) return null;\n  if (captions.state === \"unavailable\") {\n    return (\n      <div className=\"mx-meet__captions\" role=\"status\" data-meet-notice=\"captions-unavailable\">\n        <p className=\"mx-meet__caption\">\n          {(captions.reason ?? \"\").startsWith(\"Captions are unavailable\") ? \"\" : \"Captions are unavailable. \"}{captions.reason}\n          {captions.remedy !== null ? ` ${captions.remedy}` : \"\"}\n        </p>\n        <button type=\"button\" className=\"mx-meet__caption-retry\" onClick={captions.retry}>\n          Try again\n        </button>\n      </div>\n    );\n  }\n  if (visible.length === 0) {\n    return (\n      <div className=\"mx-meet__captions\" aria-live=\"polite\" aria-label=\"Live captions\" data-meet-caption={captions.state}>\n        <p className=\"mx-meet__caption mx-meet__caption--interim\">\n          {captions.state === \"starting\" ? \"Starting captions. They appear as people speak.\" : \"Captions are on. They appear as people speak.\"}\n        </p>\n      </div>\n    );\n  }\n  return (\n    <div className=\"mx-meet__captions\" aria-live=\"polite\" aria-label=\"Live captions\" data-meet-caption=\"live\">\n      {visible.map((line) => {\n        const translated = translation.language === null ? undefined : translation.translations[line.id];\n        return (\n          <p\n            key={line.id}\n            className={\n              line.final ? \"mx-meet__caption\" : \"mx-meet__caption mx-meet__caption--interim\"\n            }\n          >\n            <strong>{line.speaker}</strong> {translated ?? line.text}\n            {translated !== undefined ? <span className=\"mx-meet__caption-original\">{line.text}</span> : null}\n          </p>\n        );\n      })}\n      {translation.language !== null && translation.error !== null ? (\n        <p className=\"mx-meet__caption mx-meet__caption--interim\">{translation.error}</p>\n      ) : null}\n    </div>\n  );\n}\n\n/**\n * CONSENT IS NOT A PROP (README rule 8, D10).\n *\n * Whenever an agent participant is in the room, EVERY participant sees this —\n * host, member and guest alike. There is no prop that hides it and no host code\n * involved: through 0.2.1 the first real consumer had to write this banner\n * itself by reading `isAgent` off the roster, which is exactly the massage C22\n * forbids.\n */\nexport function ConsentNotice(): ReactNode {\n  const notice = useConsentNotice();\n  if (notice === null) return null;\n  return (\n    <p className=\"mx-meet__consent\" role=\"status\" data-meet-notice=\"notes-started\">\n      {notice}\n    </p>\n  );\n}\n\n/**\n * LISTEN-ONLY ATTENDANCE, said out loud. Shown whenever the local participant\n * is in the room publishing no microphone — whether they chose that or the\n * browser refused. When it was refused, the browser's own reason and the remedy\n * are shown too, because \"others can't hear you\" without \"and here is why\"\n * leaves someone clicking a mute button that cannot work.\n */\nexport function AttendanceNotice(): ReactNode {\n  const media = useLocalMedia();\n  const notice = listenOnlyNotice(media);\n  if (notice === null) return null;\n  const refused = media.microphone.unavailable;\n  const code = microphoneNoticeCode(media.microphone);\n  return (\n    <p\n      className=\"mx-meet__banner mx-meet__banner--attendance\"\n      role=\"status\"\n      {...(code !== null ? { \"data-meet-notice\": code } : {})}\n    >\n      {notice}\n      {refused === null ? null : <span className=\"mx-meet__remedy\">{refused.remedy}</span>}\n    </p>\n  );\n}\n\n/* --------------------------------------------------------------- pre-join */\n\nexport function PreJoin(props: {\n  roomName: RoomName;\n  meetingId?: string;\n  slug?: string;\n  onJoined?: () => void;\n  /** HR-360 wave 2 (MD-16): join as a silent observer — no camera, no microphone. */\n  observe?: boolean;\n}): ReactNode {\n  // THE GUARD, not a throw. See <InertNotice>.\n  const host = useMeetHost();\n  if (host === null) return <InertNotice what=\"This meeting\" />;\n  return <PreJoinBody {...props} host={host} />;\n}\n\nfunction PreJoinBody({\n  roomName,\n  meetingId,\n  slug,\n  onJoined,\n  observe = false,\n  host,\n}: {\n  roomName: RoomName;\n  meetingId?: string;\n  slug?: string;\n  onJoined?: () => void;\n  observe?: boolean;\n  host: MeetHost;\n}): ReactNode {\n  const room = useRoom();\n  const devices = useDeviceSnapshot();\n  const recording = useRecording();\n  const effects = useMediaEffects();\n  const { notice } = useModerationNotice();\n  const [mode, setMode] = useState<CallMode>(\"video\");\n  // Attendance is not contingent on a device (see core/attendance.ts), so this\n  // is an ordinary choice, not a gate. Unchecking it joins listen-only; leaving\n  // it checked and having the browser refuse ALSO joins, listen-only, with the\n  // refusal's own remedy shown in the room.\n  const [microphone, setMicrophone] = useState(true);\n  const [joining, setJoining] = useState(false);\n  const camera = devices?.selected.videoinput ?? host.devices.resolve(\"videoinput\");\n  const mic = devices?.selected.audioinput ?? host.devices.resolve(\"audioinput\");\n  const { reportPreview } = useMediaSupervisor();\n  const [attempt, setAttempt] = useState(0);\n  const preview = useCameraPreview(\n    mode === \"video\" ? camera : undefined,\n    effects.effects,\n    (outcome) => reportPreview(\"camera\", outcome),\n    attempt,\n  );\n  const micStream = useMicrophoneStream(microphone ? mic : \"off\", (outcome) => reportPreview(\"microphone\", outcome), attempt);\n  const level = useAudioLevel(micStream);\n  const [speakerTesting, setSpeakerTesting] = useState(false);\n\n  useEffect(() => {\n    void host.devices.refresh();\n  }, [host]);\n\n  // S7: another tab of THIS browser already has the person in this room — the choice is offered\n  // before Join, not discovered after the press.\n  const { checkElsewhere } = room;\n  useEffect(() => {\n    void checkElsewhere(roomName);\n  }, [checkElsewhere, roomName]);\n\n  const joinWith = (secondDevice?: \"switch_here\" | \"join_too\"): void => {\n    setJoining(true);\n    // The preview hands the camera back before the room takes it.\n    preview.release();\n    void room\n      .join({\n        roomName,\n        // An observer publishes nothing: no camera, no microphone (MD-16). A companion\n        // (\"join here too\") never opens the microphone (S7).\n        mode: observe ? \"audio\" : mode,\n        microphone: observe || secondDevice === \"join_too\" ? false : microphone,\n        ...(meetingId !== undefined ? { meetingId } : {}),\n        ...(slug !== undefined ? { slug } : {}),\n        ...(observe ? { observe: true } : {}),\n        ...(secondDevice !== undefined ? { secondDevice } : {}),\n      })\n      .then(() => onJoined?.())\n      // The failure is ON SCREEN (room.failure, the server's sentence); an\n      // unhandled rejection only added a page error nobody can act on.\n      .catch(() => undefined)\n      .finally(() => setJoining(false));\n  };\n\n  return (\n    <div className=\"mx-meet__prejoin\">\n      <div className=\"mx-meet__preview\">\n        {mode === \"video\" && preview.preview !== null ? (\n          <video\n            className=\"mx-meet__video mx-meet__video--mirror\"\n            autoPlay\n            playsInline\n            muted\n            ref={(element) => {\n              if (element !== null) preview.preview?.attach(element);\n            }}\n          />\n        ) : (\n          <div className=\"mx-meet__tile-placeholder\">\n            <MeetAvatar name={host.identity.displayName} url={host.identity.avatarUrl} size={96} />\n          </div>\n        )}\n        {mode === \"video\" && preview.error !== null ? (\n          <p className=\"mx-meet__preview-note\">{preview.error}</p>\n        ) : null}\n        {microphone && micStream !== null ? (\n          <div className=\"mx-meet__meter mx-meet__meter--preview\" role=\"meter\" aria-label=\"Microphone level\" aria-valuemin={0} aria-valuemax={100} aria-valuenow={Math.round(level * 100)}>\n            <span style={{ width: `${Math.min(100, Math.round(level * 160))}%` }} />\n          </div>\n        ) : null}\n      </div>\n\n      <div className=\"mx-meet__prejoin-panel\">\n        <h1 className=\"mx-meet__prejoin-title\">Ready to join?</h1>\n\n        <PreviewStatus onRetry={() => setAttempt((n) => n + 1)} />\n\n        {notice?.kind === \"removed\" ? <p className=\"mx-meet__warning\">{notice.text}</p> : null}\n\n        {devices?.labelsHidden === true ? (\n          <p className=\"mx-meet__panel-note\">\n            Your browser is hiding device names until you allow camera and microphone access.\n            <button\n              type=\"button\"\n              className=\"mx-meet__link\"\n              onClick={() => {\n                void host.devices.requestPermission({ audio: true, video: true });\n              }}\n            >\n              Allow access\n            </button>\n          </p>\n        ) : null}\n\n        {/* A FALLBACK ANNOUNCES ITSELF — an unplugged headset never silently\n            becomes the laptop mic. */}\n        {devices?.fallbackNotice != null ? (\n          <p className=\"mx-meet__warning\">{devices.fallbackNotice}</p>\n        ) : null}\n\n        <DevicePicker kind=\"audioinput\" label=\"Microphone\" />\n        <div className=\"mx-meet__field-row\">\n          <DevicePicker kind=\"audiooutput\" label=\"Speaker\" />\n          <Button\n            type=\"button\"\n            variant=\"outline\"\n            disabled={speakerTesting}\n            onClick={() => {\n              setSpeakerTesting(true);\n              void playTestSound(devices?.selected.audiooutput ?? host.devices.resolve(\"audiooutput\")).finally(\n                () => setSpeakerTesting(false),\n              );\n            }}\n          >\n            <SpeakerIcon /> {speakerTesting ? \"Playing…\" : \"Test\"}\n          </Button>\n        </div>\n        <DevicePicker kind=\"videoinput\" label=\"Camera\" />\n        <EffectsSettings preview={preview.preview} />\n\n        {recording.consentNotice !== null ? (\n          <Alert variant=\"info\">\n            <AlertDescription>{recording.consentNotice}</AlertDescription>\n          </Alert>\n        ) : null}\n\n        <div className=\"mx-meet__prejoin-actions\">\n          <div className=\"mx-meet__check\">\n            <Checkbox\n              id=\"mx-meet-join-video\"\n              checked={mode === \"video\"}\n              onCheckedChange={(checked) => setMode(checked === true ? \"video\" : \"audio\")}\n            />\n            <Label htmlFor=\"mx-meet-join-video\">Join with video</Label>\n          </div>\n          <div className=\"mx-meet__check\">\n            <Checkbox\n              id=\"mx-meet-join-mic\"\n              checked={microphone}\n              onCheckedChange={(checked) => setMicrophone(checked === true)}\n            />\n            <Label htmlFor=\"mx-meet-join-mic\">Join with microphone</Label>\n          </div>\n          {room.secondDevice === null ? (\n            <Button type=\"button\" className=\"mx-meet__join\" disabled={joining} onClick={() => joinWith()}>\n              {joining ? \"Joining…\" : observe ? \"Observe\" : \"Join now\"}\n            </Button>\n          ) : (\n            // S7: ALREADY IN THIS MEETING on another tab or device — the meeting's choice\n            // (Meet: Switch here / Join here too; Teams: Transfer here / Add this device).\n            <div className=\"mx-meet__second-device\" data-meet-region=\"second-device\">\n              <p className=\"mx-meet__hint\">You're in this meeting on another device</p>\n              <Button\n                type=\"button\"\n                className=\"mx-meet__join\"\n                data-meet-control=\"switch-here\"\n                disabled={joining}\n                onClick={() => joinWith(\"switch_here\")}\n              >\n                {room.secondDevice.rule === \"ask_transfer_or_add\" ? \"Transfer here\" : \"Switch here\"}\n              </Button>\n              <Button\n                type=\"button\"\n                variant=\"outline\"\n                data-meet-control=\"join-too\"\n                disabled={joining}\n                onClick={() => joinWith(\"join_too\")}\n              >\n                {room.secondDevice.rule === \"ask_transfer_or_add\" ? \"Add this device\" : \"Join here too\"}\n              </Button>\n            </div>\n          )}\n        </div>\n\n        {room.failure !== null ? (\n          <p className=\"mx-meet__error\">\n            {room.failure.message}\n            <span className=\"mx-meet__remedy\">{room.failure.remedy}</span>\n          </p>\n        ) : null}\n      </div>\n    </div>\n  );\n}\n\n/**\n * The pre-join camera, WITH the chosen background — the same SDK track and\n * processor the room uses. `undefined` device = camera not wanted (no preview,\n * no light). A refused camera is a sentence, never a black box.\n */\nfunction useCameraPreview(\n  deviceId: string | null | undefined,\n  effects: MediaEffects,\n  report?: (outcome: \"prompting\" | \"on\" | \"off\" | { readonly error: unknown }) => void,\n  attempt = 0,\n): { preview: CameraPreview | null; error: string | null; release: () => void } {\n  const reportRef = useRef(report);\n  reportRef.current = report;\n  const [preview, setPreview] = useState<CameraPreview | null>(null);\n  const [error, setError] = useState<string | null>(null);\n  const current = useRef<CameraPreview | null>(null);\n  const initialEffect = useRef(toVideoEffect(effects));\n  initialEffect.current = toVideoEffect(effects);\n  useEffect(() => {\n    if (deviceId === undefined) {\n      reportRef.current?.(\"off\");\n      return undefined;\n    }\n    let live = true;\n    setError(null);\n    reportRef.current?.(\"prompting\");\n    void createCameraPreview(deviceId, initialEffect.current)\n      .then((created) => {\n        if (!live) {\n          created.stop();\n          return;\n        }\n        current.current = created;\n        setPreview(created);\n        reportRef.current?.(\"on\");\n      })\n      .catch((thrown: unknown) => {\n        if (!live) return;\n        reportRef.current?.({ error: thrown });\n        const failure = thrown as { message?: string; remedy?: string };\n        // The person reads the sentence and its remedy — never the operation tag\n        // (\"meet.cameraPreview: …\") a diagnostic carries.\n        const message = (failure.message ?? \"\").replace(/^meet\\.[A-Za-z.()]+:\\s*/, \"\");\n        const sentence = message.length > 0 ? message.charAt(0).toUpperCase() + message.slice(1) : \"\";\n        setError([sentence, failure.remedy].filter(Boolean).join(\". \") || \"The camera did not start.\");\n      });\n    return () => {\n      live = false;\n      current.current?.stop();\n      current.current = null;\n      setPreview(null);\n    };\n  }, [deviceId, attempt]);\n  return {\n    preview,\n    error,\n    release: () => {\n      current.current?.stop();\n      current.current = null;\n      setPreview(null);\n    },\n  };\n}\n\nfunction DevicePicker({\n  kind,\n  label,\n  onPick,\n}: {\n  kind: \"audioinput\" | \"videoinput\" | \"audiooutput\";\n  label: string;\n  /** In the room: also switch the live device. Pre-join: the choice is applied on join. */\n  onPick?: (kind: \"audioinput\" | \"videoinput\" | \"audiooutput\", deviceId: string) => void;\n}): ReactNode {\n  const host = useRequiredMeetHost();\n  const devices = useDeviceSnapshot();\n  const list = devices?.devices[kind] ?? [];\n  // A browser that cannot route audio output (Safari, Firefox without the flag)\n  // lists no outputs — the picker is then absent, never a select that lies.\n  if (list.length === 0) return null;\n  const triggerId = `mx-meet-device-${kind}`;\n  // Radix Select refuses an empty-string item value; a device with no id\n  // (some browsers before permission) is listed under a stable stand-in.\n  const valueOf = (deviceId: string) => (deviceId.length > 0 ? deviceId : \"default\");\n  const current = devices?.selected[kind] ?? host.devices.resolve(kind) ?? \"\";\n  return (\n    <div className=\"mx-meet__field\">\n      <Label htmlFor={triggerId}>{label}</Label>\n      <Select\n        {...(current.length > 0 ? { value: valueOf(current) } : {})}\n        onValueChange={(value) => {\n          const deviceId = list.find((device) => valueOf(device.deviceId) === value)?.deviceId ?? value;\n          if (onPick !== undefined) onPick(kind, deviceId);\n          else host.devices.select(kind, deviceId);\n        }}\n      >\n        <SelectTrigger id={triggerId} aria-label={label}>\n          <SelectValue placeholder={label} />\n        </SelectTrigger>\n        <SelectContent>\n          {list.map((device) => (\n            <SelectItem key={device.deviceId || \"default\"} value={valueOf(device.deviceId)}>\n              {device.label.length > 0 ? device.label : `${label} (name hidden)`}\n            </SelectItem>\n          ))}\n        </SelectContent>\n      </Select>\n    </div>\n  );\n}\n\n/* ----------------------------------------------------------- meeting room */\n\n/**\n * THE MEET SKIN'S ROOM (v0) — today's pre-join, waiting room and live room,\n * chosen by the store's phase. `<MeetingSkinRoot>` (in `@ai-matrx/meet/react`)\n * owns everything that is not a look: the inert guard, the observation root,\n * watching the room and the meeting, the resolved-row seed and the ended\n * meeting's record. This renders only once a runtime exists and the meeting\n * is live or joinable.\n */\nexport function MeetSkinRoom({\n  roomName,\n  meetingId,\n  slug,\n  onLeave,\n  headerControls,\n  observe = false,\n}: {\n  roomName: RoomName;\n  meetingId?: string;\n  slug?: string;\n  onLeave?: () => void;\n  /** HR-360 wave 2 (MD-16): the pre-join joins as a silent observer. */\n  observe?: boolean;\n  /**\n   * A HOST-PROVIDED control for the in-meeting header — rendered in the header\n   * row of the live room only. The package never inspects it.\n   */\n  headerControls?: ReactNode;\n}): ReactNode {\n  const core = useMeetCore();\n  const { host, snapshot, isHost, phase } = core;\n  const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);\n  if (host === null) return null;\n\n  // THE PHASE → SCREEN MAP (CORE-DESIGN §3.1, §5.4): one screen per phase, exhaustive — a phase\n  // added to the machine without a screen here is a compile error. Nothing the person can be in\n  // renders pre-join except `prejoin` itself.\n  const screen = (() => {\n    if (isRefusedPhase(phase)) return \"refused\" as const;\n    switch (phase) {\n      case \"resolving\":\n        return \"resolving\" as const;\n      case \"prejoin\":\n      case \"guest_name\":\n        return \"prejoin\" as const;\n      case \"joining\":\n      case \"in_call\":\n        return \"room\" as const;\n      case \"waiting:host_not_started\":\n      case \"waiting:knocking\":\n      case \"denied\":\n      case \"knock_expired\":\n        return \"waiting\" as const;\n      case \"left\":\n        return snapshot?.waiting?.admission === \"withdrawn\" ? (\"waiting\" as const) : (\"exit\" as const);\n      case \"disconnected\":\n      case \"removed\":\n      case \"superseded\":\n      case \"inactive\":\n      case \"unsupported\":\n      case \"ended\":\n      case \"record\":\n      case \"ringing_out\":\n      case \"ringing_in\":\n      case \"call_declined\":\n      case \"call_missed\":\n      case \"call_busy\":\n      case \"answered_elsewhere\":\n        return \"exit\" as const;\n      default: {\n        const unhandled: never = phase;\n        return unhandled;\n      }\n    }\n  })();\n\n  if (screen === \"resolving\") {\n    return (\n      <div className=\"mx-meet\">\n        <p className=\"mx-meet__empty-body\" role=\"status\">Getting the meeting ready…</p>\n      </div>\n    );\n  }\n\n  if (screen === \"prejoin\") {\n    return (\n      <div className=\"mx-meet\">\n        <PreJoin\n          roomName={roomName}\n          {...(meetingId !== undefined ? { meetingId } : {})}\n          {...(slug !== undefined ? { slug } : {})}\n          observe={observe}\n        />\n      </div>\n    );\n  }\n\n  if (screen === \"waiting\") {\n    return (\n      <div className=\"mx-meet mx-meet--lobby\">\n        <WaitingRoom host={host} {...(onLeave !== undefined ? { onLeave } : {})} />\n      </div>\n    );\n  }\n\n  if (screen === \"refused\" || screen === \"exit\") {\n    return (\n      <div className=\"mx-meet mx-meet--lobby\">\n        <ExitScreen {...(onLeave !== undefined ? { onLeave } : {})} />\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"mx-meet\">\n      <ConsentNotice />\n      <AttendanceNotice />\n      <header className=\"mx-meet__header\">\n        <h1 className=\"mx-meet__title\">{snapshot?.meeting?.title ?? \"Meeting\"}</h1>\n        <span className=\"mx-meet__meta\">\n          {participantSummary(snapshot?.participants ?? [])}\n          {elapsed > 0 ? ` · ${formatDurationMs(elapsed)}` : \"\"}\n        </span>\n        <RecordingIndicator />\n        {captureHeldOf(snapshot?.meeting) ? (\n          <span className=\"mx-meet__badge\" data-meet-capture-held=\"\">\n            Confidential · not recorded\n          </span>\n        ) : null}\n        {isObserverRole(snapshot?.grants.role) ? (\n          <span className=\"mx-meet__badge\" data-meet-observing=\"self\">Observing</span>\n        ) : null}\n        {snapshot?.locked === true ? (\n          <span className=\"mx-meet__badge\">\n            <LockIcon strokeWidth={1.75} width={12} height={12} /> Locked\n          </span>\n        ) : null}\n        {headerControls !== undefined && headerControls !== null ? (\n          <span className=\"mx-meet__header-controls\" data-meet-header-controls=\"\">\n            {headerControls}\n          </span>\n        ) : null}\n        {isHost ? <HostMenu /> : null}\n      </header>\n\n      {/* A reconnect is VISIBLE, after the profile's debounce (S6b) — and it says WHICH problem,\n          because no network and unreachable servers have different fixes. */}\n      {core.connectionBanner && core.connection !== \"stable\" ? (\n        <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice={`connection-${core.connection}`}>\n          {CONNECTION_BANNER[core.connection]}\n        </p>\n      ) : null}\n      <ShareNotice />\n      <NetworkNotice />\n\n      <Stage />\n      <Captions />\n      <ControlBar {...(onLeave !== undefined ? { onLeave } : {})} />\n    </div>\n  );\n}\n\n/**\n * WHAT MY OWN NETWORK IS DOING (P1 connection-network) — at most one notice, most urgent first:\n * the camera paused to keep the audio (`net-video-auto-off`), a poor connection with the fix\n * (`net-quality-self`), media on a restricted network (`net-udp-blocked`, shown once, briefly).\n * Never while the reconnect banner is up: that one says more.\n */\nconst RESTRICTED_NOTICE_MS = 30_000;\n\nexport function NetworkNotice(): ReactNode {\n  const { snapshot, connectionBanner } = useMeetCore();\n  const room = useRoom();\n  const network = snapshot?.localNetwork;\n  const [closed, setClosed] = useState<ReadonlySet<string>>(() => new Set());\n  const [restrictedSince, setRestrictedSince] = useState<number | null>(null);\n  const [, setTick] = useState(0);\n  const restricted = network?.path === \"restricted\";\n  useEffect(() => {\n    if (!restricted || restrictedSince !== null) return;\n    setRestrictedSince(Date.now());\n    const timer = setTimeout(() => setTick((n) => n + 1), RESTRICTED_NOTICE_MS + 50);\n    return () => clearTimeout(timer);\n  }, [restricted, restrictedSince]);\n  if (network === undefined || snapshot?.phase !== \"in_call\" || connectionBanner) return null;\n  const close = (code: string) => () => setClosed((prev) => new Set([...prev, code]));\n  const cameraOn = room.local?.cameraEnabled === true;\n  if (network.videoPaused && !cameraOn) {\n    return (\n      <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"video-paused\">\n        Your video is paused to save your audio\n        <button type=\"button\" className=\"mx-meet__link\" onClick={() => void room.toggleCamera()}>\n          Try video again\n        </button>\n      </p>\n    );\n  }\n  if (network.quality === \"poor\" && !closed.has(\"connection-poor\")) {\n    return (\n      <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"connection-poor\">\n        Your connection is unstable\n        {cameraOn ? (\n          <button type=\"button\" className=\"mx-meet__link\" onClick={() => void room.toggleCamera()}>\n            Turn off camera\n          </button>\n        ) : null}\n        <button type=\"button\" className=\"mx-meet__link\" onClick={close(\"connection-poor\")}>\n          Dismiss\n        </button>\n      </p>\n    );\n  }\n  if (restricted && !closed.has(\"restricted-network\") && restrictedSince !== null && Date.now() - restrictedSince < RESTRICTED_NOTICE_MS) {\n    return (\n      <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"restricted-network\">\n        Restricted network · quality may be reduced\n        <button type=\"button\" className=\"mx-meet__link\" onClick={close(\"restricted-network\")}>\n          Dismiss\n        </button>\n      </p>\n    );\n  }\n  return null;\n}\n\n/**\n * A REFUSED SHARE IS A NOTICE, NEVER AN EXIT (CORE-DESIGN §3.3 SA). It stays until the person\n * dismisses it or shares again; the call carries on underneath.\n */\nfunction ShareNotice(): ReactNode {\n  const { share, actions, snapshot } = useMeetCore();\n  const [soundHintClosed, setSoundHintClosed] = useState<number | null>(null);\n  if (share.state === \"presenting\" && share.audio === false && soundHintClosed !== share.at) {\n    // `share-audio`: the share has no sound — said once per share, with how to include it.\n    return (\n      <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"share-audio-missing\">\n        Sound not shared\n        <span className=\"mx-meet__remedy\">To include sound, share a tab and turn on Also share tab audio</span>\n        <button type=\"button\" className=\"mx-meet__link\" onClick={() => setSoundHintClosed(share.at)}>\n          Dismiss\n        </button>\n      </p>\n    );\n  }\n  if (share.state === \"ended\") {\n    // The SERVER took the share down (`share-takeover`, `share-who-can`) and says why — never a share that just vanishes.\n    const replaced = share.reason === \"replaced\";\n    const rule = snapshot?.livePolicy.shareWhoCan ?? \"host_only\";\n    const why = replaced\n      ? `${share.by ?? \"Someone\"} is now presenting`\n      : rule === \"presenters\"\n        ? \"Sharing is turned off. Only presenters can share their screen\"\n        : rule === \"org\"\n          ? \"Sharing is turned off. Only people in the organization can share their screen\"\n          : \"Sharing is turned off. Only the host can share their screen\";\n    return (\n      <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice={replaced ? \"share-ended\" : \"share-unavailable\"}>\n        {replaced ? \"Your presentation ended\" : \"Your presentation was stopped\"}\n        <span className=\"mx-meet__remedy\">{why}</span>\n        <button type=\"button\" className=\"mx-meet__link\" onClick={() => actions.dismissShareNotice()}>\n          Dismiss\n        </button>\n      </p>\n    );\n  }\n  if (share.state !== \"refused\") return null;\n  const text =\n    share.reason === \"unsupported\"\n      ? \"You can't share your screen from this browser\"\n      : share.reason === \"blocked\"\n        ? \"Screen sharing is blocked\"\n        : \"Couldn't start sharing your screen\";\n  return (\n    <p className=\"mx-meet__banner\" role=\"status\" data-meet-notice=\"share-unavailable\">\n      {text}\n      {share.remedy !== null ? <span className=\"mx-meet__remedy\">{share.remedy}</span> : null}\n      <button type=\"button\" className=\"mx-meet__link\" onClick={actions.dismissShareNotice}>\n        Dismiss\n      </button>\n    </p>\n  );\n}\n\n/** The words for each refusal and exit reason (the skin owns every string, §5.4). */\nconst REFUSED_TITLES: Record<string, string> = {\n  not_found: \"Check your meeting code\",\n  cancelled: \"This meeting was canceled\",\n  expired: \"This meeting link has expired\",\n  too_early: \"This meeting hasn't started yet\",\n  sign_in_required: \"Sign in to join this meeting\",\n  wrong_account: \"You're signed in with a different account\",\n  not_invited: \"You aren't invited to this meeting\",\n  locked: \"This meeting is locked\",\n  removed: \"You can't rejoin this meeting\",\n  lobby_rejects: \"The host declined your request\",\n  meeting_full: \"This meeting is full\",\n  platform_capacity: \"Meetings are busy right now\",\n  verification_required: \"Verify your account to join\",\n  registration_required: \"Register to join this meeting\",\n};\n\n/** `0:37` — the time left, for a countdown the person is waiting out. */\nfunction clockText(ms: number): string {\n  return formatDurationMs(Math.ceil(ms / 1000) * 1000, { style: \"clock\" });\n}\n\n/**\n * EVERY WAY OUT OF THE ROOM, SAID PLAINLY (CORE-DESIGN §3.1, §3.4): left, disconnected, removed,\n * replaced, inactive, ended, refused. Each names what happened and offers only what the rules\n * allow — Rejoin where the machine allows it, never a silent pre-join.\n */\nfunction ExitScreen({ onLeave }: { onLeave?: () => void }): ReactNode {\n  const { phase, reason, host, snapshot, actions, call, connection } = useMeetCore();\n  const [busy, setBusy] = useState(false);\n  const failure = snapshot?.failure ?? null;\n  // A declined knock under a cooldown rule: the time left, then the one way to ask again.\n  // `before-start-early-entry`: the same countdown runs to the opening time, then asks again.\n  const retryLeft = useCountdown(\n    phase === \"refused:lobby_rejects\" || phase === \"refused:too_early\" ? (failure?.retryAt ?? null) : null,\n  );\n  const reaskedAtZero = useRef(false);\n  useEffect(() => {\n    if (phase !== \"refused:too_early\") {\n      reaskedAtZero.current = false;\n      return;\n    }\n    if (retryLeft === 0 && !reaskedAtZero.current) {\n      reaskedAtZero.current = true;\n      actions.retry();\n    }\n  }, [phase, retryLeft, actions]);\n  const rejoin = (\n    <Button\n      type=\"button\"\n      disabled={busy}\n      onClick={() => {\n        setBusy(true);\n        void actions\n          .rejoin()\n          .catch(() => undefined)\n          .finally(() => setBusy(false));\n      }}\n    >\n      Rejoin\n    </Button>\n  );\n  const home = (\n    <a\n      className=\"mx-meet__link\"\n      href=\"/\"\n      onClick={(event) => {\n        if (call !== null) {\n          event.preventDefault();\n          actions.dismissCall();\n        }\n        if (onLeave !== undefined) {\n          event.preventDefault();\n          onLeave();\n        }\n      }}\n    >\n      Go home\n    </a>\n  );\n  let title: string;\n  let line: string | null = null;\n  let notice: string | null = null;\n  let actionsNode: ReactNode = home;\n  if (phase.startsWith(\"refused:\")) {\n    const code = phase.slice(\"refused:\".length);\n    // THE SKIN OWNS THE WORDS (CORE-DESIGN §5.4): the screen is decided by the reason CODE.\n    // The server's text is never shown as the headline — it can be a canned generic line\n    // (\"You do not have permission…\") when its own message was short. Only a remedy that\n    // carries specifics the code cannot (the next start time) is shown under the title.\n    title = REFUSED_TITLES[code] ?? \"You can't join this meeting\";\n    line =\n      code === \"too_early\" || code === \"registration_required\" || code === \"cancelled\" || code === \"wrong_account\"\n        ? (failure?.remedy ?? null)\n        : null;\n    if (code === \"too_early\" && retryLeft !== null && retryLeft > 0) line = `Opens in ${clockText(retryLeft)}`;\n    actionsNode = (\n      <>\n        <Button type=\"button\" variant=\"outline\" onClick={actions.retry}>\n          Try again\n        </Button>\n        {home}\n      </>\n    );\n    if (code === \"sign_in_required\" || code === \"wrong_account\") {\n      // `access-sign-in-required` / `access-wrong-account`: the way in is another account.\n      const back = typeof window === \"undefined\" ? \"/\" : `${window.location.pathname}${window.location.search}`;\n      actionsNode = (\n        <>\n          <Button asChild>\n            <a href={`/login?redirectTo=${encodeURIComponent(back)}`}>\n              {code === \"sign_in_required\" ? \"Sign in\" : \"Switch account\"}\n            </a>\n          </Button>\n          {home}\n        </>\n      );\n    }\n    if (code === \"lobby_rejects\") {\n      // THE REFUSAL, NOT A PRE-JOIN: no Join button. The only way to knock again is the one the\n      // meeting's rule allows — a cooldown that has run out — and the button says so.\n      if (retryLeft !== null && retryLeft > 0) {\n        line = `You can ask again in ${clockText(retryLeft)}`;\n        notice = \"reknock-cooldown\";\n        actionsNode = home;\n      } else if (retryLeft === 0) {\n        line = \"You can ask to join again\";\n        actionsNode = (\n          <>\n            <Button\n              type=\"button\"\n              disabled={busy}\n              onClick={() => {\n                setBusy(true);\n                void actions\n                  .rejoin()\n                  .catch(() => undefined)\n                  .finally(() => setBusy(false));\n              }}\n            >\n              Ask to join again\n            </Button>\n            {home}\n          </>\n        );\n      } else {\n        line = \"Ask the host to let you in, then open the link again\";\n        actionsNode = home;\n      }\n    }\n  } else {\n    switch (phase) {\n      case \"left\":\n        title = \"You left the meeting\";\n        actionsNode = (\n          <>\n            {rejoin}\n            {home}\n          </>\n        );\n        break;\n      case \"disconnected\":\n        if (failure?.stage === \"join\" && (failure.reason ?? null) === null) {\n          // `net-cannot-connect`: never got in — what to check, and one Try again.\n          title = \"Can't connect to the meeting\";\n          line = connection === \"offline\"\n            ? \"You're offline. Check your internet connection.\"\n            : \"Check your network. A VPN, firewall or proxy may be blocking the call.\";\n          notice = \"cannot-connect\";\n          actionsNode = (\n            <>\n              <Button\n                type=\"button\"\n                disabled={busy}\n                onClick={() => {\n                  setBusy(true);\n                  void actions\n                    .rejoin()\n                    .catch(() => undefined)\n                    .finally(() => setBusy(false));\n                }}\n              >\n                Try again\n              </Button>\n              {home}\n            </>\n          );\n          break;\n        }\n        title = \"You lost your connection to the meeting\";\n        // S6b: say which problem — and that it rejoins by itself once it can.\n        line =\n          connection === \"offline\"\n            ? \"You're offline. You'll rejoin automatically when your internet is back.\"\n            : connection === \"server_unreachable\"\n              ? \"Can't reach the meeting server. You'll rejoin automatically when it answers.\"\n              : (failure?.remedy ?? \"Check your internet connection, then rejoin.\");\n        notice = \"disconnected\";\n        actionsNode = (\n          <>\n            {rejoin}\n            {home}\n          </>\n        );\n        break;\n      case \"removed\":\n        title = \"You've been removed from the meeting\";\n        notice = \"removed\";\n        break;\n      case \"superseded\":\n        title = \"You joined from another tab or device\";\n        line = \"This screen left the meeting so you aren't in it twice.\";\n        notice = \"displaced\";\n        actionsNode = (\n          <>\n            {rejoin}\n            {home}\n          </>\n        );\n        break;\n      case \"inactive\":\n        title = \"You left the meeting because this tab was inactive\";\n        actionsNode = (\n          <>\n            {rejoin}\n            {home}\n          </>\n        );\n        break;\n      case \"unsupported\":\n        title = \"Meet is not compatible with your browser yet\";\n        line = \"Open this link in Chrome, Edge, Firefox or Safari.\";\n        break;\n      case \"ended\":\n      case \"record\":\n        title = reason === \"time_limit\" ? \"The meeting reached its time limit\" : \"The meeting has ended\";\n        // A series run that ended says so, and when the next one starts (the gate's own words).\n        if (failure?.reason === \"ended\" && failure.remedy.length > 0 && failure.message.startsWith(\"This run\")) {\n          title = failure.message.replace(/\\.$/, \"\");\n          line = failure.remedy;\n        }\n        notice = \"meeting-ended\";\n        break;\n      default:\n        title = \"The call has ended\";\n        break;\n    }\n  }\n  return (\n    <div className=\"mx-meet__waiting\" data-meet-exit={phase}>\n      <MeetAvatar name={host?.identity.displayName ?? \"\"} url={host?.identity.avatarUrl ?? null} size={72} />\n      <h1 className=\"mx-meet__prejoin-title\">{title}</h1>\n      {line !== null ? <p className=\"mx-meet__empty-body\">{line}</p> : null}\n      {notice !== null ? (\n        <span role=\"status\" data-meet-notice={notice} className=\"mx-meet__sr-only\">\n          {notice === \"reknock-cooldown\" && line !== null ? line : title}\n        </span>\n      ) : null}\n      <div className=\"mx-meet__waiting-actions\">{actionsNode}</div>\n    </div>\n  );\n}\n\n/**\n * THE WAITING SCREENS (S4). Every one is the SERVER's word on this person's row — read by the\n * core's state read, never a broadcast: waiting for the host, knocking, declined, no answer,\n * left the waiting room, ended. Controls appear only when the rules allow them.\n */\nfunction WaitingRoom({ host, onLeave }: { host: MeetHost; onLeave?: () => void }): ReactNode {\n  const { waiting, withdraw, askAgain } = useWaiting();\n  const { phaseNotice } = useMeetCore();\n  const localMedia = useLocalMedia();\n  const { region: mediaRegion } = useMediaSupervisor();\n  // A person who knocks with no microphone is told, here, that they will attend listen-only (catalog `device-none-found`).\n  const noMicrophone = localMedia.microphone.unavailable !== null || mediaRegion.preview.microphone.state === \"unavailable\";\n  const [busy, setBusy] = useState(false);\n  const admission = waiting?.admission ?? \"knocking\";\n  // A denial under a cooldown rule: the time left shows, and \"Ask to join again\" appears when it ends.\n  const reknockLeft = useCountdown(admission === \"denied\" ? (waiting?.reknockAt ?? null) : null);\n  const run = (action: () => Promise<void>) => () => {\n    setBusy(true);\n    void action()\n      .catch(() => undefined)\n      .finally(() => setBusy(false));\n  };\n  const home = (\n    <Button type=\"button\" variant=\"outline\" onClick={() => (onLeave !== undefined ? onLeave() : window.location.assign(\"/\"))}>\n      Back to home\n    </Button>\n  );\n\n  let title: string;\n  let line: string | null = null;\n  let cooldownNotice = false;\n  let actions: ReactNode;\n  switch (admission) {\n    case \"waiting_host\":\n      title = \"Waiting for the host to start\";\n      actions = (\n        <Button type=\"button\" variant=\"outline\" disabled={busy} onClick={run(withdraw)}>\n          Leave\n        </Button>\n      );\n      break;\n    case \"denied\":\n      title = \"The host declined your request\";\n      if (reknockLeft !== null && reknockLeft > 0) {\n        line = `You can ask again in ${clockText(reknockLeft)}`;\n        cooldownNotice = true;\n      }\n      actions = (\n        <>\n          {waiting?.reknockAllowed === true || (waiting?.reknockAt != null && reknockLeft === 0) ? (\n            <Button type=\"button\" disabled={busy} onClick={run(askAgain)}>\n              Ask to join again\n            </Button>\n          ) : null}\n          {home}\n        </>\n      );\n      break;\n    case \"expired\":\n      title = \"No one responded\";\n      actions = (\n        <>\n          <Button type=\"button\" disabled={busy} onClick={run(askAgain)}>\n            Ask again\n          </Button>\n          {home}\n        </>\n      );\n      break;\n    case \"withdrawn\":\n      title = \"You left the waiting room\";\n      actions = (\n        <>\n          <Button type=\"button\" disabled={busy} onClick={run(askAgain)}>\n            Rejoin\n          </Button>\n          {home}\n        </>\n      );\n      break;\n    case \"ended\":\n      title = \"The meeting has ended\";\n      actions = home;\n      break;\n    default:\n      title = \"Waiting for the host to let you in\";\n      line = waiting?.admittersPresent === false ? \"The host isn't here yet\" : null;\n      actions = (\n        <Button type=\"button\" variant=\"outline\" disabled={busy} onClick={run(withdraw)}>\n          Cancel request\n        </Button>\n      );\n  }\n\n  return (\n    <div className=\"mx-meet__waiting\">\n      <MeetAvatar name={host.identity.displayName} url={host.identity.avatarUrl} size={72} />\n      <h1 className=\"mx-meet__prejoin-title\">{title}</h1>\n      {phaseNotice === \"sent-to-waiting\" ? (\n        <p className=\"mx-meet__empty-body\" role=\"status\" data-meet-notice=\"sent-to-waiting\">\n          The host moved you back to the waiting room\n        </p>\n      ) : null}\n      {line !== null ? (\n        <p\n          className=\"mx-meet__empty-body\"\n          role=\"status\"\n          data-meet-notice={cooldownNotice ? \"reknock-cooldown\" : \"host-absent\"}\n        >\n          {line}\n        </p>\n      ) : null}\n      {noMicrophone && (admission === \"knocking\" || admission === \"waiting_host\") ? (\n        <p className=\"mx-meet__empty-body\" role=\"status\" data-meet-notice=\"joining-without-microphone\">\n          You&apos;re joining without a microphone. You&apos;ll be able to listen, but others won&apos;t hear you.\n        </p>\n      ) : null}\n      <div className=\"mx-meet__waiting-actions\">{actions}</div>\n    </div>\n  );\n}\n\nexport function HostMenu(): ReactNode {\n  const host = useRequiredMeetHost();\n  const snapshot = useMeetSnapshot();\n  const end = useEndMeeting();\n  // ENDING A MEETING IS DESTRUCTIVE AND IRREVERSIBLE, so the click that does it\n  // names the consequence first — inline, never `window.confirm` (no browser\n  // dialogs).\n  const [confirmingEnd, setConfirmingEnd] = useState(false);\n  const locked = snapshot?.locked === true;\n  return (\n    <div className=\"mx-meet__host-menu\">\n      <button\n        type=\"button\"\n        className=\"mx-meet__link\"\n        onClick={() => {\n          void host.meetings.setLock(!locked);\n        }}\n      >\n        {locked ? \"Unlock meeting\" : \"Lock meeting\"}\n      </button>\n      {/* ENDING IT IS A HOST POWER AND A SERVER DECISION (MRI-A6). The button\n          is real; a server that does not serve the route yet earns a SENTENCE\n          rather than a dead control or a silent no-op. */}\n      {end.canEnd ? (\n        confirmingEnd ? (\n          <span className=\"mx-meet__confirm\" role=\"group\" aria-label=\"End this meeting?\">\n            <span className=\"mx-meet__confirm-text\">\n              End it for everyone? Every participant is disconnected, the note-taker stops, and the\n              wrap-up is written. Nobody can rejoin this meeting afterwards.\n            </span>\n            <button\n              type=\"button\"\n              className=\"mx-meet__link mx-meet__link--danger\"\n              onClick={() => {\n                setConfirmingEnd(false);\n                void end.end();\n              }}\n            >\n              End it\n            </button>\n            <button\n              type=\"button\"\n              className=\"mx-meet__link\"\n              onClick={() => setConfirmingEnd(false)}\n            >\n              Keep it running\n            </button>\n          </span>\n        ) : (\n          <button\n            type=\"button\"\n            className=\"mx-meet__link mx-meet__link--danger\"\n            onClick={() => setConfirmingEnd(true)}\n          >\n            {end.ending ? \"Ending…\" : \"End meeting for everyone\"}\n          </button>\n        )\n      ) : null}\n      {end.notice !== null ? (\n        <span className=\"mx-meet__notice\" role=\"status\">\n          {end.notice}\n        </span>\n      ) : null}\n    </div>\n  );\n}\n\n/** Reactions floating over the stage. Expired by the store, not by hope. */\nexport function ReactionOverlay({\n  reactions,\n}: {\n  reactions: readonly { id: string; emoji: string }[];\n}): ReactNode {\n  if (reactions.length === 0) return null;\n  return (\n    <div className=\"mx-meet__reactions\" aria-hidden=\"true\">\n      {reactions.map((reaction) => (\n        <span key={reaction.id} className=\"mx-meet__reaction\">\n          {reaction.emoji}\n        </span>\n      ))}\n    </div>\n  );\n}\n\nexport type { ParticipantIdentity };\n\n/** `10:35` — the clock a person reads beside a line of transcript. */\nexport function clockOf(iso: string): string {\n  const at = new Date(iso);\n  if (Number.isNaN(at.getTime())) return \"\";\n  return at.toLocaleTimeString(undefined, { hour: \"numeric\", minute: \"2-digit\" });\n}\n\n/**\n * WHAT GUESTS MAY READ OF THIS MEETING — the host's control (MRF-1).\n *\n * 🚨 **HOST-ONLY, AND ABSENT FOR EVERYONE ELSE.** Not grayed out, not present\n * with a tooltip: a participant has no control here at all, because a control\n * that exists only to be refused is the dead-end class this package does not\n * ship (D11-style honesty, same posture as `PersonHostActions`).\n *\n * It is the third rung of the ladder Arman ruled on 2026-09-12 — the system's\n * default, the organization's setting, and this meeting's. \"Use my\n * organization's setting\" is shown WITH what that resolves to, because a label\n * that does not say what the organization chose makes the host guess about\n * other people's words.\n */\nexport function GuestRecordAccessControl({\n  meeting,\n}: {\n  meeting: MeetingRecord;\n}): ReactNode {\n  const host = useMeetHost();\n  const inRoomHost = useIsHost();\n  const access = useGuestRecordAccess(meeting);\n  const viewerId = host?.identity.userId ?? null;\n  // The named host of the row, or a host of the room this tick. A co-host who\n  // holds only an `iam` grant and is not in the room does not see the control;\n  // the server would allow them, so this is the narrow side on purpose — a\n  // missing control is honest, a control that lies about who may click it is not.\n  const isHost = inRoomHost || (viewerId !== null && meeting.hostUserId === viewerId);\n  if (host === null || !isHost) return null;\n\n  const resolved =\n    access.setting === \"default\" && access.effective !== null\n      ? ` Right now that means: ${guestRecordAccessLabel(access.effective.level).toLowerCase()}.`\n      : \"\";\n\n  return (\n    <section className=\"mx-meet__record-section\" aria-label=\"What guests may read\">\n      <h2 className=\"mx-meet__record-section-title\">What guests may read</h2>\n      <label className=\"mx-meet__field\">\n        <span className=\"mx-meet__field-label\">\n          People who attended by link, without an account\n        </span>\n        <ControlSelect\n          aria-label=\"People who attended by link, without an account\"\n          value={access.setting}\n          disabled={access.saving}\n          onValueChange={(next) => {\n            void access.choose(next);\n          }}\n          options={GUEST_RECORD_ACCESS_CHOICES.map((choice) => ({\n            value: choice,\n            label: guestRecordAccessLabel(choice),\n          }))}\n        />\n      </label>\n      <p className=\"mx-meet__panel-note\">\n        {guestRecordAccessExplanation(access.setting)}\n        {resolved}\n      </p>\n      {access.saving ? (\n        <p className=\"mx-meet__panel-note\" role=\"status\">\n          Saving what guests may read…\n        </p>\n      ) : null}\n      {access.error !== null ? (\n        <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={access.error} operation=\"Change who can join\" origin=\"meet/components\">\n          <p className=\"mx-meet__refusal-reason\">{access.error.message}</p>\n          <p className=\"mx-meet__refusal-remedy\">{access.error.remedy}</p>\n        </ErrorBox>\n      ) : null}\n    </section>\n  );\n}\n","/**\n * THE SKIN FACADE — the ONLY module a skin may import (CORE-DESIGN §5.1, §5.4;\n * step S1). Guard: `scripts/check-skin-imports.mjs` (in `check:package` and\n * `pnpm test`): a file under `src/skins/` may import React, the design system,\n * files inside its own skin folder, and THIS module — nothing else.\n *\n * `useMeetCore()` is the facade over today's store: the runtime, the room\n * snapshot, devices, the server's role and the observation-contract reading,\n * as one object that changes only when one of them does. The re-exports below\n * are the headless hooks, pure helpers and types Meet skin v0 (today's in-call\n * UI, moved here unchanged) reads. Later steps (S6a+) replace the re-exports\n * with the `CoreSnapshot` slices and typed actions; a skin then reads\n * `useMeetCore()` alone.\n */\n\nimport { useMemo } from \"react\";\nimport { RETRYABLE_REFUSALS, type MeetPhase } from \"../core/phase\";\nimport type { JoinRequest } from \"../core/room\";\nimport type { ConnectionRegion, ShareRegion } from \"../core/store\";\nimport type { CallInvite } from \"../core/types\";\nimport type { DeviceSnapshot } from \"../core/devices\";\nimport type { MeetObservation } from \"../core/observation\";\nimport { NO_SHARE, type MeetSnapshot } from \"../core/store\";\nimport type { ParticipantRole } from \"../core/types\";\nimport { useCoreObservation } from \"./root\";\nimport { useDeviceSnapshot, useIsHost, useMeetHost, useMeetSnapshot, useRole, type MeetHost } from \"./provider\";\n\nexport interface MeetCore {\n  /** The runtime, or null while auth/organization resolve (render nothing). */\n  readonly host: MeetHost | null;\n  readonly snapshot: MeetSnapshot | null;\n  readonly devices: DeviceSnapshot | null;\n  /** The server's word on this person's role (both carriers, MRI-A11). */\n  readonly role: ParticipantRole;\n  readonly isHost: boolean;\n  /** What the observation contract reads for this tab (S0). */\n  readonly observation: MeetObservation;\n  /**\n   * WHERE THIS TAB IS (CORE-DESIGN §3.1) — the contract's phase value, verbatim. A skin renders\n   * one screen per phase (exhaustive) and NEVER decides a phase itself: every move goes through\n   * `actions`, and the machine refuses any move its table does not allow.\n   */\n  readonly phase: MeetPhase;\n  /** `data-meet-reason` of a refused / terminal phase. */\n  readonly reason: string | null;\n  /** A notice that came with the phase (`sent-to-waiting`), or null. */\n  readonly phaseNotice: string | null;\n  /** The `connection` region (reconnecting is here, never a phase). */\n  readonly connection: ConnectionRegion;\n  /** Show the reconnect banner: the drop outlasted `reconnect_banner_delay_ms` (S6b). */\n  readonly connectionBanner: boolean;\n  /** The `share` region (a refused share is a notice, never a phase). */\n  readonly share: ShareRegion;\n  /** The 1:1 call this tab is placing or answering (§3.6), or null. */\n  readonly call: { readonly invite: CallInvite; readonly direction: \"outgoing\" | \"incoming\" } | null;\n  /** The typed actions. None can move the phase on failure (§5.1). */\n  readonly actions: MeetCoreActions;\n}\n\nexport interface MeetCoreActions {\n  /** Join from pre-join (the person's press). */\n  join(request: JoinRequest): Promise<void>;\n  /** Rejoin from `left` / `disconnected` / `superseded` / `inactive` (the person's press). */\n  rejoin(): Promise<void>;\n  leave(): Promise<void>;\n  /** Back to the device check from `left` / `disconnected` (the person's press). */\n  backToPrejoin(): void;\n  /** Try again on a refusal: the link is looked up again (`refused:*` → `resolving`). */\n  retry(): void;\n  /** The link resolved and the meeting screen mounted (`resolving` → `prejoin`). */\n  resolved(): void;\n  dismissShareNotice(): void;\n  /** Close a finished call's screen (`call_*` / `left` after a call → `resolving`). */\n  dismissCall(): void;\n}\n\nconst NO_ACTIONS: MeetCoreActions = {\n  join: async () => undefined,\n  rejoin: async () => undefined,\n  leave: async () => undefined,\n  backToPrejoin: () => undefined,\n  retry: () => undefined,\n  resolved: () => undefined,\n  dismissShareNotice: () => undefined,\n  dismissCall: () => undefined,\n};\n\nfunction actionsFor(host: MeetHost | null): MeetCoreActions {\n  if (host === null) return NO_ACTIONS;\n  const { engine, store } = host;\n  return {\n    join: (request) => engine.join(request),\n    rejoin: () => engine.rejoin(),\n    leave: () => engine.leave(),\n    backToPrejoin: () => engine.backToPrejoin(),\n    retry: () => {\n      // A refusal that lifts (lock, window, seat) re-asks the gate with the same request — the\n      // person is not sent back through the name and device steps (CORE-DESIGN §11).\n      if (RETRYABLE_REFUSALS.has(store.snapshot().phase)) {\n        void engine.rejoin().catch(() => undefined);\n        return;\n      }\n      store.dispatch({ type: \"retry\", click: true });\n    },\n    resolved: () => {\n      store.dispatch({ type: \"resolved\" });\n    },\n    dismissShareNotice: () => engine.dismissShareNotice(),\n    dismissCall: () => {\n      if (store.dispatch({ type: \"reset\" })) store.patch({ call: null });\n    },\n  };\n}\n\n/** The one headless read a skin starts from. Stable until something moves. */\nexport function useMeetCore(): MeetCore {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const devices = useDeviceSnapshot();\n  const role = useRole();\n  const isHost = useIsHost();\n  const observation = useCoreObservation();\n  const actions = useMemo(() => actionsFor(host), [host]);\n  return useMemo(\n    () => ({\n      host,\n      snapshot,\n      devices,\n      role,\n      isHost,\n      observation,\n      phase: snapshot?.phase ?? \"resolving\",\n      reason: snapshot?.reason ?? null,\n      phaseNotice: snapshot?.phaseNotice ?? null,\n      connection: snapshot?.connection ?? \"stable\",\n      connectionBanner: snapshot?.connectionBanner ?? false,\n      share: snapshot?.share ?? NO_SHARE,\n      call: snapshot?.call ?? null,\n      actions,\n    }),\n    [host, snapshot, devices, role, isHost, observation, actions],\n  );\n}\n\nexport { avatarPaletteIndex, formatDurationMs, getInitials } from \"@ai-matrx/kit/format\";\nexport { OutboundLink } from \"@ai-matrx/kit/outbound-react\";\nexport { fileDownloadPath } from \"../core/api\";\nexport type { MeetFileMedia } from \"../core/api\";\nexport { displayNameFor } from \"../core/names\";\nexport { uniqueAttendees } from \"../core/after\";\nexport { participantSummary } from \"../core/format\";\nexport { gridColumns } from \"../core/layout\";\nexport { meetingLink } from \"../core/meetings\";\nexport { asMeetingId } from \"../core/types\";\nexport type { CallInvite, CallMode, CallablePerson, MeetParticipant, MeetingKind, MeetingRecord, ParticipantIdentity, ParticipantRole, ParticipantStanding, RoomName } from \"../core/types\";\nexport { isLinkFollower, isObserverRole } from \"../core/types\";\n// HR-360 wave 2 (MD-15): the app panel slot.\nexport { useMeetAppPanel } from \"./app-panel\";\nexport { captureHeldOf } from \"../core/app-panel\";\nexport { CAPTION_LANGUAGES, assignedRoom, autoAssign, breakoutClosingMs, breakoutRemainingMs, defaultCaptionLanguage } from \"../core/collab\";\nexport type { CollabPanel, CollabSnapshot, MeetBreakoutPlan, MeetPoll, MeetQuestion, MeetStroke } from \"../core/collab\";\nexport type { UseLobbyResult } from \"./hooks\";\nexport { useCalls, useLeave, useCanModerate, useConsentNotice, useCountdown, useElapsed, useKnockNotice, useEndMeeting, useHostControls, useLivePolicy, useLobby, useWaiting, useLocalMedia, useMediaSupervisor, useMeetAi, useCaptions, useGuestRecordAccess, useMeetingRecord, useMeetings, useRecording, useRoom, useStage, useTrack, useAudioLevel, useHandQueue, useMediaEffects, useModerationNotice, useMeetShortcuts, useReactions, MEET_SHORTCUTS } from \"./hooks\";\nexport type { UseHostControlsResult, UseWaitingResult } from \"./hooks\";\nexport { createCameraPreview, videoEffectsSupported } from \"../core/livekit-driver\";\nexport type { CameraPreview } from \"../core/livekit-driver\";\nexport type { VideoEffect } from \"../core/room-driver\";\nexport type { MediaEffects, MeetWaiting, RoomChatMessage } from \"../core/store\";\nexport { listenOnlyNotice } from \"../core/attendance\";\nexport { groupTranscript, guestRecordAccessExplanation, guestRecordAccessLabel, GUEST_RECORD_ACCESS_CHOICES, hasEnded, meetingWhen, playableRecordingFileId, recordingNotice, absenceSentence, REFUSED_ABSENCE, summarizeMeetingRecordRestrictions, wasRefused, wrapUpStatus } from \"../core/record\";\nexport { isNoteTaker } from \"../core/note-taker\";\nexport { microphoneNoticeCode, participantAttributes } from \"../core/observation\";\nexport { deviceChipLabel, deviceFixSteps, deviceNoticeCode, deviceUnavailableReason } from \"../core/media-supervisor\";\nexport { useDeviceSnapshot, useIsHost, useMeetHost, useMeetSnapshot, useRequiredMeetHost, useRole } from \"./provider\";\nexport type { MeetHost } from \"./provider\";\nexport type { CollabRequest } from \"../core/in-room\";\nexport { setCaptionLanguage, takeMoveRequest } from \"../core/collab-state\";\nexport {\n  useActivityAttention,\n  useAvailableActivities,\n  useCaptionTranslation,\n  useCollab,\n  useCollabPanelRequest,\n} from \"./collab-hooks\";\nexport type { UseCollabResult } from \"./collab-hooks\";\nexport { MEET_REACTIONS } from \"../core/reactions\";\n// S6a: the phase machine's vocabulary, for the skin's exhaustive phase → screen map.\nexport type { MeetPhase } from \"../core/phase\";\nexport { isRefusedPhase } from \"../core/phase\";\nexport type { ConnectionRegion, ShareRegion } from \"../core/store\";\n\nexport type { HostLeavePrompt, LeaveChoice, LeavePolicy } from \"../core/leave\";\nexport { createSpeakingWhileMutedDetector } from \"../core/speaking-detector\";\nexport { detectCapabilities } from \"../core/capabilities\";\n","/**\n * AFTER THE MEETING (Meet wave 3) — the pure pieces every client needs once the\n * room is gone: the attendance report, the transcript and notes as documents,\n * a moment in the transcript as a moment in the recording, search within one\n * transcript, and the two server calls behind the recap email and the saved\n * chat.\n *\n * Nothing here computes MEANING (same rule as `record.ts`): the summary,\n * decisions and action items are the wrap-up's durable rows; this file only\n * arranges, measures and formats them. Every function is framework-free so a\n * worker, a test and a browser produce byte-identical exports.\n */\n\nimport { toDelimited } from \"@ai-matrx/kit/delimited\";\nimport { formatDurationMs } from \"@ai-matrx/kit/format\";\nimport { readRefusalBody, refusalFromResponse } from \"./ai\";\nimport type { MeetApi } from \"./api\";\nimport { MeetError } from \"./errors\";\nimport { displayNameFor, type NameBook } from \"./names\";\nimport type { MeetingRecordBundle } from \"./record\";\nimport { chatFromRow } from \"./room-events\";\nimport type { RoomChatMessage } from \"./store\";\nimport { MEET_ROUTES, meetingPath, MEETING_PASS_HEADER } from \"./tokens\";\nimport type {\n  MeetingAttendee,\n  MeetingId,\n  MeetingNote,\n  MeetingRecord,\n  RecordingRecord,\n  TranscriptSegment,\n} from \"./types\";\n\n/* ─────────────────────────── Attendance ─────────────────────────── */\n\n/**\n * Who someone was, in the words an attendance report uses. `signed-in guest` is\n * an account from outside the meeting's organization that followed the link;\n * `guest` has no account at all.\n */\nexport type AttendanceKind = \"host\" | \"cohost\" | \"member\" | \"signed-in guest\" | \"guest\" | \"assistant\";\n\nexport interface AttendanceRow {\n  readonly id: string;\n  readonly identity: string;\n  readonly name: string;\n  readonly userId: string | null;\n  readonly kind: AttendanceKind;\n  /** First time they were in the room; null when they knocked and never came in. */\n  readonly joinedAt: string | null;\n  /** When they left; null while still in the room or when the leave was never recorded. */\n  readonly leftAt: string | null;\n  /**\n   * Time in the room. A missing `leftAt` is measured to the meeting's end —\n   * the room closed around them — and `null` only when neither is known.\n   */\n  readonly durationMs: number | null;\n  /** True when `durationMs` was measured to the meeting's end, not a recorded leave. */\n  readonly durationToEnd: boolean;\n  readonly admission: MeetingAttendee[\"admissionState\"];\n  /** How many times this person came in (a rejoin or a second device). */\n  readonly joins: number;\n}\n\nfunction kindOf(person: MeetingAttendee): AttendanceKind {\n  if (person.isAgent) return \"assistant\";\n  if (person.role === \"host\") return \"host\";\n  if (person.role === \"cohost\") return \"cohost\";\n  // The durable row stores a link guest as `participant` with no account, so\n  // \"no account\" is what makes someone a guest here — not the role word.\n  if (person.userId === null) return \"guest\";\n  return \"member\";\n}\n\nfunction ms(iso: string | null): number | null {\n  if (iso === null) return null;\n  const at = new Date(iso).getTime();\n  return Number.isNaN(at) ? null : at;\n}\n\n/**\n * The attendance report of ONE meeting, host first then by arrival. People who\n * knocked and were never let in are kept (with no join time) — \"who asked to\n * come in\" is part of the record — but a denied knock has no duration.\n */\n/**\n * WHO a participant row is, as a PERSON (verifier, 2026-09-27: an export listed\n * the same attendee twice under \"attended\"). A signed-in person is their\n * account — every device and every rejoin is one person. A guest without an\n * account gets a fresh `guest:<random>` identity on every join, so the name\n * they typed is the only thread between their joins (Zoom's attendee report\n * merges link guests the same way); two different accountless guests who\n * typed the identical name read as one, which is the lesser error.\n */\nexport function attendeeKey(person: MeetingAttendee, names: NameBook = {}): string {\n  if (person.userId !== null) return `user:${person.userId}`;\n  if (person.isAgent) return `agent:${person.identity}`;\n  const name = displayNameFor(names, person.identity, person.displayName).trim().toLowerCase();\n  return name.length > 0 ? `guest-name:${name}` : `identity:${person.identity}`;\n}\n\n/**\n * One row per PERSON, in first-seen order: the row that actually joined (the\n * earliest) represents them. For a list of names or a head-count; the\n * attendance REPORT merges times as well (`attendanceReport`).\n */\nexport function uniqueAttendees(\n  attendees: readonly MeetingAttendee[],\n  names: NameBook = {},\n): readonly MeetingAttendee[] {\n  const byKey = new Map<string, MeetingAttendee>();\n  for (const person of attendees) {\n    const key = attendeeKey(person, names);\n    const kept = byKey.get(key);\n    if (kept === undefined) {\n      byKey.set(key, person);\n      continue;\n    }\n    const keptJoin = ms(kept.joinedAt);\n    const join = ms(person.joinedAt);\n    if (join !== null && (keptJoin === null || join < keptJoin)) byKey.set(key, person);\n  }\n  return [...byKey.values()];\n}\n\nconst KIND_RANK: Record<AttendanceKind, number> = {\n  host: 0,\n  cohost: 1,\n  member: 2,\n  \"signed-in guest\": 3,\n  guest: 4,\n  assistant: 5,\n};\n\n/** Total time covered by a set of [start, end] intervals — overlaps count once. */\nfunction coveredMs(intervals: readonly (readonly [number, number])[]): number {\n  const sorted = [...intervals].sort((a, b) => a[0] - b[0]);\n  let total = 0;\n  let from = -Infinity;\n  let to = -Infinity;\n  for (const [start, end] of sorted) {\n    if (start > to) {\n      if (to > from) total += to - from;\n      from = start;\n      to = end;\n    } else if (end > to) {\n      to = end;\n    }\n  }\n  if (to > from) total += to - from;\n  return total;\n}\n\nexport function attendanceReport(\n  meeting: MeetingRecord,\n  attendees: readonly MeetingAttendee[],\n  names: NameBook = {},\n): readonly AttendanceRow[] {\n  const end = ms(meeting.endedAt);\n  // EVERY STAY COUNTS (verifier, 2026-09-29: a rejoin overwrote the first join,\n  // so fifty minutes in the room read as ten). A row carries its stays; a row\n  // written before stays were kept is one stay, first join to last leave.\n  const measuredOf = new Map<AttendanceRow, (readonly [number, number])[]>();\n  const perJoin = attendees.map((person): AttendanceRow => {\n    const stays =\n      person.sessions !== undefined && person.sessions.length > 0\n        ? person.sessions.map((stay) => [ms(stay.joinedAt), ms(stay.leftAt)] as const)\n        : [[ms(person.joinedAt), ms(person.leftAt)] as const];\n    let toEnd = false;\n    const measured: (readonly [number, number])[] = [];\n    for (const [joined, left] of stays) {\n      const until = left ?? end;\n      if (joined === null || until === null || until < joined) continue;\n      if (left === null) toEnd = true;\n      measured.push([joined, until]);\n    }\n    const duration = measured.length === 0 ? null : coveredMs(measured);\n    const row: AttendanceRow = {\n      id: person.id,\n      identity: person.identity,\n      name: displayNameFor(names, person.identity, person.displayName),\n      userId: person.userId,\n      kind: kindOf(person),\n      joinedAt: person.joinedAt,\n      leftAt: person.leftAt,\n      durationMs: duration,\n      durationToEnd: duration !== null && toEnd,\n      admission: person.admissionState,\n      joins: Math.max(1, person.sessions?.length ?? 0),\n    };\n    measuredOf.set(row, measured);\n    return row;\n  });\n  // ONE ROW PER PERSON: several joins (a rejoin, a second device) are one\n  // attendee with their first arrival, last departure and total time — time\n  // in the room twice at once counts once.\n  const groups = new Map<string, { rows: AttendanceRow[]; people: MeetingAttendee[] }>();\n  attendees.forEach((person, index) => {\n    const key = attendeeKey(person, names);\n    const group = groups.get(key) ?? { rows: [], people: [] };\n    group.rows.push(perJoin[index]!);\n    group.people.push(person);\n    groups.set(key, group);\n  });\n  const rows = [...groups.values()].map(({ rows: joins }): AttendanceRow => {\n    if (joins.length === 1) return joins[0]!;\n    const came = joins.filter((row) => row.joinedAt !== null);\n    const first =\n      [...came].sort((a, b) => (ms(a.joinedAt) ?? 0) - (ms(b.joinedAt) ?? 0))[0] ?? joins[0]!;\n    const kind = joins.reduce<AttendanceKind>(\n      (best, row) => (KIND_RANK[row.kind] < KIND_RANK[best] ? row.kind : best),\n      first.kind,\n    );\n    const open = came.some((row) => row.leftAt === null);\n    const lastLeave = came.reduce<number | null>((latest, row) => {\n      const left = ms(row.leftAt);\n      return left !== null && (latest === null || left > latest) ? left : latest;\n    }, null);\n    const intervals = came.flatMap((row) => measuredOf.get(row) ?? []);\n    return {\n      ...first,\n      kind,\n      leftAt: open ? null : lastLeave === null ? null : new Date(lastLeave).toISOString(),\n      durationMs: intervals.length === 0 ? null : coveredMs(intervals),\n      durationToEnd: came.some((row) => row.durationToEnd),\n      joins:\n        came.length === 0 ? joins.length : came.reduce((total, row) => total + row.joins, 0),\n    };\n  });\n  const rank = KIND_RANK;\n  return rows.sort((a, b) => {\n    if (rank[a.kind] !== rank[b.kind]) return rank[a.kind] - rank[b.kind];\n    return (ms(a.joinedAt) ?? Number.MAX_SAFE_INTEGER) - (ms(b.joinedAt) ?? Number.MAX_SAFE_INTEGER);\n  });\n}\n\n/** Headline numbers for the top of a report. The assistant is never a person. */\nexport function attendanceTotals(rows: readonly AttendanceRow[]): {\n  readonly people: number;\n  readonly guests: number;\n  readonly neverAdmitted: number;\n  readonly averageMs: number | null;\n} {\n  const humans = rows.filter((row) => row.kind !== \"assistant\");\n  const attended = humans.filter((row) => row.joinedAt !== null);\n  const timed = attended.filter((row) => row.durationMs !== null);\n  return {\n    people: attended.length,\n    guests: attended.filter((row) => row.kind === \"guest\" || row.kind === \"signed-in guest\").length,\n    neverAdmitted: humans.filter((row) => row.joinedAt === null).length,\n    averageMs:\n      timed.length === 0\n        ? null\n        : Math.round(timed.reduce((sum, row) => sum + (row.durationMs ?? 0), 0) / timed.length),\n  };\n}\n\nexport const ATTENDANCE_CSV_HEADER = [\n  \"Meeting\",\n  \"Meeting started\",\n  \"Name\",\n  \"Attended as\",\n  \"Joined\",\n  \"Left\",\n  \"Minutes in the meeting\",\n  \"Admission\",\n] as const;\n\n/**\n * CSV for a spreadsheet: one header row, one row per person, ISO timestamps (a\n * spreadsheet parses them; a formatted local clock loses the zone). Several\n * meetings — a series — concatenate with one header.\n */\nexport function attendanceCsv(\n  reports: readonly { meeting: MeetingRecord; rows: readonly AttendanceRow[] }[],\n): string {\n  // THE one writer (kit `toDelimited`): CRLF records, a trailing CRLF, names formula-guarded.\n  return toDelimited(\n    [\n      ATTENDANCE_CSV_HEADER,\n      ...reports.flatMap(({ meeting, rows }) =>\n        rows.map((row) => [\n          meeting.title,\n          meeting.startedAt ?? meeting.scheduledFor,\n          row.name,\n          row.kind,\n          row.joinedAt,\n          row.leftAt,\n          row.durationMs === null ? null : Math.round(row.durationMs / 6_000) / 10,\n          row.admission,\n        ]),\n      ),\n    ],\n    { lineEnding: \"\\r\\n\", trailingNewline: true },\n  );\n}\n\n/* ───────────────────── A moment in the recording ───────────────────── */\n\n/**\n * Where an instant of the meeting falls in the RECORDING, in milliseconds from\n * its start — or `null` when the recording does not cover it (a recording is\n * often a few minutes of a longer meeting). Never a clamp: seeking a line that\n * was said before recording began to 0:00 would play the wrong words.\n */\nexport function recordingOffsetMs(at: string, recording: RecordingRecord | null): number | null {\n  if (recording === null || recording.state !== \"available\") return null;\n  const start = ms(recording.startedAt);\n  const moment = ms(at);\n  if (start === null || moment === null || moment < start) return null;\n  const end = ms(recording.endedAt);\n  if (end !== null && moment > end) return null;\n  return moment - start;\n}\n\n/** `m:ss` or `h:mm:ss` — a position in a recording or a meeting. */\nexport function clockPosition(offsetMs: number): string {\n  return formatDurationMs(Math.max(0, offsetMs), { style: \"clock\" });\n}\n\n/* ───────────────────── Search within one transcript ───────────────────── */\n\nexport interface TranscriptMatch {\n  readonly segmentId: string;\n  /** [start, end) character ranges inside the segment's text, in order. */\n  readonly ranges: readonly (readonly [number, number])[];\n}\n\n/**\n * Case-insensitive search of the transcript text AND the speaker's\n * name. Returns matches in transcript order. An empty query matches nothing.\n */\nexport function searchTranscript(\n  segments: readonly TranscriptSegment[],\n  query: string,\n  names: NameBook = {},\n): readonly TranscriptMatch[] {\n  const needle = fold(query.trim());\n  if (needle.length === 0) return [];\n  const out: TranscriptMatch[] = [];\n  for (const segment of segments) {\n    const hay = fold(segment.text);\n    const ranges: [number, number][] = [];\n    let from = 0;\n    for (;;) {\n      const at = hay.indexOf(needle, from);\n      if (at < 0) break;\n      ranges.push([at, at + needle.length]);\n      from = at + needle.length;\n    }\n    const speaker = fold(displayNameFor(names, segment.identity, segment.speaker));\n    if (ranges.length > 0 || speaker.includes(needle)) {\n      out.push({ segmentId: segment.id, ranges });\n    }\n  }\n  return out;\n}\n\n/** Lowercase, strip combining marks; length-preserving for the Latin range. */\nfunction fold(value: string): string {\n  return value\n    .normalize(\"NFD\")\n    .replace(/[̀-ͯ]/g, (mark) => (mark.length === 1 ? \"\" : mark))\n    .toLowerCase();\n}\n\n/* ───────────────────────── Documents ───────────────────────── */\n\nexport type TranscriptFormat = \"txt\" | \"md\" | \"vtt\";\n\ninterface ExportOptions {\n  readonly names?: NameBook;\n  /** Timestamps as a clock of day (default) or offsets from `zero`. */\n  readonly locale?: string;\n  readonly timeZone?: string;\n}\n\nfunction clockOfDay(iso: string, options: ExportOptions): string {\n  const at = new Date(iso);\n  if (Number.isNaN(at.getTime())) return \"\";\n  return at.toLocaleTimeString(options.locale, {\n    hour: \"numeric\",\n    minute: \"2-digit\",\n    second: \"2-digit\",\n    ...(options.timeZone !== undefined ? { timeZone: options.timeZone } : {}),\n  });\n}\n\nfunction vttStamp(offsetMs: number): string {\n  const total = Math.max(0, Math.round(offsetMs));\n  const h = Math.floor(total / 3_600_000);\n  const m = Math.floor((total % 3_600_000) / 60_000);\n  const s = Math.floor((total % 60_000) / 1000);\n  const milli = total % 1000;\n  return `${String(h).padStart(2, \"0\")}:${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}.${String(milli).padStart(3, \"0\")}`;\n}\n\n/**\n * The transcript as a document. `txt` and `md` group consecutive lines by one\n * speaker with the clock of day; `vtt` is WebVTT cued from the recording's\n * start when a recording exists (so it plays as captions over it), otherwise\n * from the meeting's start — and a cue ends where the next line begins.\n */\nexport function transcriptDocument(\n  bundle: Pick<MeetingRecordBundle, \"meeting\" | \"transcript\" | \"recording\" | \"names\">,\n  format: TranscriptFormat,\n  options: ExportOptions = {},\n): string {\n  const names = options.names ?? bundle.names;\n  const lines = bundle.transcript.filter((line) => line.text.trim().length > 0);\n  const speaker = (line: TranscriptSegment) => displayNameFor(names, line.identity, line.speaker);\n\n  if (format === \"vtt\") {\n    const zeroIso =\n      bundle.recording?.state === \"available\" && bundle.recording.startedAt !== null\n        ? bundle.recording.startedAt\n        : (bundle.meeting.startedAt ?? lines[0]?.startedAt ?? null);\n    const zero = ms(zeroIso) ?? 0;\n    const cues = [\"WEBVTT\", \"\"];\n    lines.forEach((line, index) => {\n      const start = (ms(line.startedAt) ?? zero) - zero;\n      if (start < 0) return;\n      const next = lines[index + 1];\n      const nextStart = next !== undefined ? (ms(next.startedAt) ?? zero) - zero : start + 4000;\n      const end = Math.max(start + 500, Math.min(nextStart, start + 10_000));\n      cues.push(`${vttStamp(start)} --> ${vttStamp(end)}`);\n      cues.push(`<v ${speaker(line).replace(/[<>]/g, \"\")}>${line.text.replace(/-->/g, \"->\")}`);\n      cues.push(\"\");\n    });\n    return cues.join(\"\\n\");\n  }\n\n  const out: string[] = [];\n  const title = bundle.meeting.title;\n  out.push(format === \"md\" ? `# ${title} — transcript` : `${title} — transcript`);\n  out.push(\"\");\n  let last: string | null = null;\n  for (const line of lines) {\n    if (line.identity !== last) {\n      if (last !== null) out.push(\"\");\n      const who = speaker(line);\n      const clock = clockOfDay(line.startedAt, options);\n      out.push(format === \"md\" ? `**${who}** · ${clock}` : `${who} (${clock})`);\n      last = line.identity;\n    }\n    out.push(line.text.trim());\n  }\n  if (lines.length === 0) out.push(\"No transcript was captured for this meeting.\");\n  return `${out.join(\"\\n\")}\\n`;\n}\n\nfunction bullet(note: MeetingNote): string {\n  const owner = note.assigneeDisplayName !== null ? ` — ${note.assigneeDisplayName}` : \"\";\n  return `- ${note.text.trim()}${owner}`;\n}\n\n/**\n * The meeting's notes as Markdown: when, who attended, the summary, decisions\n * and action items (with owners), and the link back. What a person pastes into\n * a doc or an email; also the source for PDF / Word export.\n */\nexport function notesDocument(\n  bundle: Pick<\n    MeetingRecordBundle,\n    \"meeting\" | \"summary\" | \"decisions\" | \"actionItems\" | \"attendees\" | \"names\"\n  >,\n  options: { readonly link?: string | null; readonly when?: string | null } = {},\n): string {\n  const out: string[] = [`# ${bundle.meeting.title}`, \"\"];\n  if (options.when) out.push(`_${options.when}_`, \"\");\n  // One name per PERSON — a rejoin is not a second attendee.\n  const people = uniqueAttendees(\n    bundle.attendees.filter((person) => !person.isAgent && person.joinedAt !== null),\n    bundle.names,\n  ).map((person) => displayNameFor(bundle.names, person.identity, person.displayName));\n  if (people.length > 0) out.push(`**Attended:** ${people.join(\", \")}`, \"\");\n  out.push(\"## Summary\", \"\", bundle.summary?.text.trim() || \"No summary was written.\", \"\");\n  out.push(\"## Decisions\", \"\");\n  out.push(...(bundle.decisions.length > 0 ? bundle.decisions.map(bullet) : [\"None recorded.\"]), \"\");\n  out.push(\"## Action items\", \"\");\n  out.push(\n    ...(bundle.actionItems.length > 0 ? bundle.actionItems.map(bullet) : [\"None recorded.\"]),\n    \"\",\n  );\n  if (options.link) out.push(`[Open the meeting record](${options.link})`, \"\");\n  return out.join(\"\\n\");\n}\n\n/** How long the meeting ran, in words (\"42 minutes\"), or null when unknown. */\nexport function meetingLength(meeting: MeetingRecord): string | null {\n  const start = ms(meeting.startedAt);\n  const end = ms(meeting.endedAt);\n  if (start === null || end === null || end < start) return null;\n  return formatDurationMs(end - start, { style: \"long\" });\n}\n\n/* ───────────────────────── Saved chat ───────────────────────── */\n\nexport interface MeetingChatHistory {\n  readonly messages: readonly RoomChatMessage[];\n  /** The server's refusal, in its words, when the history could not be read. */\n  readonly refusal: { readonly message: string; readonly remedy: string } | null;\n}\n\n/**\n * The saved chat of a finished meeting (`GET /v1/meet/chat`). Private messages\n * are never saved, by design, so they are never here. A refusal is returned as\n * data — the record still renders everything else.\n */\nexport async function loadMeetingChat(\n  api: MeetApi,\n  meetingId: MeetingId,\n  meetingPass: string | null = null,\n): Promise<MeetingChatHistory> {\n  const operation = \"meet.loadMeetingChat\";\n  let response: Response;\n  try {\n    response = await api.request({\n      path: `${MEET_ROUTES.chat}?meeting_id=${encodeURIComponent(meetingId)}`,\n      method: \"GET\",\n      operation,\n      requireAuth: meetingPass === null,\n      ...(meetingPass !== null ? { headers: { [MEETING_PASS_HEADER]: meetingPass } } : {}),\n    });\n  } catch (error) {\n    return {\n      messages: [],\n      refusal: {\n        message: `The chat could not be read (${(error as Error).message}).`,\n        remedy: (error as { remedy?: string }).remedy ?? \"Reload the page.\",\n      },\n    };\n  }\n  if (!response.ok) {\n    let body: unknown = null;\n    try {\n      body = await response.json();\n    } catch {\n      body = null;\n    }\n    const said = readRefusalBody(body);\n    return {\n      messages: [],\n      refusal: {\n        message: said?.reason ?? `The chat could not be read (the server answered ${response.status}).`,\n        remedy: said?.remedy || \"Reload the page.\",\n      },\n    };\n  }\n  const payload = (await response.json()) as { messages?: unknown };\n  const rows = Array.isArray(payload.messages) ? payload.messages : [];\n  return {\n    messages: rows\n      .map((row) =>\n        typeof row === \"object\" && row !== null ? chatFromRow(row as Record<string, unknown>) : null,\n      )\n      .filter((message): message is RoomChatMessage => message !== null),\n    refusal: null,\n  };\n}\n\n/* ───────────────────────── The recap email ───────────────────────── */\n\n/** One person the recap can go to, as the server resolved them. */\nexport interface FollowUpRecipient {\n  /** Stable key for the choice: `user:<id>` or `email:<address>`. */\n  readonly key: string;\n  readonly name: string;\n  /** The address, when this reader may see it (the host sees their guests'). */\n  readonly email: string | null;\n  readonly userId: string | null;\n  /** `invitee`, `attendee` or both — where the server found them. */\n  readonly sources: readonly (\"invitee\" | \"attendee\")[];\n  /** False when the server has no way to reach them (no account, no address). */\n  readonly reachable: boolean;\n}\n\n/** The draft the host reviews. The text is the wrap-up's own, arranged. */\nexport interface FollowUpDraft {\n  readonly subject: string;\n  readonly body: string;\n  readonly recipients: readonly FollowUpRecipient[];\n  /** False while the wrap-up has not been written — the draft says so. */\n  readonly wrapUpWritten: boolean;\n  /** When a recap for this meeting was last sent, and to how many. */\n  readonly lastSent: { readonly at: string; readonly count: number } | null;\n}\n\nexport interface FollowUpSendResult {\n  readonly dryRun: boolean;\n  /** Recipients the send queued (or, on a dry run, would queue). */\n  readonly queued: readonly string[];\n  /** Recipient keys skipped, each with the reason. */\n  readonly skipped: readonly { readonly key: string; readonly reason: string }[];\n}\n\nfunction refusalOf(response: Response, operation: string): Promise<MeetError> {\n  return refusalFromResponse(response, operation, \"Nothing was sent. Try again.\");\n}\n\nfunction asRecipient(row: Record<string, unknown>): FollowUpRecipient {\n  const sources = Array.isArray(row[\"sources\"]) ? (row[\"sources\"] as string[]) : [];\n  return {\n    key: String(row[\"key\"] ?? \"\"),\n    name: String(row[\"name\"] ?? \"\"),\n    email: typeof row[\"email\"] === \"string\" ? row[\"email\"] : null,\n    userId: typeof row[\"user_id\"] === \"string\" ? row[\"user_id\"] : null,\n    sources: sources.filter((s): s is \"invitee\" | \"attendee\" => s === \"invitee\" || s === \"attendee\"),\n    reachable: row[\"reachable\"] !== false,\n  };\n}\n\n/** The recap draft for a finished meeting. The host, a co-host or an editor. */\nexport async function loadFollowUpDraft(api: MeetApi, meetingId: MeetingId): Promise<FollowUpDraft> {\n  const operation = \"meet.loadFollowUpDraft\";\n  const response = await api.request({\n    path: meetingPath(MEET_ROUTES.meetingFollowUp, meetingId),\n    method: \"GET\",\n    requireAuth: true,\n    operation,\n  });\n  if (!response.ok) throw await refusalOf(response, operation);\n  const body = (await response.json()) as Record<string, unknown>;\n  const last = body[\"last_sent\"] as Record<string, unknown> | null | undefined;\n  return {\n    subject: String(body[\"subject\"] ?? \"\"),\n    body: String(body[\"body\"] ?? \"\"),\n    recipients: (Array.isArray(body[\"recipients\"]) ? body[\"recipients\"] : []).map((row) =>\n      asRecipient(row as Record<string, unknown>),\n    ),\n    wrapUpWritten: body[\"wrap_up_written\"] === true,\n    lastSent:\n      last && typeof last[\"at\"] === \"string\"\n        ? { at: last[\"at\"], count: typeof last[\"count\"] === \"number\" ? last[\"count\"] : 0 }\n        : null,\n  };\n}\n\n/**\n * Send the recap the host reviewed. `dryRun` resolves every recipient and\n * renders every email but queues nothing — how a test proves the path without\n * mailing a real inbox. Never called automatically.\n */\nexport async function sendFollowUp(\n  api: MeetApi,\n  meetingId: MeetingId,\n  input: {\n    readonly subject: string;\n    readonly body: string;\n    readonly recipientKeys: readonly string[];\n    readonly dryRun?: boolean;\n  },\n): Promise<FollowUpSendResult> {\n  const operation = \"meet.sendFollowUp\";\n  const response = await api.request({\n    path: meetingPath(MEET_ROUTES.meetingFollowUp, meetingId),\n    method: \"POST\",\n    requireAuth: true,\n    operation,\n    body: {\n      subject: input.subject,\n      body: input.body,\n      recipient_keys: [...input.recipientKeys],\n      dry_run: input.dryRun === true,\n    },\n  });\n  if (!response.ok) throw await refusalOf(response, operation);\n  const body = (await response.json()) as Record<string, unknown>;\n  return {\n    dryRun: body[\"dry_run\"] === true,\n    queued: Array.isArray(body[\"queued\"]) ? (body[\"queued\"] as string[]) : [],\n    skipped: Array.isArray(body[\"skipped\"])\n      ? (body[\"skipped\"] as Record<string, unknown>[]).map((row) => ({\n          key: String(row[\"key\"] ?? \"\"),\n          reason: String(row[\"reason\"] ?? \"\"),\n        }))\n      : [],\n  };\n}\n","/**\n * PRESENTATION HELPERS specific to a CALL. Pure, tested, and shared by every\n * surface — so a roster line reads the same in the meeting, in the history\n * list, and in the notification.\n *\n * The GENERIC formatters this file used to define — `formatDuration`,\n * `getInitials`, `avatarPaletteIndex` — moved to `@ai-matrx/kit/format` on\n * 2026-09-07 (duplication census H1). They were byte-for-byte duplicated in\n * `@ai-matrx/messaging`, and because two packages claimed them, ~65 host\n * twins across six repos had no correct owner to point at: no surface should\n * take a dependency on the video-calling package to print a duration. Nothing\n * is re-exported from here — import `@ai-matrx/kit/format` directly.\n */\n\nimport type { CallState, MeetParticipant } from \"./types\";\n\n/** \"Ana, Ben and 3 others\" — the roster line, never a raw array join. */\nexport function participantSummary(participants: readonly MeetParticipant[]): string {\n  const names = participants.filter((p) => !p.isLocal).map((p) => p.displayName);\n  if (names.length === 0) return \"Just you\";\n  if (names.length === 1) return names[0] ?? \"\";\n  if (names.length === 2) return `${names[0]} and ${names[1]}`;\n  return `${names[0]}, ${names[1]} and ${names.length - 2} ${names.length - 2 === 1 ? \"other\" : \"others\"}`;\n}\n\n/** What a settled call says in history. One sentence per terminal state. */\nexport function callStateLabel(state: CallState, outgoing: boolean): string {\n  switch (state) {\n    case \"dialing\":\n    case \"ringing\":\n      return outgoing ? \"Calling…\" : \"Incoming call\";\n    case \"connecting\":\n      return \"Connecting…\";\n    case \"active\":\n      return \"In call\";\n    case \"declined\":\n      return outgoing ? \"Declined\" : \"You declined\";\n    case \"missed\":\n      return outgoing ? \"No answer\" : \"Missed call\";\n    case \"busy\":\n      return outgoing ? \"On another call\" : \"You were busy\";\n    case \"cancelled\":\n      return outgoing ? \"Canceled\" : \"Canceled by caller\";\n    case \"ended\":\n      return \"Call ended\";\n    case \"failed\":\n      return \"Call failed\";\n    default:\n      return \"Call\";\n  }\n}\n\n/** \"2 waiting\" for the lobby badge — plural handled once, not per surface. */\nexport function countLabel(count: number, singular: string, plural = `${singular}s`): string {\n  return `${count} ${count === 1 ? singular : plural}`;\n}\n","/**\n * THE APP PANEL SLOT, FOR REACT (HR-360 wave 2, Meet register MD-15).\n *\n * The HOST APP registers its panels — `<MeetAppPanels panels={{ \"hr.review_360\": … }}>` around\n * the meeting — and the skin opens the one the meeting carries (`appPanelOf`) beside the call.\n * Nothing app-specific lives in this package: a panel is a key, a title and a component that\n * reads its record through the viewer's own doors.\n *\n * `useSharedFocus` is the panel's one shared \"current section\": the server keeps it per run\n * and tells the room on the existing collab packet, so every seat moves together.\n */\n\nimport { createContext, useContext, useMemo, type ComponentType, type ReactNode } from \"react\";\nimport { appPanelOf, type MeetingAppPanel } from \"../core/app-panel\";\nimport { performCollab } from \"../core/collab-state\";\nimport { isObserverRole, type MeetingRecord } from \"../core/types\";\nimport { useMeetHost, useMeetSnapshot } from \"./provider\";\n\nexport interface MeetAppPanelProps {\n  /** The record the meeting carries. */\n  readonly recordId: string;\n  /** The meeting's organization — the panel's records are read in it. */\n  readonly organizationId: string;\n  /** The panel's key, e.g. `hr.review_360`. */\n  readonly panelKey: string;\n}\n\nexport interface MeetAppPanelEntry {\n  /** The panel's header title. */\n  readonly title: string;\n  readonly Component: ComponentType<MeetAppPanelProps>;\n}\n\nexport type MeetAppPanelRegistry = Readonly<Record<string, MeetAppPanelEntry>>;\n\nconst RegistryContext = createContext<MeetAppPanelRegistry>({});\n\n/** Register the host app's panels for every meeting rendered inside. */\nexport function MeetAppPanels({\n  panels,\n  children,\n}: {\n  panels: MeetAppPanelRegistry;\n  children: ReactNode;\n}): ReactNode {\n  return <RegistryContext.Provider value={panels}>{children}</RegistryContext.Provider>;\n}\n\nexport function useMeetAppPanelRegistry(): MeetAppPanelRegistry {\n  return useContext(RegistryContext);\n}\n\nexport interface ResolvedMeetAppPanel extends MeetAppPanelEntry {\n  readonly panel: MeetingAppPanel;\n  readonly organizationId: string;\n}\n\n/**\n * The panel this meeting carries AND this app registered, or null. A key the app did not\n * register resolves to null — the slot is absent, never a dead button.\n */\nexport function useMeetAppPanel(meeting?: MeetingRecord | null): ResolvedMeetAppPanel | null {\n  const snapshot = useMeetSnapshot();\n  const registry = useMeetAppPanelRegistry();\n  const record = meeting ?? snapshot?.meeting ?? null;\n  return useMemo(() => {\n    const panel = appPanelOf(record);\n    if (panel === null || record === null) return null;\n    const entry = registry[panel.key];\n    if (entry === undefined) return null;\n    return { ...entry, panel, organizationId: record.organizationId };\n  }, [record, registry]);\n}\n\nexport interface SharedFocus {\n  /** The section everyone is on, or null before anyone moved it. */\n  readonly section: string | null;\n  /** Who moved it last. */\n  readonly byName: string | null;\n  /** False for an observer — they watch, the people in the meeting move the panel. */\n  readonly canMove: boolean;\n  /** Move everyone to `section`. Resolves with the server's sentence or its refusal. */\n  setSection(section: string): Promise<{ ok: boolean; message: string }>;\n}\n\n/** The app panel's one shared section focus (server-kept, on the collab packet). */\nexport function useSharedFocus(panelKey: string): SharedFocus {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const focus = snapshot?.collab.focus ?? null;\n  const mine = focus !== null && focus.panel === panelKey ? focus : null;\n  const canMove = !isObserverRole(snapshot?.grants.role) && snapshot?.phase === \"in_call\";\n  return {\n    section: mine?.section || null,\n    byName: mine?.byName || null,\n    canMove,\n    async setSection(section) {\n      if (host !== null && canMove) {\n        // Move this seat at once; the room packet confirms it for everyone.\n        const collab = host.store.snapshot().collab;\n        host.store.patch({\n          collab: { ...collab, focus: { panel: panelKey, section, byName: host.identity.displayName, at: new Date().toISOString() } },\n        });\n      }\n      return performCollab(host, { action: \"focus_set\", panel: panelKey, section });\n    },\n  };\n}\n","/**\n * COLLAB AND CAPTION LOGIC, HEADLESS (CORE-DESIGN §5.3, step S1).\n *\n * What used to live inside the React hooks of the in-room activities: which\n * activities a person has, when the Activities door deserves a dot, the act /\n * move-to-breakout calls with their sentences, the caption-translation work\n * queue, and the one-shot panel and language requests on the store. Pure or\n * store-shaped, so every skin reads the same answers; the `/react` hooks are\n * thin selectors over these.\n */\n\nimport type { CollabPanel, CollabSnapshot } from \"./collab\";\nimport type { CollabRequest, CollabResult } from \"./in-room\";\nimport type { MeetSnapshot } from \"./store\";\n\n/** The activities this person has, in the order Meet lists them. */\nexport function availableActivities(collab: CollabSnapshot | null, isHost: boolean): CollabPanel[] {\n  const settings = collab?.settings ?? null;\n  if (settings === null) return [];\n  const out: CollabPanel[] = [];\n  if (settings.whiteboardEnabled) out.push(\"whiteboard\");\n  // A participant sees Polls once a poll exists for them; a host always (to create one).\n  if (settings.pollsEnabled && (isHost || (collab?.polls.length ?? 0) > 0)) out.push(\"polls\");\n  if (settings.qaEnabled) out.push(\"qa\");\n  // Breakouts: hosts run them; a participant needs the panel only when rooms are open.\n  if (settings.breakoutsEnabled && (isHost || collab?.breakout?.state === \"open\")) out.push(\"breakouts\");\n  return out;\n}\n\n/** Something worth a dot on the Activities button: a live poll unanswered, a new question for a host. */\nexport function activityAttention(collab: CollabSnapshot | null, isHost: boolean): boolean {\n  if (collab === null) return false;\n  if (collab.polls.some((poll) => poll.state === \"live\" && poll.myVote.length === 0 && !isHost)) return true;\n  if (isHost && collab.questions.some((q) => q.state === \"open\")) return true;\n  return false;\n}\n\nexport interface CollabRuntime {\n  readonly inRoom: { collab(request: CollabRequest): Promise<CollabResult>; loadCollab?(): Promise<void> };\n  readonly engine: { moveToBreakout(roomId: string | null): Promise<unknown> };\n}\n\n/** Perform one act; resolves with the server's sentence, or its refusal (never throws). */\nexport async function performCollab(\n  runtime: CollabRuntime | null,\n  request: CollabRequest,\n): Promise<{ ok: boolean; message: string; itemId?: string | null }> {\n  if (runtime === null) return { ok: false, message: \"This meeting is not connected.\" };\n  try {\n    const result = await runtime.inRoom.collab(request);\n    return { ok: true, message: result.message, itemId: result.itemId };\n  } catch (error) {\n    return { ok: false, message: (error as { message?: string }).message ?? \"That did not work.\" };\n  }\n}\n\n/** Go to a breakout room (`null` = the main room), with the sentence to show. */\nexport async function moveToRoom(\n  runtime: CollabRuntime | null,\n  roomId: string | null,\n): Promise<{ ok: boolean; message: string }> {\n  if (runtime === null) return { ok: false, message: \"This meeting is not connected.\" };\n  try {\n    await runtime.engine.moveToBreakout(roomId);\n    // A room's packets only reach people already in it, so a person arriving mid-countdown (or\n    // returning to the main room) re-reads the plan: they must see the closing countdown too.\n    await runtime.inRoom.loadCollab?.().catch(() => undefined);\n    return { ok: true, message: roomId === null ? \"Back in the main room.\" : \"Joined the breakout room.\" };\n  } catch (error) {\n    return { ok: false, message: (error as { message?: string }).message ?? \"That room could not be joined.\" };\n  }\n}\n\nexport interface CollabStoreLike {\n  snapshot(): MeetSnapshot;\n  patch(next: Partial<MeetSnapshot>): void;\n}\n\n/** Finished caption lines that still need a translation into `language`. */\nexport function untranslatedLines(\n  lines: readonly { id: string; text: string; final: boolean }[],\n  translations: Readonly<Record<string, string>>,\n): { id: string; text: string }[] {\n  return lines\n    .filter((line) => line.final && translations[line.id] === undefined)\n    .map(({ id, text }) => ({ id, text }));\n}\n\n/** The next batch to send: never a line already asked for in this language, at most 20. */\nexport function nextTranslationBatch(\n  pending: readonly { id: string; text: string }[],\n  language: string,\n  asked: Set<string>,\n): { id: string; text: string }[] {\n  const batch = pending.filter((line) => !asked.has(`${language}:${line.id}`)).slice(-20);\n  for (const line of batch) asked.add(`${language}:${line.id}`);\n  return batch;\n}\n\n/** The viewer chose a caption language (or `null` = as spoken): start over in it. */\nexport function setCaptionLanguage(store: CollabStoreLike, next: string | null): void {\n  store.patch({\n    collab: {\n      ...store.snapshot().collab,\n      captionLanguage: next,\n      captionTranslations: {},\n      captionTranslationError: null,\n    },\n  });\n}\n\n/** Take (and clear) the one-shot \"open this panel\" request, if any. */\nexport function takePanelRequest(store: CollabStoreLike): CollabPanel | null {\n  const request = store.snapshot().collab.panelRequest;\n  if (request === null) return null;\n  store.patch({ collab: { ...store.snapshot().collab, panelRequest: null } });\n  return request.panel;\n}\n\n/** Take (and clear) the one-shot \"move to this breakout room\" request, if any. */\nexport function takeMoveRequest(store: CollabStoreLike): { roomId: string | null } | null {\n  const request = store.snapshot().collab.moveRequest;\n  if (request === null) return null;\n  store.patch({ collab: { ...store.snapshot().collab, moveRequest: null } });\n  return { roomId: request.roomId };\n}\n","/**\n * THE COLLAB AND CAPTION HOOKS — thin selectors over the core (CORE-DESIGN\n * §5.3, step S1). The logic lives in `core/collab-state.ts`; these only bind it\n * to the provider's store so every skin gets the same answers.\n */\n\nimport { useEffect, useRef } from \"react\";\nimport type { CollabPanel, CollabSnapshot } from \"../core/collab\";\nimport {\n  activityAttention,\n  availableActivities,\n  moveToRoom,\n  nextTranslationBatch,\n  performCollab,\n  takePanelRequest,\n  untranslatedLines,\n} from \"../core/collab-state\";\nimport type { CollabRequest } from \"../core/in-room\";\nimport { useIsHost, useMeetHost, useMeetSnapshot } from \"./provider\";\n\nexport interface UseCollabResult {\n  readonly collab: CollabSnapshot | null;\n  readonly isHost: boolean;\n  readonly localIdentity: string | null;\n  readonly breakoutRoomId: string | null;\n  /** Perform one act; resolves with the server's sentence, or its refusal (never throws). */\n  act(request: CollabRequest): Promise<{ ok: boolean; message: string; itemId?: string | null }>;\n  /** Go to a breakout room (`null` = the main room). */\n  moveTo(roomId: string | null): Promise<{ ok: boolean; message: string }>;\n}\n\nexport function useCollab(): UseCollabResult {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const isHost = useIsHost();\n  return {\n    collab: snapshot?.collab ?? null,\n    isHost,\n    localIdentity: snapshot?.localIdentity ?? null,\n    breakoutRoomId: snapshot?.breakoutRoomId ?? null,\n    act: (request) => performCollab(host, request),\n    moveTo: (roomId) => moveToRoom(host, roomId),\n  };\n}\n\n/** The activities this person has, in the order Meet lists them. */\nexport function useAvailableActivities(): CollabPanel[] {\n  const { collab, isHost } = useCollab();\n  return availableActivities(collab, isHost);\n}\n\n/** Something worth a dot on the Activities button. */\nexport function useActivityAttention(): boolean {\n  const { collab, isHost } = useCollab();\n  return activityAttention(collab, isHost);\n}\n\n/**\n * The viewer's caption-translation choice and the translator's work queue. Finished\n * lines without a translation are sent in small batches; each line is translated once\n * per language for the whole meeting (server cache).\n */\nexport function useCaptionTranslation(lines: readonly { id: string; text: string; final: boolean }[]): {\n  language: string | null;\n  translations: Readonly<Record<string, string>>;\n  error: string | null;\n} {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const collab = snapshot?.collab ?? null;\n  const language = collab?.captionLanguage ?? null;\n  const asked = useRef<Set<string>>(new Set());\n  const translations = collab?.captionTranslations ?? {};\n  const missing = untranslatedLines(lines, translations);\n  // The batch's identity: the effect below runs when it changes, never per render.\n  const key = `${language ?? \"\"}|${missing.map((l) => l.id).join(\",\")}`;\n  const pending = useRef(missing);\n  pending.current = missing;\n  useEffect(() => {\n    if (host === null || language === null) return;\n    const batch = nextTranslationBatch(pending.current, language, asked.current);\n    if (batch.length === 0) return;\n    void host.inRoom.translateCaptions(language, batch).catch(() => undefined);\n  }, [host, language, key]);\n  return { language, translations, error: collab?.captionTranslationError ?? null };\n}\n\n/** Which collab panel the bar should open, asked by something else (a poll launched). */\nexport function useCollabPanelRequest(onRequest: (panel: CollabPanel) => void): void {\n  const host = useMeetHost();\n  const at = useMeetSnapshot()?.collab.panelRequest?.at ?? null;\n  const callback = useRef(onRequest);\n  callback.current = onRequest;\n  useEffect(() => {\n    if (host === null) return;\n    const panel = takePanelRequest(host.store);\n    if (panel === null) return;\n    callback.current(panel);\n  }, [at, host]);\n}\n","/**\n * The reaction ids every skin offers (CORE-DESIGN §5.3). The id IS the emoji\n * the wire carries; a skin may draw its own art for each, never a different set.\n */\nexport const MEET_REACTIONS: readonly string[] = [\"💖\", \"👍\", \"🎉\", \"👏\", \"😂\", \"😮\", \"😢\", \"🤔\", \"👎\"];\n","/**\n * MS — SPEAKING WHILE MUTED (CORE-DESIGN §11 `speaking-while-muted`). A pure detector fed the local\n * microphone level while the person muted themselves: sound that lasts `holdMs` (gaps shorter than\n * `gapMs` do not break it) fires ONCE, then stays quiet for `cooldownMs` so the nudge never nags.\n * The level source is the platform's (a browser analyzer in the web skin); the rule lives here.\n */\n\nexport interface SpeakingWhileMutedOptions {\n  /** Peak level 0..1 that counts as speech. */\n  readonly threshold?: number;\n  /** How long speech must last before the nudge. */\n  readonly holdMs?: number;\n  /** A pause shorter than this does not end the speech. */\n  readonly gapMs?: number;\n  /** After a nudge, no second one for this long. */\n  readonly cooldownMs?: number;\n}\n\nexport interface SpeakingWhileMutedDetector {\n  /** One level reading at time `at` (ms). True exactly when the nudge should show now. */\n  feed(level: number, at: number): boolean;\n  /** The person unmuted (or left): start over, cooldown included. */\n  reset(): void;\n}\n\nexport function createSpeakingWhileMutedDetector(options: SpeakingWhileMutedOptions = {}): SpeakingWhileMutedDetector {\n  const threshold = options.threshold ?? 0.06;\n  const holdMs = options.holdMs ?? 600;\n  const gapMs = options.gapMs ?? 400;\n  const cooldownMs = options.cooldownMs ?? 20_000;\n  let speechStart: number | null = null;\n  let lastLoud: number | null = null;\n  let firedAt: number | null = null;\n  return {\n    feed(level, at) {\n      if (level >= threshold) {\n        if (speechStart === null || lastLoud === null || at - lastLoud > gapMs) speechStart = at;\n        lastLoud = at;\n      } else if (lastLoud !== null && at - lastLoud > gapMs) {\n        speechStart = null;\n        lastLoud = null;\n      }\n      if (speechStart === null || at - speechStart < holdMs) return false;\n      if (firedAt !== null && at - firedAt < cooldownMs) return false;\n      firedAt = at;\n      speechStart = null;\n      lastLoud = null;\n      return true;\n    },\n    reset() {\n      speechStart = null;\n      lastLoud = null;\n      firedAt = null;\n    },\n  };\n}\n","\"use client\";\n\n/**\n * POLLS, Q&A, THE SHARED WHITEBOARD AND BREAKOUT ROOMS — the in-room surfaces (Meet wave 5).\n *\n * Every act goes to the server (`host.inRoom.collab`), which decides who may do it and\n * what each person sees; these components render what the store holds and say the\n * server's sentence when it refuses. A control exists only when the organization's knob\n * turns it on (`collab.settings`) — absent, never dead.\n *\n * The champions: Google Meet's Activities panel (one door to polls, Q&A, whiteboard and\n * breakouts) and Zoom's breakout-room controls (automatic / manual / let people choose,\n * timer, broadcast, move, bring everyone back).\n */\n\nimport { Select } from \"@ai-matrx/design-system/controls\";\nimport { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent, type ReactNode } from \"react\";\nimport { CAPTION_LANGUAGES, type CollabPanel, type MeetBreakoutPlan, type MeetPoll, type MeetQuestion, type MeetStroke, assignedRoom, autoAssign, breakoutClosingMs, breakoutRemainingMs, defaultCaptionLanguage, displayNameFor, formatDurationMs, useCaptions, useMeetAi, useMeetHost, useMeetSnapshot, setCaptionLanguage, takeMoveRequest, useActivityAttention, useAvailableActivities, useCollab } from \"../../react/facade\";\n\nimport { ControlButton, MenuItem, PanelShell, Popover } from \"./components\";\nimport { ActivitiesIcon, BreakoutIcon, CaptionsIcon, NotesIcon, EraserIcon, HighlighterIcon, PollIcon, QuestionIcon, UndoIcon, UpvoteIcon, WhiteboardIcon } from \"./icons\";\nimport { PencilIcon, XIcon } from \"@ai-matrx/design-system/icons\";\n\nfunction useNotice(): [\n  { text: string; failed: boolean } | null,\n  (result: { ok: boolean; message: string }) => void,\n] {\n  const [notice, setNotice] = useState<{ text: string; failed: boolean } | null>(null);\n  useEffect(() => {\n    if (notice === null) return undefined;\n    const timer = setTimeout(() => setNotice(null), notice.failed ? 7000 : 3000);\n    return () => clearTimeout(timer);\n  }, [notice]);\n  return [notice, (result) => setNotice({ text: result.message, failed: !result.ok })];\n}\n\nfunction Notice({ notice }: { notice: { text: string; failed: boolean } | null }): ReactNode {\n  if (notice === null) return null;\n  return (\n    <p className={notice.failed ? \"mx-meet__panel-note mx-meet__collab-error\" : \"mx-meet__panel-note\"} role=\"status\">\n      {notice.text}\n    </p>\n  );\n}\n\n// ── the Activities control ─────────────────────────────────────────────────\n\nconst ACTIVITY_LABELS: Record<CollabPanel, string> = {\n  polls: \"Polls\",\n  qa: \"Q&A\",\n  whiteboard: \"Whiteboard\",\n  breakouts: \"Breakout rooms\",\n};\n\nfunction ActivityIcon({ panel }: { panel: CollabPanel }): ReactNode {\n  const props = { width: 16, height: 16 };\n  if (panel === \"polls\") return <PollIcon {...props} />;\n  if (panel === \"qa\") return <QuestionIcon {...props} />;\n  if (panel === \"whiteboard\") return <WhiteboardIcon {...props} />;\n  return <BreakoutIcon {...props} />;\n}\n\nexport function ActivitiesControl({\n  active,\n  onOpen,\n}: {\n  active: CollabPanel | null;\n  onOpen: (panel: CollabPanel) => void;\n}): ReactNode {\n  const [open, setOpen] = useState(false);\n  const available = useAvailableActivities();\n  const attention = useActivityAttention();\n  if (available.length === 0) return null;\n  return (\n    <span className=\"mx-meet__anchor\">\n      <ControlButton label=\"Activities\" active={open || active !== null} onClick={() => setOpen(!open)}>\n        <ActivitiesIcon />\n        {attention ? <span className=\"mx-meet__dot\" aria-hidden=\"true\" /> : null}\n      </ControlButton>\n      {open ? (\n        <Popover label=\"Activities\" onClose={() => setOpen(false)}>\n          <div className=\"mx-meet__menu\" role=\"menu\">\n            {available.map((panel) => (\n              <MenuItem\n                key={panel}\n                onSelect={() => {\n                  setOpen(false);\n                  onOpen(panel);\n                }}\n              >\n                <ActivityIcon panel={panel} /> {ACTIVITY_LABELS[panel]}\n              </MenuItem>\n            ))}\n          </div>\n        </Popover>\n      ) : null}\n    </span>\n  );\n}\n\n// ── polls ──────────────────────────────────────────────────────────────────\n\nfunction PollComposer({ maxOptions, onDone }: { maxOptions: number; onDone: () => void }): ReactNode {\n  const { act } = useCollab();\n  const [question, setQuestion] = useState(\"\");\n  const [options, setOptions] = useState<string[]>([\"\", \"\"]);\n  const [multiple, setMultiple] = useState(false);\n  const [anonymous, setAnonymous] = useState(false);\n  const [busy, setBusy] = useState(false);\n  const [notice, show] = useNotice();\n  const filled = options.map((o) => o.trim()).filter(Boolean);\n  const ready = question.trim().length > 0 && filled.length >= 2;\n\n  const save = async (launch: boolean) => {\n    setBusy(true);\n    const created = await act({ action: \"poll_create\", question, options: filled, multiple, anonymous });\n    if (!created.ok) {\n      show(created);\n      setBusy(false);\n      return;\n    }\n    if (launch && created.itemId != null) {\n      const launched = await act({ action: \"poll_launch\", itemId: created.itemId });\n      if (!launched.ok) {\n        show(launched);\n        setBusy(false);\n        return;\n      }\n    }\n    setBusy(false);\n    onDone();\n  };\n\n  return (\n    <form\n      className=\"mx-meet__collab-card\"\n      onSubmit={(event) => {\n        event.preventDefault();\n        if (ready) void save(true);\n      }}\n    >\n      <label className=\"mx-meet__field\">\n        <span className=\"mx-meet__field-label\">Question</span>\n        <input\n          className=\"mx-meet__input\"\n          value={question}\n          maxLength={1000}\n          onChange={(event) => setQuestion(event.target.value)}\n          placeholder=\"Ask the room something\"\n          autoFocus\n        />\n      </label>\n      {options.map((option, index) => (\n        <div className=\"mx-meet__composer-row\" key={index}>\n          <input\n            className=\"mx-meet__input\"\n            value={option}\n            maxLength={200}\n            aria-label={`Answer ${index + 1}`}\n            placeholder={`Answer ${index + 1}`}\n            onChange={(event) => setOptions(options.map((o, i) => (i === index ? event.target.value : o)))}\n          />\n          {options.length > 2 ? (\n            <ControlButton label={`Remove answer ${index + 1}`} onClick={() => setOptions(options.filter((_, i) => i !== index))}>\n              <XIcon strokeWidth={1.75} width={14} height={14} />\n            </ControlButton>\n          ) : null}\n        </div>\n      ))}\n      {options.length < maxOptions ? (\n        <button type=\"button\" className=\"mx-meet__link\" onClick={() => setOptions([...options, \"\"])}>\n          Add an answer\n        </button>\n      ) : null}\n      <label className=\"mx-meet__toggle\">\n        <input type=\"checkbox\" checked={multiple} onChange={(event) => setMultiple(event.target.checked)} />\n        People can pick more than one\n      </label>\n      <label className=\"mx-meet__toggle\">\n        <input type=\"checkbox\" checked={anonymous} onChange={(event) => setAnonymous(event.target.checked)} />\n        Anonymous — nobody sees who picked what\n      </label>\n      <Notice notice={notice} />\n      <div className=\"mx-meet__collab-actions\">\n        <button type=\"submit\" className=\"mx-meet__primary mx-meet__primary--small\" disabled={!ready || busy}>\n          Launch\n        </button>\n        <button type=\"button\" className=\"mx-meet__chip\" disabled={!ready || busy} onClick={() => void save(false)}>\n          Save draft\n        </button>\n        <button type=\"button\" className=\"mx-meet__link\" onClick={onDone}>\n          Cancel\n        </button>\n      </div>\n    </form>\n  );\n}\n\nfunction PollCard({ poll }: { poll: MeetPoll }): ReactNode {\n  const { act, isHost } = useCollab();\n  const [picked, setPicked] = useState<string[]>(poll.myVote.slice());\n  const [notice, show] = useNotice();\n  useEffect(() => setPicked(poll.myVote.slice()), [poll.myVote]);\n  const counts = poll.options.some((o) => o.votes !== undefined);\n  const total = poll.options.reduce((sum, o) => sum + (o.votes ?? 0), 0);\n  const canVote = poll.state === \"live\";\n  const voted = poll.myVote.length > 0;\n  const stateWord =\n    poll.state === \"draft\" ? \"Draft\" : poll.state === \"live\" ? \"Open\" : \"Closed\";\n\n  const toggle = (id: string) => {\n    if (!canVote) return;\n    setPicked(poll.multiple ? (picked.includes(id) ? picked.filter((p) => p !== id) : [...picked, id]) : [id]);\n  };\n\n  return (\n    <article className=\"mx-meet__collab-card\" aria-label={poll.question}>\n      <header className=\"mx-meet__collab-head\">\n        <strong className=\"mx-meet__collab-title\">{poll.question}</strong>\n        <span className=\"mx-meet__collab-state\">{stateWord}</span>\n      </header>\n      <p className=\"mx-meet__panel-note\">\n        {poll.multiple ? \"Pick any.\" : \"Pick one.\"}\n        {poll.anonymous ? \" Anonymous.\" : \"\"}\n        {counts && poll.voterCount !== null ? ` ${poll.voterCount} voted.` : \"\"}\n        {isHost && poll.state !== \"draft\" && !poll.resultsShared ? \" Results are visible only to hosts.\" : \"\"}\n      </p>\n      <ul className=\"mx-meet__poll-options\">\n        {poll.options.map((option) => {\n          const share = counts && total > 0 ? Math.round(((option.votes ?? 0) / total) * 100) : 0;\n          const chosen = picked.includes(option.id);\n          return (\n            <li key={option.id}>\n              <button\n                type=\"button\"\n                className={chosen ? \"mx-meet__poll-option mx-meet__poll-option--chosen\" : \"mx-meet__poll-option\"}\n                aria-pressed={chosen}\n                disabled={!canVote}\n                onClick={() => toggle(option.id)}\n              >\n                {counts ? <span className=\"mx-meet__poll-bar\" style={{ width: `${share}%` }} aria-hidden=\"true\" /> : null}\n                <span className=\"mx-meet__poll-text\">{option.text}</span>\n                {counts ? (\n                  <span className=\"mx-meet__poll-count\">\n                    {option.votes ?? 0} · {share}%\n                  </span>\n                ) : null}\n              </button>\n              {option.voters !== undefined && option.voters.length > 0 ? (\n                <span className=\"mx-meet__poll-voters\">{option.voters.join(\", \")}</span>\n              ) : null}\n            </li>\n          );\n        })}\n      </ul>\n      <Notice notice={notice} />\n      <div className=\"mx-meet__collab-actions\">\n        {canVote ? (\n          <button\n            type=\"button\"\n            className=\"mx-meet__primary mx-meet__primary--small\"\n            disabled={picked.length === 0 || (voted && picked.join() === poll.myVote.join())}\n            onClick={() => void act({ action: \"poll_vote\", itemId: poll.id, optionIds: picked }).then(show)}\n          >\n            {voted ? \"Change vote\" : \"Vote\"}\n          </button>\n        ) : null}\n        {isHost && poll.state === \"draft\" ? (\n          <button type=\"button\" className=\"mx-meet__primary mx-meet__primary--small\" onClick={() => void act({ action: \"poll_launch\", itemId: poll.id }).then(show)}>\n            Launch\n          </button>\n        ) : null}\n        {isHost && poll.state === \"live\" ? (\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void act({ action: \"poll_close\", itemId: poll.id }).then(show)}>\n            End poll\n          </button>\n        ) : null}\n        {isHost && poll.state !== \"draft\" ? (\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void act({ action: \"poll_share\", itemId: poll.id }).then(show)}>\n            {poll.resultsShared ? \"Hide results\" : \"Share results\"}\n          </button>\n        ) : null}\n        {isHost && poll.state === \"live\" ? null : isHost ? (\n          <button type=\"button\" className=\"mx-meet__link\" onClick={() => void act({ action: \"poll_delete\", itemId: poll.id }).then(show)}>\n            Delete\n          </button>\n        ) : null}\n      </div>\n    </article>\n  );\n}\n\nexport function PollsPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const { collab, isHost } = useCollab();\n  const [composing, setComposing] = useState(false);\n  const polls = collab?.polls ?? [];\n  const maxOptions = collab?.settings?.pollMaxOptions ?? 10;\n  // Newest first: the poll that just launched is the one people are looking for.\n  const ordered = [...polls].reverse();\n  return (\n    <PanelShell title=\"Polls\" onClose={onClose}>\n      {collab?.error != null ? <p className=\"mx-meet__panel-note mx-meet__collab-error\">{collab.error}</p> : null}\n      {isHost && !composing ? (\n        <button type=\"button\" className=\"mx-meet__primary mx-meet__primary--small\" onClick={() => setComposing(true)}>\n          New poll\n        </button>\n      ) : null}\n      {isHost && composing ? <PollComposer maxOptions={maxOptions} onDone={() => setComposing(false)} /> : null}\n      {ordered.length === 0 && !composing ? (\n        <p className=\"mx-meet__panel-note\">\n          {isHost ? \"No polls yet. Polls and their results are kept with the meeting.\" : \"No polls yet.\"}\n        </p>\n      ) : null}\n      {ordered.map((poll) => (\n        <PollCard key={poll.id} poll={poll} />\n      ))}\n    </PanelShell>\n  );\n}\n\n// ── Q&A ────────────────────────────────────────────────────────────────────\n\nfunction QuestionCard({ question }: { question: MeetQuestion }): ReactNode {\n  const { act, isHost } = useCollab();\n  const [answering, setAnswering] = useState(false);\n  const [reply, setReply] = useState(\"\");\n  const [notice, show] = useNotice();\n  return (\n    <li className={`mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`}>\n      <div className=\"mx-meet__question-row\">\n        <button\n          type=\"button\"\n          className={question.upvotedByMe ? \"mx-meet__upvote mx-meet__upvote--on\" : \"mx-meet__upvote\"}\n          aria-pressed={question.upvotedByMe}\n          aria-label={question.upvotedByMe ? \"Remove your upvote\" : \"Upvote\"}\n          disabled={question.state === \"dismissed\"}\n          onClick={() => void act({ action: \"question_upvote\", itemId: question.id }).then((r) => (r.ok ? undefined : show(r)))}\n        >\n          <UpvoteIcon width={16} height={16} />\n          <span>{question.upvotes}</span>\n        </button>\n        <div className=\"mx-meet__question-body\">\n          <span className=\"mx-meet__chat-meta\">\n            <strong>{question.mine ? \"You\" : question.askerName}</strong>\n            {question.mine && question.anonymous ? <span className=\"mx-meet__chat-private\">anonymous</span> : null}\n            {question.state !== \"open\" ? (\n              <span className=\"mx-meet__collab-state\">{question.state === \"answered\" ? \"Answered\" : \"Dismissed\"}</span>\n            ) : null}\n          </span>\n          <span className=\"mx-meet__chat-text\">{question.text}</span>\n          {question.answer !== null ? (\n            <span className=\"mx-meet__question-answer\">\n              <strong>{question.answeredByName ?? \"Host\"}:</strong> {question.answer}\n            </span>\n          ) : null}\n        </div>\n      </div>\n      {answering ? (\n        <form\n          className=\"mx-meet__composer-row\"\n          onSubmit={(event) => {\n            event.preventDefault();\n            void act({ action: \"question_answer\", itemId: question.id, text: reply }).then((r) => {\n              show(r);\n              if (r.ok) {\n                setAnswering(false);\n                setReply(\"\");\n              }\n            });\n          }}\n        >\n          <input\n            className=\"mx-meet__input\"\n            value={reply}\n            maxLength={2000}\n            onChange={(event) => setReply(event.target.value)}\n            placeholder=\"Type an answer, or leave empty if you answered out loud\"\n            aria-label=\"Answer\"\n            autoFocus\n          />\n          <button type=\"submit\" className=\"mx-meet__send\">\n            Done\n          </button>\n        </form>\n      ) : null}\n      <Notice notice={notice} />\n      {isHost || question.mine ? (\n        <div className=\"mx-meet__collab-actions\">\n          {isHost && question.state === \"open\" && !answering ? (\n            <button type=\"button\" className=\"mx-meet__chip\" onClick={() => setAnswering(true)}>\n              Answer\n            </button>\n          ) : null}\n          {isHost && question.state === \"open\" ? (\n            <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void act({ action: \"question_dismiss\", itemId: question.id }).then(show)}>\n              Dismiss\n            </button>\n          ) : null}\n          {isHost && question.state !== \"open\" ? (\n            <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void act({ action: \"question_reopen\", itemId: question.id }).then(show)}>\n              Reopen\n            </button>\n          ) : null}\n          {question.mine || isHost ? (\n            <button type=\"button\" className=\"mx-meet__link\" onClick={() => void act({ action: \"question_delete\", itemId: question.id }).then(show)}>\n              Delete\n            </button>\n          ) : null}\n        </div>\n      ) : null}\n    </li>\n  );\n}\n\nexport function QaPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const { collab, act } = useCollab();\n  const [draft, setDraft] = useState(\"\");\n  const [anonymous, setAnonymous] = useState(false);\n  const [order, setOrder] = useState<\"popular\" | \"recent\">(\"popular\");\n  const [notice, show] = useNotice();\n  const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;\n  const questions = [...(collab?.questions ?? [])];\n  const rank = (q: MeetQuestion) => (q.state === \"open\" ? 0 : q.state === \"answered\" ? 1 : 2);\n  questions.sort((a, b) =>\n    rank(a) !== rank(b)\n      ? rank(a) - rank(b)\n      : order === \"popular\"\n        ? b.upvotes - a.upvotes || (b.createdAt ?? \"\").localeCompare(a.createdAt ?? \"\")\n        : (b.createdAt ?? \"\").localeCompare(a.createdAt ?? \"\"),\n  );\n  return (\n    <PanelShell title=\"Q&A\" onClose={onClose}>\n      {collab?.error != null ? <p className=\"mx-meet__panel-note mx-meet__collab-error\">{collab.error}</p> : null}\n      <form\n        className=\"mx-meet__composer mx-meet__composer--chat\"\n        onSubmit={(event) => {\n          event.preventDefault();\n          const text = draft.trim();\n          if (text.length === 0) return;\n          void act({ action: \"question_ask\", text, anonymous: allowAnonymous && anonymous }).then((r) => {\n            if (r.ok) setDraft(\"\");\n            else show(r);\n          });\n        }}\n      >\n        <div className=\"mx-meet__composer-row\">\n          <input\n            className=\"mx-meet__input\"\n            value={draft}\n            maxLength={1000}\n            onChange={(event) => setDraft(event.target.value)}\n            placeholder=\"Ask the host a question\"\n            aria-label=\"Ask the host a question\"\n          />\n          <button type=\"submit\" className=\"mx-meet__send\" disabled={draft.trim().length === 0}>\n            Ask\n          </button>\n        </div>\n        {allowAnonymous ? (\n          <label className=\"mx-meet__toggle\">\n            <input type=\"checkbox\" checked={anonymous} onChange={(event) => setAnonymous(event.target.checked)} />\n            Ask anonymously\n          </label>\n        ) : null}\n      </form>\n      <Notice notice={notice} />\n      {questions.length > 1 ? (\n        <div className=\"mx-meet__pills\" role=\"group\" aria-label=\"Order questions\">\n          {([\"popular\", \"recent\"] as const).map((value) => (\n            <button\n              key={value}\n              type=\"button\"\n              className={order === value ? \"mx-meet__pill mx-meet__pill--on\" : \"mx-meet__pill\"}\n              aria-pressed={order === value}\n              onClick={() => setOrder(value)}\n            >\n              {value === \"popular\" ? \"Popular\" : \"Recent\"}\n            </button>\n          ))}\n        </div>\n      ) : null}\n      {questions.length === 0 ? (\n        <p className=\"mx-meet__panel-note\">No questions yet. Questions are kept with the meeting.</p>\n      ) : (\n        <ul className=\"mx-meet__chat\">\n          {questions.map((question) => (\n            <QuestionCard key={question.id} question={question} />\n          ))}\n        </ul>\n      )}\n    </PanelShell>\n  );\n}\n\n// ── the shared whiteboard ──────────────────────────────────────────────────\n\nconst BOARD_W = 1600;\nconst BOARD_H = 1000;\nconst INK = [\"#111827\", \"#dc2626\", \"#2563eb\", \"#16a34a\", \"#f59e0b\", \"#7c3aed\"];\n\ntype Tool = \"pen\" | \"highlighter\" | \"eraser\";\n\nfunction strokePath(points: readonly (readonly [number, number])[]): string {\n  if (points.length === 0) return \"\";\n  const [first, ...rest] = points;\n  const move = `M${(first![0] * BOARD_W).toFixed(1)} ${(first![1] * BOARD_H).toFixed(1)}`;\n  if (rest.length === 0) return `${move} l0.1 0`;\n  return `${move} ${rest.map(([x, y]) => `L${(x * BOARD_W).toFixed(1)} ${(y * BOARD_H).toFixed(1)}`).join(\" \")}`;\n}\n\nfunction StrokeView({ stroke, onPick }: { stroke: MeetStroke; onPick?: (() => void) | undefined }): ReactNode {\n  return (\n    <path\n      d={strokePath(stroke.points)}\n      fill=\"none\"\n      stroke={stroke.color}\n      strokeWidth={stroke.tool === \"highlighter\" ? stroke.width * 4 : stroke.width}\n      strokeOpacity={stroke.tool === \"highlighter\" ? 0.35 : stroke.pending === true ? 0.6 : 1}\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      onPointerDown={onPick}\n      style={onPick !== undefined ? { cursor: \"pointer\" } : undefined}\n    >\n      <title>{stroke.byName}</title>\n    </path>\n  );\n}\n\n/**\n * THE SHARED WHITEBOARD — one board per meeting, everyone draws, it is saved with the\n * meeting (every stroke is a room item). Replaces the stage while open, the way Zoom's\n * whiteboard does; the control bar stays.\n */\nexport function WhiteboardPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const { collab, act, isHost, localIdentity } = useCollab();\n  const [tool, setTool] = useState<Tool>(\"pen\");\n  const [color, setColor] = useState(INK[0]!);\n  const [drawing, setDrawing] = useState<[number, number][] | null>(null);\n  const [pending, setPending] = useState<MeetStroke[]>([]);\n  const [notice, show] = useNotice();\n  const svgRef = useRef<SVGSVGElement | null>(null);\n  const strokes = collab?.strokes ?? [];\n  const mine = strokes.filter((s) => s.by === localIdentity);\n\n  const point = (event: ReactPointerEvent<SVGSVGElement>): [number, number] | null => {\n    const svg = svgRef.current;\n    if (svg === null) return null;\n    const rect = svg.getBoundingClientRect();\n    // The board keeps its 16:10 shape inside whatever box it gets (xMidYMid meet).\n    const scale = Math.min(rect.width / BOARD_W, rect.height / BOARD_H);\n    const offsetX = (rect.width - BOARD_W * scale) / 2;\n    const offsetY = (rect.height - BOARD_H * scale) / 2;\n    const x = (event.clientX - rect.left - offsetX) / (BOARD_W * scale);\n    const y = (event.clientY - rect.top - offsetY) / (BOARD_H * scale);\n    return [Math.min(1, Math.max(0, x)), Math.min(1, Math.max(0, y))];\n  };\n\n  const finish = () => {\n    const points = drawing;\n    setDrawing(null);\n    if (points === null || points.length === 0 || tool === \"eraser\") return;\n    // Thin the stroke: a point every ~2px of board is plenty and keeps rows small.\n    const thinned = points.filter((p, i) => i === 0 || i === points.length - 1 || i % 2 === 0).slice(0, 2000);\n    const stroke = {\n      points: thinned.map(([x, y]) => [Number(x.toFixed(4)), Number(y.toFixed(4))] as [number, number]),\n      color,\n      width: tool === \"highlighter\" ? 4 : 3,\n      tool: tool === \"highlighter\" ? (\"highlighter\" as const) : (\"pen\" as const),\n    };\n    const localId = `pending-${Date.now()}`;\n    setPending((list) => [...list, { id: localId, ...stroke, by: localIdentity ?? \"\", byName: \"You\", pending: true }]);\n    void act({ action: \"stroke_add\", stroke }).then((result) => {\n      setPending((list) => list.filter((s) => s.id !== localId));\n      if (!result.ok) show(result);\n    });\n  };\n\n  return (\n    <section className=\"mx-meet__whiteboard\" aria-label=\"Whiteboard\">\n      <header className=\"mx-meet__whiteboard-bar\">\n        <strong className=\"mx-meet__panel-title\">Whiteboard</strong>\n        <div className=\"mx-meet__pills\" role=\"group\" aria-label=\"Tool\">\n          {(\n            [\n              [\"pen\", \"Pen\", <PencilIcon strokeWidth={1.75} key=\"p\" width={16} height={16} />],\n              [\"highlighter\", \"Highlighter\", <HighlighterIcon key=\"h\" width={16} height={16} />],\n              [\"eraser\", \"Eraser — click a stroke\", <EraserIcon key=\"e\" width={16} height={16} />],\n            ] as const\n          ).map(([value, label, icon]) => (\n            <button\n              key={value}\n              type=\"button\"\n              className={tool === value ? \"mx-meet__pill mx-meet__pill--on\" : \"mx-meet__pill\"}\n              aria-pressed={tool === value}\n              aria-label={label}\n              title={label}\n              onClick={() => setTool(value)}\n            >\n              {icon}\n            </button>\n          ))}\n        </div>\n        <div className=\"mx-meet__swatches\" role=\"group\" aria-label=\"Color\">\n          {INK.map((ink) => (\n            <button\n              key={ink}\n              type=\"button\"\n              className={ink === color ? \"mx-meet__swatch mx-meet__swatch--on\" : \"mx-meet__swatch\"}\n              style={{ background: ink }}\n              aria-label={`Color ${ink}`}\n              aria-pressed={ink === color}\n              onClick={() => {\n                setColor(ink);\n                if (tool === \"eraser\") setTool(\"pen\");\n              }}\n            />\n          ))}\n        </div>\n        <ControlButton\n          label=\"Undo my last stroke\"\n          onClick={() => {\n            const last = mine[mine.length - 1];\n            if (last !== undefined) void act({ action: \"stroke_erase\", itemId: last.id }).then((r) => (r.ok ? undefined : show(r)));\n          }}\n        >\n          <UndoIcon width={16} height={16} />\n        </ControlButton>\n        {isHost && strokes.length > 0 ? (\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void act({ action: \"whiteboard_clear\" }).then(show)}>\n            Clear board\n          </button>\n        ) : null}\n        <span className=\"mx-meet__whiteboard-note\">Saved with the meeting</span>\n        <ControlButton label=\"Close whiteboard\" onClick={onClose}>\n          <XIcon strokeWidth={1.75} width={16} height={16} />\n        </ControlButton>\n      </header>\n      <Notice notice={notice} />\n      <svg\n        ref={svgRef}\n        className={tool === \"eraser\" ? \"mx-meet__board mx-meet__board--erase\" : \"mx-meet__board\"}\n        viewBox={`0 0 ${BOARD_W} ${BOARD_H}`}\n        preserveAspectRatio=\"xMidYMid meet\"\n        role=\"img\"\n        aria-label={`Shared whiteboard, ${strokes.length} strokes`}\n        onPointerDown={(event) => {\n          if (tool === \"eraser\") return;\n          const p = point(event);\n          if (p === null) return;\n          (event.target as Element).setPointerCapture?.(event.pointerId);\n          setDrawing([p]);\n        }}\n        onPointerMove={(event) => {\n          if (drawing === null) return;\n          const p = point(event);\n          if (p !== null) setDrawing([...drawing, p]);\n        }}\n        onPointerUp={finish}\n        onPointerCancel={finish}\n      >\n        <rect x={0} y={0} width={BOARD_W} height={BOARD_H} className=\"mx-meet__board-paper\" />\n        {strokes.map((stroke) => (\n          <StrokeView\n            key={stroke.id}\n            stroke={stroke}\n            onPick={\n              tool === \"eraser\" && (isHost || stroke.by === localIdentity)\n                ? () => void act({ action: \"stroke_erase\", itemId: stroke.id }).then((r) => (r.ok ? undefined : show(r)))\n                : undefined\n            }\n          />\n        ))}\n        {pending.map((stroke) => (\n          <StrokeView key={stroke.id} stroke={stroke} />\n        ))}\n        {drawing !== null ? (\n          <StrokeView\n            stroke={{\n              id: \"drawing\",\n              points: drawing,\n              color,\n              width: tool === \"highlighter\" ? 4 : 3,\n              tool: tool === \"highlighter\" ? \"highlighter\" : \"pen\",\n              by: \"\",\n              byName: \"You\",\n            }}\n          />\n        ) : null}\n      </svg>\n    </section>\n  );\n}\n\n// ── breakout rooms ─────────────────────────────────────────────────────────\n\n/** A countdown: half a second left still reads 0:01, so round up to the whole second. */\nfunction clock(ms: number): string {\n  return formatDurationMs(Math.ceil(ms / 1000) * 1000, { style: \"clock\" });\n}\n\n/** How long a refused `breakout_expire` waits before asking again. */\nconst BREAKOUT_EXPIRE_RETRY_MS = 5000;\n\nfunction useNow(active: boolean): number {\n  const [now, setNow] = useState(() => Date.now());\n  useEffect(() => {\n    if (!active) return undefined;\n    const timer = setInterval(() => setNow(Date.now()), 1000);\n    return () => clearInterval(timer);\n  }, [active]);\n  return now;\n}\n\ntype AssignMode = \"auto\" | \"manual\" | \"choose\";\n\nfunction BreakoutSetup(): ReactNode {\n  const { collab, act } = useCollab();\n  const snapshot = useMeetSnapshot();\n  const settings = collab?.settings ?? null;\n  const people = (snapshot?.participants ?? []).filter(\n    (p) => !p.isAgent && p.role !== \"host\" && p.role !== \"cohost\",\n  );\n  const [count, setCount] = useState(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));\n  const [mode, setMode] = useState<AssignMode>(\"auto\");\n  const [minutes, setMinutes] = useState(settings?.breakoutDefaultMinutes ?? 15);\n  const [manual, setManual] = useState<Record<string, number>>({});\n  const [busy, setBusy] = useState(false);\n  const [notice, show] = useNotice();\n  const max = settings?.breakoutMaxRooms ?? 20;\n  const rooms = Math.min(Math.max(1, count), max);\n  const assignment =\n    mode === \"auto\"\n      ? autoAssign(\n          people.map((p) => p.identity),\n          rooms,\n        )\n      : mode === \"manual\"\n        ? Array.from({ length: rooms }, (_, index) =>\n            people.filter((p) => (manual[p.identity] ?? -1) === index).map((p) => p.identity),\n          )\n        : Array.from({ length: rooms }, () => [] as string[]);\n  const nameOf = (identity: string) => people.find((p) => p.identity === identity)?.displayName ?? identity;\n\n  return (\n    <div className=\"mx-meet__collab-card\">\n      <label className=\"mx-meet__field\">\n        <span className=\"mx-meet__field-label\">Rooms</span>\n        <input\n          className=\"mx-meet__input\"\n          type=\"number\"\n          min={1}\n          max={max}\n          value={count}\n          onChange={(event) => setCount(Number(event.target.value) || 1)}\n        />\n      </label>\n      <div className=\"mx-meet__pills\" role=\"group\" aria-label=\"How people are placed\">\n        {(\n          [\n            [\"auto\", \"Automatically\"],\n            [\"manual\", \"Manually\"],\n            [\"choose\", \"Let people choose\"],\n          ] as const\n        ).map(([value, label]) => (\n          <button\n            key={value}\n            type=\"button\"\n            className={mode === value ? \"mx-meet__pill mx-meet__pill--on\" : \"mx-meet__pill\"}\n            aria-pressed={mode === value}\n            onClick={() => setMode(value)}\n          >\n            {label}\n          </button>\n        ))}\n      </div>\n      <label className=\"mx-meet__field\">\n        <span className=\"mx-meet__field-label\">Timer (minutes, 0 for none)</span>\n        <input\n          className=\"mx-meet__input\"\n          type=\"number\"\n          min={0}\n          max={720}\n          value={minutes}\n          onChange={(event) => setMinutes(Math.max(0, Number(event.target.value) || 0))}\n        />\n      </label>\n      {mode === \"manual\" ? (\n        people.length === 0 ? (\n          <p className=\"mx-meet__panel-note\">Nobody else is in the meeting yet.</p>\n        ) : (\n          <ul className=\"mx-meet__people\">\n            {people.map((person) => (\n              <li className=\"mx-meet__person\" key={person.identity}>\n                <span className=\"mx-meet__person-name\">{person.displayName}</span>\n                <Select\n                  aria-label={`Room for ${person.displayName}`}\n                  value={String(manual[person.identity] ?? -1)}\n                  onValueChange={(next) => setManual({ ...manual, [person.identity]: Number(next) })}\n                  options={[\n                    { value: \"-1\", label: \"Main room\" },\n                    ...Array.from({ length: rooms }, (_, index) => ({ value: String(index), label: `Room ${index + 1}` })),\n                  ]}\n                />\n              </li>\n            ))}\n          </ul>\n        )\n      ) : mode === \"auto\" ? (\n        <ul className=\"mx-meet__breakout-rooms\">\n          {assignment.map((members, index) => (\n            <li key={index}>\n              <strong>Room {index + 1}</strong>{\" \"}\n              <span className=\"mx-meet__panel-note\">{members.length === 0 ? \"empty\" : members.map(nameOf).join(\", \")}</span>\n            </li>\n          ))}\n        </ul>\n      ) : (\n        <p className=\"mx-meet__panel-note\">Everyone picks a room from their own screen.</p>\n      )}\n      <Notice notice={notice} />\n      <button\n        type=\"button\"\n        className=\"mx-meet__primary mx-meet__primary--small\"\n        disabled={busy}\n        onClick={() => {\n          setBusy(true);\n          void act({\n            action: \"breakout_open\",\n            rooms: assignment.map((identities, index) => ({ name: `Room ${index + 1}`, identities })),\n            allowChoose: mode === \"choose\",\n            minutes,\n          }).then((result) => {\n            setBusy(false);\n            show(result);\n          });\n        }}\n      >\n        Open {rooms} room{rooms === 1 ? \"\" : \"s\"}\n      </button>\n    </div>\n  );\n}\n\nfunction BreakoutRun({ plan }: { plan: MeetBreakoutPlan }): ReactNode {\n  const { act, moveTo, isHost, breakoutRoomId, localIdentity } = useCollab();\n  const snapshot = useMeetSnapshot();\n  const now = useNow(plan.endsAt !== null);\n  const remaining = breakoutRemainingMs(plan, now);\n  const [broadcast, setBroadcast] = useState(\"\");\n  const [notice, show] = useNotice();\n  const nameOf = (identity: string) =>\n    displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);\n  const mine = assignedRoom(plan, localIdentity);\n\n  const join = async (roomId: string | null) => {\n    const said = await act({ action: \"breakout_join\", roomId });\n    if (!said.ok) {\n      show(said);\n      return;\n    }\n    show(await moveTo(roomId));\n  };\n\n  return (\n    <div className=\"mx-meet__collab-card\">\n      <p className=\"mx-meet__panel-note\">\n        {plan.rooms.length} room{plan.rooms.length === 1 ? \"\" : \"s\"} open\n        {remaining !== null ? ` · ${clock(remaining)} left` : \"\"}\n        {plan.allowChoose ? \" · people choose their room\" : \"\"}\n      </p>\n      <ul className=\"mx-meet__breakout-rooms\">\n        {plan.rooms.map((room) => {\n          const here = breakoutRoomId === room.id;\n          const mayJoin = isHost || plan.allowChoose || mine?.id === room.id;\n          return (\n            <li key={room.id} className={here ? \"mx-meet__breakout-room mx-meet__breakout-room--here\" : \"mx-meet__breakout-room\"}>\n              <div className=\"mx-meet__collab-head\">\n                <strong>{room.name}</strong>\n                {here ? (\n                  <span className=\"mx-meet__collab-state\">You are here</span>\n                ) : mayJoin ? (\n                  <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void join(room.id)}>\n                    Join\n                  </button>\n                ) : null}\n              </div>\n              <span className=\"mx-meet__panel-note\">\n                {room.identities.length === 0 ? \"Nobody assigned\" : room.identities.map(nameOf).join(\", \")}\n              </span>\n              {isHost && room.identities.length > 0 ? (\n                <ul className=\"mx-meet__people\">\n                  {room.identities.map((identity) => (\n                    <li className=\"mx-meet__person\" key={identity}>\n                      <span className=\"mx-meet__person-name\">{nameOf(identity)}</span>\n                      <Select\n                        aria-label={`Move ${nameOf(identity)}`}\n                        value={room.id}\n                        onValueChange={(next) =>\n                          void act({\n                            action: \"breakout_move\",\n                            identity,\n                            roomId: next === \"\" ? null : next,\n                          }).then(show)\n                        }\n                        options={[\n                          { value: \"\", label: \"Main room\" },\n                          ...plan.rooms.map((option) => ({ value: option.id, label: option.name })),\n                        ]}\n                      />\n                    </li>\n                  ))}\n                </ul>\n              ) : null}\n            </li>\n          );\n        })}\n      </ul>\n      {breakoutRoomId !== null ? (\n        <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void join(null)}>\n          Return to the main room\n        </button>\n      ) : null}\n      {isHost ? (\n        <form\n          className=\"mx-meet__composer-row\"\n          onSubmit={(event) => {\n            event.preventDefault();\n            const text = broadcast.trim();\n            if (text.length === 0) return;\n            void act({ action: \"breakout_broadcast\", text }).then((result) => {\n              show(result);\n              if (result.ok) setBroadcast(\"\");\n            });\n          }}\n        >\n          <input\n            className=\"mx-meet__input\"\n            value={broadcast}\n            maxLength={500}\n            onChange={(event) => setBroadcast(event.target.value)}\n            placeholder=\"Message every room\"\n            aria-label=\"Message every room\"\n          />\n          <button type=\"submit\" className=\"mx-meet__send\" disabled={broadcast.trim().length === 0}>\n            Send\n          </button>\n        </form>\n      ) : null}\n      <Notice notice={notice} />\n      {isHost ? (\n        <button\n          type=\"button\"\n          className=\"mx-meet__primary mx-meet__primary--small\"\n          onClick={() => void act({ action: \"breakout_close\" }).then(show)}\n        >\n          Close rooms\n        </button>\n      ) : null}\n    </div>\n  );\n}\n\nexport function BreakoutsPanel({ onClose }: { onClose: () => void }): ReactNode {\n  const { collab, isHost } = useCollab();\n  const plan = collab?.breakout?.state === \"open\" ? collab.breakout : null;\n  return (\n    <PanelShell title=\"Breakout rooms\" onClose={onClose}>\n      {collab?.error != null ? <p className=\"mx-meet__panel-note mx-meet__collab-error\">{collab.error}</p> : null}\n      {plan !== null ? <BreakoutRun plan={plan} /> : isHost ? <BreakoutSetup /> : (\n        <p className=\"mx-meet__panel-note\">Breakout rooms are closed.</p>\n      )}\n    </PanelShell>\n  );\n}\n\n/**\n * WHAT A PERSON IN A MEETING WITH BREAKOUTS SEES WITHOUT OPENING ANYTHING: the room they\n * were assigned to (with Join), the room they are in and its countdown (with Return),\n * a host's broadcast — and the moves: a host moving them, and everyone coming back.\n * Also asks the server to close the plan when the countdown reaches zero (the server's\n * clock decides; no schedule).\n */\nexport function BreakoutBanner(): ReactNode {\n  const host = useMeetHost();\n  const { collab, act, moveTo, localIdentity, breakoutRoomId } = useCollab();\n  const plan = collab?.breakout ?? null;\n  const open = plan?.state === \"open\" ? plan : null;\n  const now = useNow(open?.endsAt != null || open?.closingAt != null);\n  const remaining = breakoutRemainingMs(open, now);\n  const closing = breakoutClosingMs(open, now);\n  const assigned = assignedRoom(open, localIdentity);\n  // bo-invite-join: an invitation (Join / Later) or, in `auto` mode, a short countdown and\n  // then the move. Later hides the card but Join stays one click away.\n  const [later, setLater] = useState<string | null>(null);\n  const [autoSince, setAutoSince] = useState<{ id: string; at: number } | null>(null);\n  const AUTO_MOVE_MS = 10_000;\n  const autoLeft =\n    open?.moveMode === \"auto\" && assigned !== null && autoSince?.id === open.id && later !== open.id\n      ? Math.max(0, AUTO_MOVE_MS - (now - autoSince.at))\n      : null;\n  const [dismissedBroadcast, setDismissedBroadcast] = useState<string | null>(null);\n  const [failure, setFailure] = useState<string | null>(null);\n  const expireAsked = useRef<{ id: string; at: number } | null>(null);\n\n  // Moves the server asked for: a host moved me, or the rooms closed.\n  const moveAt = collab?.moveRequest?.at ?? null;\n  useEffect(() => {\n    if (host === null) return;\n    const request = takeMoveRequest(host.store);\n    if (request === null) return;\n    const here = host.store.snapshot().breakoutRoomId;\n    if ((here ?? null) === request.roomId) return;\n    void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));\n  }, [moveAt, host, moveTo]);\n\n  const joinAssigned = async () => {\n    if (assigned === null) return;\n    const said = await act({ action: \"breakout_join\", roomId: assigned.id });\n    const result = said.ok ? await moveTo(assigned.id) : said;\n    setFailure(result.ok ? null : result.message);\n  };\n  useEffect(() => {\n    if (open === null || open.moveMode !== \"auto\" || assigned === null || breakoutRoomId !== null) return;\n    if (autoSince?.id !== open.id) setAutoSince({ id: open.id, at: Date.now() });\n  }, [open, assigned, breakoutRoomId, autoSince]);\n  useEffect(() => {\n    if (autoLeft === 0) void joinAssigned();\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [autoLeft]);\n\n  // The timer ran out on this screen: ask; the server's clock decides. A screen whose\n  // clock runs ahead is refused, so it asks again every few seconds, never only once.\n  useEffect(() => {\n    if (open === null || remaining === null || remaining > 0) return;\n    const asked = expireAsked.current;\n    if (asked !== null && asked.id === open.id && now - asked.at < BREAKOUT_EXPIRE_RETRY_MS) return;\n    expireAsked.current = { id: open.id, at: now };\n    void act({ action: \"breakout_expire\" });\n  }, [open, remaining, act, now]);\n\n  const broadcast = collab?.broadcast ?? null;\n  const showBroadcast = broadcast !== null && broadcast.at !== dismissedBroadcast && open !== null;\n  const room = open?.rooms.find((r) => r.id === breakoutRoomId) ?? null;\n\n  if (open === null && failure === null) return null;\n  return (\n    <div className=\"mx-meet__breakout-banner\" role=\"status\">\n      {failure !== null ? <span className=\"mx-meet__collab-error\">{failure}</span> : null}\n      {closing !== null ? (\n        <span role=\"status\" data-meet-notice=\"breakout-closing\">\n          Rooms closing in {Math.ceil(closing / 1000)}\n          {room !== null ? \" — you return to the main meeting\" : \"\"}\n        </span>\n      ) : null}\n      {room !== null ? (\n        <span>\n          <strong>{room.name}</strong>\n          {remaining !== null && closing === null ? ` · ${clock(remaining)} left` : \"\"}\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void moveTo(null)}>\n            Return to main room\n          </button>\n        </span>\n      ) : assigned !== null && later !== open?.id ? (\n        <span>\n          {autoLeft !== null\n            ? `You're being moved to ${assigned.name} in ${formatDurationMs(Math.ceil(autoLeft / 1000) * 1000, { style: \"long\" })}`\n            : `You're invited to ${assigned.name}`}\n          {remaining !== null && closing === null ? ` · ${clock(remaining)} left` : \"\"}\n          <button type=\"button\" className=\"mx-meet__primary mx-meet__primary--small\" onClick={() => void joinAssigned()}>\n            Join room\n          </button>\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => setLater(open?.id ?? null)}>\n            Later\n          </button>\n        </span>\n      ) : assigned !== null ? (\n        <span>\n          {assigned.name} is open\n          <button type=\"button\" className=\"mx-meet__chip\" onClick={() => void joinAssigned()}>\n            Join room\n          </button>\n        </span>\n      ) : open?.allowChoose ? (\n        <span>Rooms are open — pick one under Activities.</span>\n      ) : null}\n      {showBroadcast ? (\n        <span className=\"mx-meet__breakout-broadcast\">\n          <strong>{broadcast.by}:</strong> {broadcast.text}\n          <button type=\"button\" className=\"mx-meet__link\" onClick={() => setDismissedBroadcast(broadcast.at)}>\n            Dismiss\n          </button>\n        </span>\n      ) : null}\n    </div>\n  );\n}\n\n// ── translated captions ────────────────────────────────────────────────────\n\n/** The Settings panel's captions section: translate captions into a language, or not. */\nexport function CaptionLanguageSettings(): ReactNode {\n  const host = useMeetHost();\n  const snapshot = useMeetSnapshot();\n  const collab = snapshot?.collab ?? null;\n  const settings = collab?.settings ?? null;\n  if (host === null || settings === null || !settings.captionTranslationEnabled) return null;\n  const viewer =\n    typeof navigator !== \"undefined\" && typeof navigator.language === \"string\" ? navigator.language.slice(0, 2) : null;\n  const preferred = defaultCaptionLanguage(settings, viewer);\n  const current = collab?.captionLanguage ?? \"\";\n  const choices = CAPTION_LANGUAGES.some((l) => l.tag === preferred)\n    ? CAPTION_LANGUAGES\n    : [{ tag: preferred, name: preferred }, ...CAPTION_LANGUAGES];\n  return (\n    <section className=\"mx-meet__section\" aria-label=\"Captions\">\n      <label className=\"mx-meet__field\">\n        <span className=\"mx-meet__field-label\">Translate captions to</span>\n        <Select\n          aria-label=\"Translate captions to\"\n          value={current}\n          onValueChange={(next) => setCaptionLanguage(host.store, next === \"\" ? null : next)}\n          options={[\n            { value: \"\", label: \"Off — as spoken\" },\n            ...(current === \"\"\n              ? [{ value: preferred, label: `${choices.find((c) => c.tag === preferred)?.name ?? preferred} (yours)` }]\n              : []),\n            ...choices\n              .filter((choice) => current !== \"\" || choice.tag !== preferred)\n              .map((choice) => ({ value: choice.tag, label: choice.name })),\n          ]}\n        />\n      </label>\n      {collab?.captionTranslationError != null ? (\n        <p className=\"mx-meet__panel-note mx-meet__collab-error\">{collab.captionTranslationError}</p>\n      ) : null}\n    </section>\n  );\n}\n\n// ── captions for me, and \"Take notes for me\" ───────────────────────────────\n\n/** Google Meet's captions button: \"Turn on captions\" / \"Turn off captions\", for this viewer only. */\nexport function CaptionsControl(): ReactNode {\n  const captions = useCaptions();\n  return (\n    <ControlButton\n      label={captions.on ? \"Turn off captions\" : \"Turn on captions\"}\n      active={captions.on}\n      pressed={captions.on}\n      onClick={captions.toggle}\n    >\n      <CaptionsIcon />\n    </ControlButton>\n  );\n}\n\n/**\n * Google Meet's \"Take notes for me\", host only (it summons the AI note-taker). Absent for\n * everyone who cannot use it; once notes are on, the same place stops them.\n */\nexport function TakeNotesControl(): ReactNode {\n  const ai = useMeetAi();\n  if (!ai.canControlNoteTaker) return null;\n  const running = ai.noteTaker.state === \"joining\" || ai.noteTaker.state === \"transcribing\";\n  return (\n    <ControlButton\n      label={running ? \"Stop taking notes\" : \"Take notes for me\"}\n      active={running}\n      onClick={() => void (running ? ai.stopNoteTaker() : ai.startNoteTaker())}\n    >\n      <NotesIcon />\n    </ControlButton>\n  );\n}\n","\"use client\";\n\n/**\n * skins/meet/icons.tsx — this package's glyph names, as aliases of the ONE glyph home,\n * `@ai-matrx/design-system/icons`. No path data lives here (policy C19: no icon library, and one drawing per\n * glyph); the alias only fixes this package's historical size and stroke. Exports are unchanged.\n */\n\nimport {\n  ActivitiesIcon as GActivitiesIcon,\n  BreakoutIcon as GBreakoutIcon,\n  CameraIcon as GCameraIcon,\n  CameraOffIcon as GCameraOffIcon,\n  CaptionsIcon as GCaptionsIcon,\n  ChatIcon as GChatIcon,\n  ChevronUpIcon as GChevronUpIcon,\n  EraserIcon as GEraserIcon,\n  FlagIcon as GFlagIcon,\n  HandIcon as GHandIcon,\n  HighlighterIcon as GHighlighterIcon,\n  KeyboardIcon as GKeyboardIcon,\n  MicIcon as GMicIcon,\n  MicOffIcon as GMicOffIcon,\n  NotesIcon as GNotesIcon,\n  PeopleIcon as GPeopleIcon,\n  PhoneOffIcon as GPhoneOffIcon,\n  PollIcon as GPollIcon,\n  QuestionIcon as GQuestionIcon,\n  RecordIcon as GRecordIcon,\n  ScreenShareIcon as GScreenShareIcon,\n  SettingsIcon as GSettingsIcon,\n  SmileIcon as GSmileIcon,\n  SpeakerIcon as GSpeakerIcon,\n  SpotlightIcon as GSpotlightIcon,\n  Undo2Icon as GUndo2Icon,\n  UpvoteIcon as GUpvoteIcon,\n  WhiteboardIcon as GWhiteboardIcon,\n  WifiLowIcon as GWifiLowIcon,\n  withGlyphDefaults,\n  type GlyphComponent,\n} from \"@ai-matrx/design-system/icons\";\n\nimport type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement>;\n\nconst sized = (Glyph: GlyphComponent): GlyphComponent => withGlyphDefaults(Glyph, { width: 20, height: 20, strokeWidth: 1.75 });\n\nconst MicIcon = sized(GMicIcon);\nconst MicOffIcon = sized(GMicOffIcon);\nconst CameraIcon = sized(GCameraIcon);\nconst CameraOffIcon = sized(GCameraOffIcon);\nconst ScreenShareIcon = sized(GScreenShareIcon);\nconst PhoneOffIcon = sized(GPhoneOffIcon);\nconst HandIcon = sized(GHandIcon);\nconst ChatIcon = sized(GChatIcon);\nconst PeopleIcon = sized(GPeopleIcon);\nconst RecordIcon = sized(GRecordIcon);\nconst CaptionsIcon = sized(GCaptionsIcon);\nconst NotesIcon = sized(GNotesIcon);\nconst SettingsIcon = sized(GSettingsIcon);\nconst WifiLowIcon = sized(GWifiLowIcon);\nconst SmileIcon = sized(GSmileIcon);\nconst KeyboardIcon = sized(GKeyboardIcon);\nconst SpotlightIcon = sized(GSpotlightIcon);\nconst SpeakerIcon = sized(GSpeakerIcon);\nconst FlagIcon = sized(GFlagIcon);\nconst ActivitiesIcon = sized(GActivitiesIcon);\nconst PollIcon = sized(GPollIcon);\nconst QuestionIcon = sized(GQuestionIcon);\nconst WhiteboardIcon = sized(GWhiteboardIcon);\nconst BreakoutIcon = sized(GBreakoutIcon);\nconst UpvoteIcon = sized(GUpvoteIcon);\nconst EraserIcon = sized(GEraserIcon);\nconst HighlighterIcon = sized(GHighlighterIcon);\nconst UndoIcon = sized(GUndo2Icon);\nconst ChevronUpIcon = sized(GChevronUpIcon);\n\nexport {\n  MicIcon,\n  MicOffIcon,\n  CameraIcon,\n  CameraOffIcon,\n  ScreenShareIcon,\n  PhoneOffIcon,\n  HandIcon,\n  ChatIcon,\n  PeopleIcon,\n  RecordIcon,\n  CaptionsIcon,\n  NotesIcon,\n  SettingsIcon,\n  WifiLowIcon,\n  SmileIcon,\n  KeyboardIcon,\n  SpotlightIcon,\n  SpeakerIcon,\n  FlagIcon,\n  ActivitiesIcon,\n  PollIcon,\n  QuestionIcon,\n  WhiteboardIcon,\n  BreakoutIcon,\n  UpvoteIcon,\n  EraserIcon,\n  HighlighterIcon,\n  UndoIcon,\n  ChevronUpIcon,\n};\n\nfunction Icon({ children, ...props }: IconProps): React.ReactElement {\n  return (\n    <svg\n      width=\"20\"\n      height=\"20\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.75\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n      focusable=\"false\"\n      {...props}\n    >\n      {children}\n    </svg>\n  );\n}\n\nexport function SignalIcon({ bars, ...props }: IconProps & { bars: 0 | 1 | 2 | 3 }): React.ReactElement {\n  return (\n    <Icon {...props}>\n      <path d=\"M4 20v-2\" opacity={bars >= 1 ? 1 : 0.3} />\n      <path d=\"M10 20v-6\" opacity={bars >= 2 ? 1 : 0.3} />\n      <path d=\"M16 20V9\" opacity={bars >= 3 ? 1 : 0.3} />\n      <path d=\"M22 20V4\" opacity={bars >= 3 ? 1 : 0.3} />\n    </Icon>\n  );\n}\n","\"use client\";\n\n/**\n * THE MEETING RECORD — a skin-EXTERNAL surface (CORE-DESIGN §5.3).\n *\n * What a meeting is once the room is gone: the record view, the recording\n * player and the host's guest-access control. Outside the skin boundary — every\n * skin links to the same record — so it lives in `@ai-matrx/meet/react`.\n * It draws with the Meet skin's v0 primitives until the record gets its own\n * look (S9 is the pixel pass).\n */\n\nimport { useEffect, useState, type ReactNode } from \"react\";\nimport { ErrorBox } from \"@ai-matrx/design-system\";\nimport { fileDownloadPath } from \"../core/api\";\nimport type { MeetFileMedia } from \"../core/api\";\nimport { displayNameFor } from \"../core/names\";\nimport { uniqueAttendees } from \"../core/after\";\nimport type { MeetingRecord } from \"../core/types\";\nimport { useMeetingRecord } from \"./hooks\";\nimport { groupTranscript, meetingWhen, playableRecordingFileId, recordingNotice, absenceSentence, REFUSED_ABSENCE, summarizeMeetingRecordRestrictions, wasRefused, wrapUpStatus } from \"../core/record\";\nimport { useMeetHost, useRequiredMeetHost } from \"./provider\";\nimport type { MeetHost } from \"./provider\";\nimport { MeetAvatar, GuestRecordAccessControl, InertNotice, NoteList, clockOf } from \"../skins/meet/components\";\n\n/* ------------------------------------------------------ the meeting record */\n\n/**\n * THE MEETING, AFTER THE MEETING (MRI-D2).\n *\n * 🚨 THE DEFECT THIS REPLACES. A meeting produced a wrap-up summary, decisions,\n * owner-assigned action items, live-note windows, a speaker-attributed\n * transcript and a recording — and then `/meet/<slug>` rendered `<PreJoin>`,\n * offering to join a room that no longer existed. Everything the campaign built\n * after the room closed was reachable only from SQL. A durable link that\n * outlives the meeting (R3) has to resolve to the RECORD.\n *\n * The bar it is written to (PLAN §3, Fireflies/Otter recon): what was decided,\n * who owns what, what was said and by whom, and a question box over all of it.\n *\n * Nothing on this screen is computed in the browser. Every line is a durable\n * row; the answer is streamed from `/intelligence/ask`, which reads those same\n * rows server-side. A part the reader is not allowed to see says so IN WORDS —\n * an empty section is indistinguishable from a meeting where nothing happened.\n */\n\nexport function MeetingRecordView({\n  meeting,\n  onRejoin,\n}: {\n  meeting: MeetingRecord;\n  /** Optional: a recurring link can be re-opened. Absent for a one-off. */\n  onRejoin?: () => void;\n}): ReactNode {\n  const host = useMeetHost();\n  if (host === null) {\n    return (\n      <div className=\"mx-meet mx-meet--record\">\n        <InertNotice what=\"This meeting record\" />\n      </div>\n    );\n  }\n  return <MeetingRecordBody meeting={meeting} {...(onRejoin !== undefined ? { onRejoin } : {})} />;\n}\n\nfunction MeetingRecordBody({\n  meeting,\n  onRejoin,\n}: {\n  meeting: MeetingRecord;\n  onRejoin?: () => void;\n}): ReactNode {\n  const host = useRequiredMeetHost();\n  const record = useMeetingRecord(meeting);\n  const [question, setQuestion] = useState(\"\");\n  const [tab, setTab] = useState<\"summary\" | \"notes\" | \"transcript\">(\"summary\");\n\n  if (record.failure !== null) {\n    return (\n      <div className=\"mx-meet mx-meet--record\">\n        <ErrorBox as=\"div\" className=\"mx-meet__empty\" error={record.failure} operation=\"Open this meeting record\" origin=\"meet/components\">\n          <p className=\"mx-meet__empty-title\">This meeting record could not be opened</p>\n          <p className=\"mx-meet__empty-body\">{record.failure.message}</p>\n          <p className=\"mx-meet__empty-body\">{record.failure.remedy}</p>\n        </ErrorBox>\n      </div>\n    );\n  }\n\n  if (record.loading || record.record === null) {\n    return (\n      <div className=\"mx-meet mx-meet--record\">\n        <div className=\"mx-meet__empty\" role=\"status\">\n          {/* A record only exists for a meeting that is over; say so while it loads. */}\n          <p className=\"mx-meet__empty-title\" data-meet-notice=\"meeting-ended\">The meeting has ended</p>\n          <p className=\"mx-meet__empty-title\">Opening the meeting record…</p>\n          <p className=\"mx-meet__empty-body\">\n            Reading the summary, the notes and the transcript this meeting left behind.\n          </p>\n        </div>\n      </div>\n    );\n  }\n\n  const bundle = record.record;\n  const wrapUp = wrapUpStatus(bundle);\n  const blocks = groupTranscript(bundle.transcript, bundle.names);\n  const notice = recordingNotice(bundle.recording);\n  const fileId = playableRecordingFileId(bundle.recording);\n  // One entry per PERSON — a rejoin or a second device is not a second attendee.\n  const attended = uniqueAttendees(\n    bundle.attendees.filter((person) => person.admissionState !== \"denied\"),\n    bundle.names,\n  );\n  const restrictionNotices = summarizeMeetingRecordRestrictions(bundle.restrictions);\n  // The server permits the room-pass Q&A only while a guest is in a live\n  // meeting. Do not offer a finished-record action that its authorization\n  // boundary will always refuse; signed-in members retain durable Q&A.\n  const guestFinishedMeeting = host.identity.userId === null && meeting.endedAt !== null;\n  const everyRecordPartRefused = (['attendance', 'notes', 'transcript', 'recording'] as const).every(\n    (part) => wasRefused(bundle, part),\n  );\n  const entirelyRestricted =\n    everyRecordPartRefused &&\n    bundle.attendees.length === 0 &&\n    bundle.liveNotes.length === 0 &&\n    bundle.transcript.length === 0 &&\n    bundle.recording === null &&\n    bundle.summary === null &&\n    bundle.decisions.length === 0 &&\n    bundle.actionItems.length === 0;\n\n  if (entirelyRestricted) {\n    return (\n      <div className=\"mx-meet mx-meet--record\">\n        <header className=\"mx-meet__record-head\">\n          <div className=\"mx-meet__record-head-inner\">\n            <p className=\"mx-meet__record-eyebrow\">Meeting record</p>\n            <h1 className=\"mx-meet__record-title\">{meeting.title}</h1>\n            <p className=\"mx-meet__record-when\">{meetingWhen(meeting)}</p>\n            {onRejoin !== undefined ? (\n              <button type=\"button\" className=\"mx-meet__link\" onClick={onRejoin}>\n                Open this link again\n              </button>\n            ) : null}\n          </div>\n        </header>\n        <div className=\"mx-meet__record-body\">\n          {restrictionNotices.map((notice) => (\n            <div key={notice.parts.join('-')} className=\"mx-meet__record-access\" role=\"status\">\n              <p className=\"mx-meet__record-access-title\">About this record</p>\n              <p className=\"mx-meet__record-access-message\">{notice.message}</p>\n              <p className=\"mx-meet__record-access-remedy\">{notice.remedy}</p>\n            </div>\n          ))}\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"mx-meet mx-meet--record\">\n      <header className=\"mx-meet__record-head\">\n        <div className=\"mx-meet__record-head-inner\">\n          <p className=\"mx-meet__record-eyebrow\">Meeting record</p>\n          <h1 className=\"mx-meet__record-title\">{meeting.title}</h1>\n          <p className=\"mx-meet__record-when\">{meetingWhen(meeting)}</p>\n          {onRejoin !== undefined ? (\n            <button type=\"button\" className=\"mx-meet__link\" onClick={onRejoin}>\n              Open this link again\n            </button>\n          ) : null}\n        </div>\n      </header>\n\n      <div className=\"mx-meet__record-body\">\n        {/* WHAT THIS READER CANNOT SEE, AND WHY. Never an empty section. */}\n        {restrictionNotices.map((notice) => (\n          <div key={notice.parts.join(\"-\")} className=\"mx-meet__record-access\" role=\"status\">\n            <p className=\"mx-meet__record-access-title\">About this record</p>\n            <p className=\"mx-meet__record-access-message\">{notice.message}</p>\n            <p className=\"mx-meet__record-access-remedy\">{notice.remedy}</p>\n          </div>\n        ))}\n\n        {/* WHO WAS THERE — the durable attendance rows, which outlive the room. */}\n        {attended.length === 0 ? (\n          /* NOT SILENCE. A refused attendance read used to remove the whole\n             section, so the reader could not tell \"nobody\" from \"not shown\". */\n          <section className=\"mx-meet__record-section\" aria-label=\"Who attended\">\n            <h2 className=\"mx-meet__record-section-title\">Who attended</h2>\n            <p className=\"mx-meet__panel-note\">\n              {absenceSentence(bundle, \"attendance\", \"Nobody is recorded as having attended.\")}\n            </p>\n          </section>\n        ) : (\n          <section className=\"mx-meet__record-section\" aria-label=\"Who attended\">\n            <h2 className=\"mx-meet__record-section-title\">Who attended</h2>\n            <ul className=\"mx-meet__record-attendees\">\n              {attended.map((person) => (\n                <li key={person.id} className=\"mx-meet__record-attendee\">\n                  <MeetAvatar\n                    name={displayNameFor(bundle.names, person.identity, person.displayName)}\n                    url={person.avatarUrl}\n                    size={28}\n                  />\n                  <span className=\"mx-meet__person-name\">\n                    {displayNameFor(bundle.names, person.identity, person.displayName)}\n                    {person.role === \"host\" ? <span className=\"mx-meet__badge\">Host</span> : null}\n                    {person.userId === null && !person.isAgent ? <span className=\"mx-meet__badge\">Guest</span> : null}\n                    {/* Attendance establishes an agent's role, not whether it\n                        captured a transcript. Recording-only meetings can have\n                        an agent row without any live capture. */}\n                    {person.isAgent ? (\n                      <span className=\"mx-meet__badge\">Meeting assistant</span>\n                    ) : null}\n                  </span>\n                </li>\n              ))}\n            </ul>\n          </section>\n        )}\n\n        {/* THE RECORDING. `available` plays; anything else states what it is\n            doing. There is never a player over a file that does not exist. */}\n        {bundle.recording !== null ? (\n          <section className=\"mx-meet__record-section mx-meet__recording-card\" aria-label=\"Recording\">\n            <h2 className=\"mx-meet__record-section-title\">Recording</h2>\n            {fileId !== null ? (\n              <>\n                <RecordingPlayer fileId={fileId} />\n                {notice !== null ? <p className=\"mx-meet__panel-note\">{notice}</p> : null}\n              </>\n            ) : (\n              <p className=\"mx-meet__panel-note\">{notice ?? \"This recording has no file.\"}</p>\n            )}\n          </section>\n        ) : wasRefused(bundle, \"recording\") ? (\n          <section className=\"mx-meet__record-section\" aria-label=\"Recording\">\n            <h2 className=\"mx-meet__record-section-title\">Recording</h2>\n            <p className=\"mx-meet__panel-note\">{REFUSED_ABSENCE}</p>\n          </section>\n        ) : null}\n\n        <nav className=\"mx-meet__record-tabs\" aria-label=\"Meeting record sections\">\n          <button\n            type=\"button\"\n            className={`mx-meet__record-tab${tab === \"summary\" ? \" mx-meet__record-tab--active\" : \"\"}`}\n            onClick={() => setTab(\"summary\")}\n            aria-pressed={tab === \"summary\"}\n          >\n            Summary &amp; decisions\n          </button>\n          <button\n            type=\"button\"\n            className={`mx-meet__record-tab${tab === \"notes\" ? \" mx-meet__record-tab--active\" : \"\"}`}\n            onClick={() => setTab(\"notes\")}\n            aria-pressed={tab === \"notes\"}\n          >\n            Notes as it happened\n          </button>\n          <button\n            type=\"button\"\n            className={`mx-meet__record-tab${tab === \"transcript\" ? \" mx-meet__record-tab--active\" : \"\"}`}\n            onClick={() => setTab(\"transcript\")}\n            aria-pressed={tab === \"transcript\"}\n          >\n            Transcript\n          </button>\n        </nav>\n\n        {tab === \"summary\" ? (\n          <>\n            <section className=\"mx-meet__record-section\" aria-label=\"Summary\">\n              <h2 className=\"mx-meet__record-section-title\">Summary</h2>\n              {/* 🚨 NEVER AN ABSENCE THIS READER CANNOT KNOW (MRI-A16), AND\n                  NEVER AN ABSENCE THAT IS MERELY EARLY (MRI-A18). This said\n                  \"No wrap-up was written for this meeting\" under a panel that\n                  had just refused to read the notes (MRI-C8), and again for the\n                  ~33 s a perfectly healthy wrap-up job takes to land. Which of\n                  the five it is comes from `wrapUpStatus`, never from here. */}\n              {wrapUp.state === \"written\" ? (\n                <p className=\"mx-meet__record-summary\">{bundle.summary?.text}</p>\n              ) : wrapUp.state === \"in-progress\" ? (\n                <div className=\"mx-meet__panel-note\" role=\"status\">\n                  <p>{wrapUp.message}</p>\n                  {/* A LIVE AFFORDANCE, not a spinner over a promise. The\n                      record view has no realtime feed for a meeting whose room\n                      is already deleted, so the honest control is the one that\n                      re-reads the record. */}\n                  <button type=\"button\" className=\"mx-meet__link\" onClick={record.reload}>\n                    Check again\n                  </button>\n                </div>\n              ) : (\n                <p className=\"mx-meet__panel-note\" role={wrapUp.state === \"failed\" ? \"alert\" : undefined}>\n                  {wrapUp.message}\n                </p>\n              )}\n            </section>\n            <NoteList\n              title=\"Decisions\"\n              notes={bundle.decisions}\n              empty={\n                wrapUp.state === \"empty\"\n                  ? \"Nothing was discussed, so there are no decisions.\"\n                  : absenceSentence(\n                      bundle,\n                      \"notes\",\n                      \"Nothing was recorded as a decision in this meeting.\",\n                    )\n              }\n            />\n            <NoteList\n              title=\"Action items\"\n              notes={bundle.actionItems}\n              empty={\n                wrapUp.state === \"empty\"\n                  ? \"Nothing was discussed, so there are no action items.\"\n                  : absenceSentence(\n                      bundle,\n                      \"notes\",\n                      \"No action items came out of this meeting.\",\n                    )\n              }\n            />\n          </>\n        ) : null}\n\n        {tab === \"notes\" ? (\n          <section className=\"mx-meet__record-section\" aria-label=\"Notes as it happened\">\n            <h2 className=\"mx-meet__record-section-title\">Notes as it happened</h2>\n            {bundle.liveNotes.length === 0 ? (\n              <p className=\"mx-meet__panel-note\">\n                {absenceSentence(\n                  bundle,\n                  \"notes\",\n                  \"No live notes are available for this meeting.\",\n                )}\n              </p>\n            ) : (\n              <ul className=\"mx-meet__notes\">\n                {bundle.liveNotes.map((note) => (\n                  <li key={note.id} className=\"mx-meet__note\">\n                    {note.window !== null ? (\n                      <span className=\"mx-meet__badge\">Window {note.window}</span>\n                    ) : null}\n                    {note.text}\n                  </li>\n                ))}\n              </ul>\n            )}\n          </section>\n        ) : null}\n\n        {tab === \"transcript\" ? (\n          <section className=\"mx-meet__record-section\" aria-label=\"Transcript\">\n            <h2 className=\"mx-meet__record-section-title\">\n              Transcript\n              <span className=\"mx-meet__record-count\">\n                {bundle.transcript.length === 1\n                  ? \"1 line\"\n                  : `${bundle.transcript.length} lines`}\n              </span>\n            </h2>\n            {blocks.length === 0 ? (\n              <p className=\"mx-meet__panel-note\">\n                {absenceSentence(\n                  bundle,\n                  \"transcript\",\n                  \"No transcript is available for this meeting.\",\n                )}\n              </p>\n            ) : (\n              <ol className=\"mx-meet__record-transcript\">\n                {blocks.map((block) => (\n                  <li key={block.id} className=\"mx-meet__record-block\">\n                    <p className=\"mx-meet__record-speaker\">\n                      {block.speaker}\n                      <time className=\"mx-meet__record-time\" dateTime={block.startedAt}>\n                        {clockOf(block.startedAt)}\n                      </time>\n                    </p>\n                    {block.lines.map((line) => (\n                      <p key={line.id} className=\"mx-meet__record-line\">\n                        {line.text}\n                      </p>\n                    ))}\n                  </li>\n                ))}\n              </ol>\n            )}\n          </section>\n        ) : null}\n\n        {/* WHAT GUESTS MAY READ, decided where the host can see what there is\n            to share. Absent entirely for anyone who is not a host (MRF-1). */}\n        <GuestRecordAccessControl meeting={meeting} />\n\n        {/* Signed-in members can ask about durable rows after the room closes.\n            A guest's room pass deliberately expires for Q&A when the meeting\n            ends, even if that guest may still read the shared record. */}\n        <section className=\"mx-meet__record-section\" aria-label=\"Ask about this meeting\">\n          <h2 className=\"mx-meet__record-section-title\">Ask about this meeting</h2>\n          {guestFinishedMeeting ? (\n            <p className=\"mx-meet__panel-note\">\n              Sign in to ask the assistant about a meeting after it ends.\n            </p>\n          ) : (\n            <>\n              <form\n                className=\"mx-meet__composer\"\n                onSubmit={(event) => {\n                  event.preventDefault();\n                  const trimmed = question.trim();\n                  if (trimmed.length === 0) return;\n                  void record.ask(trimmed);\n                }}\n              >\n                <input\n                  className=\"mx-meet__input\"\n                  value={question}\n                  onChange={(event) => setQuestion(event.target.value)}\n                  placeholder=\"What did we decide about the vendor quote?\"\n                  aria-label=\"Ask about this meeting\"\n                />\n                <button\n                  type=\"submit\"\n                  className=\"mx-meet__primary\"\n                  disabled={question.trim().length === 0 || record.asking}\n                >\n                  {record.asking ? \"Asking…\" : \"Ask\"}\n                </button>\n              </form>\n              {record.answer !== null ? (\n                <p className=\"mx-meet__answer\">{record.answer}</p>\n              ) : null}\n              {record.coverage !== null ? (\n                <p className=\"mx-meet__coverage\">\n                  Answered from {record.coverage.segmentsUsed} of {record.coverage.segmentsTotal}{\" \"}\n                  transcript {record.coverage.segmentsTotal === 1 ? \"line\" : \"lines\"}\n                  {record.coverage.truncated ? \" (the oldest were left out)\" : \"\"}.\n                </p>\n              ) : null}\n              {record.askError !== null ? (\n                <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={record.askError} operation=\"Ask about this meeting\" origin=\"meet/components\">\n                  <p className=\"mx-meet__refusal-reason\">{record.askError.message}</p>\n                  <p className=\"mx-meet__refusal-remedy\">{record.askError.remedy}</p>\n                </ErrorBox>\n              ) : null}\n            </>\n          )}\n        </section>\n      </div>\n    </div>\n  );\n}\n\n/**\n * THE RECORDING, PLAYED THROUGH THE PLATFORM FILE ID (R3).\n *\n * `meet_recordings.file_id` is a PLATFORM file id, never a provider URL — a\n * LiveKit URL is orphaned the day the room is garbage collected, which is the\n * whole reason the column is not `url`. aidream serves the bytes at\n * `GET /files/{id}/download`, and that route is AUTHENTICATED: nothing in this\n * platform ever returns a signed URL (the files law, 2026-08-21/26).\n *\n * 🚨 A BEARER TOKEN IS NOT ENOUGH, and believing it was is what broke this\n * screen. Through 0.4.7 this component built its own `fetch` with only an\n * `authorization` header, so aidream's org-admission middleware answered 400\n * `organization_required` and a 1.38 MB recording that had landed perfectly\n * could not be played by the host who made it (MRI-C8). Every request the\n * package makes now goes through `host.api` (`core/api.ts`), which carries the\n * organization on all of them and cannot be bypassed — `core/api.test.ts`\n * fails the build if a second way to reach aidream appears.\n *\n * It is fetched on a click, never on render: a meeting recording is tens of\n * megabytes and nobody who opened the summary asked to download a video.\n * Every state here is a sentence — loading, failed with a remedy, or playing.\n */\n/** Said after a streaming media error, before a byte retry is attempted. */\nconst STREAM_REFUSED =\n  \"Streaming playback did not start, so this recording was downloaded in full instead. \" +\n  \"Downloading can take longer, and seeking is unavailable until it finishes.\";\n\nconst PLAYBACK_RETRY_REMEDY =\n  \"Reload the page and try again. If it still will not play, ask a meeting host to check the recording.\";\n\nexport function RecordingPlayer(props: { fileId: string }): ReactNode {\n  // THE GUARD, not a throw (rule 7c). `<RecordingPlayer>` is a PUBLIC entry\n  // component, so a consumer may render it while the provider is still inert —\n  // which, since 0.6.0, includes the tick the session read takes (DD-240). It\n  // used to call `useRequiredMeetHost()` and throw a package error into the\n  // consumer's tree for that tick.\n  const host = useMeetHost();\n  if (host === null) return <InertNotice what=\"This recording\" />;\n  return <RecordingPlayerBody {...props} host={host} />;\n}\n\nfunction RecordingPlayerBody({ fileId, host }: { fileId: string; host: MeetHost }): ReactNode {\n  const [media, setMedia] = useState<MeetFileMedia | null>(null);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState<{ message: string; remedy: string } | null>(null);\n\n  // A `blob:` url is revoked when this unmounts; a streaming url is not one and\n  // must not be revoked. Leaking a blob pins the whole video for the tab's life.\n  useEffect(() => {\n    if (media === null || media.kind !== \"bytes\") return undefined;\n    const url = media.url;\n    return () => URL.revokeObjectURL(url);\n  }, [media]);\n\n  if (media !== null) {\n    return (\n      <div className=\"mx-meet__record-section\">\n        {/* eslint-disable-next-line jsx-a11y/media-has-caption -- the transcript\n            below IS the caption track, and it is on the same screen. */}\n        <video\n          className=\"mx-meet__record-player\"\n          src={media.url}\n          controls\n          preload=\"metadata\"\n          onError={() => {\n            if (media.kind === \"bytes\") {\n              setMedia(null);\n              setError({\n                message: \"The downloaded recording could not be played.\",\n                remedy: PLAYBACK_RETRY_REMEDY,\n              });\n              return;\n            }\n            // The media element does not classify codec, network, and browser\n            // session failures. Retry authorized bytes without guessing why.\n            if (loading) return;\n            setLoading(true);\n            void (async () => {\n              try {\n                setMedia({\n                  url: await host.api.fetchObjectUrl({\n                    path: fileDownloadPath(fileId),\n                    operation: \"meet.recording.play\",\n                  }),\n                  kind: \"bytes\",\n                  fallbackReason: STREAM_REFUSED,\n                });\n              } catch (thrown) {\n                const failure = thrown as { message?: string; remedy?: string };\n                setMedia(null);\n                setError({\n                  message: failure.message ?? \"The recording could not be played.\",\n                  remedy: failure.remedy ?? PLAYBACK_RETRY_REMEDY,\n                });\n              } finally {\n                setLoading(false);\n              }\n            })();\n          }}\n        />\n        {/* 🚨 THE FALLBACK ANNOUNCES ITSELF. When the file had to be downloaded\n            in full before playing, the person who waited deserves to know why. */}\n        {media.fallbackReason !== null ? (\n          <p className=\"mx-meet__panel-note\">{media.fallbackReason}</p>\n        ) : null}\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"mx-meet__record-section\">\n      {error !== null ? (\n        <ErrorBox as=\"div\" className=\"mx-meet__refusal\" error={error} operation=\"Complete this meeting action\" origin=\"meet/components\">\n          <p className=\"mx-meet__refusal-reason\">{error.message}</p>\n          <p className=\"mx-meet__refusal-remedy\">{error.remedy}</p>\n        </ErrorBox>\n      ) : null}\n      <button\n        type=\"button\"\n        className=\"mx-meet__primary mx-meet__record-play\"\n        disabled={loading}\n        onClick={() => {\n          setLoading(true);\n          setError(null);\n          void (async () => {\n            try {\n              // 🚨 THROUGH THE ONE CLIENT (MRI-A16). This call used to be a\n              // bare `fetch` carrying only a bearer token, and aidream answered\n              // 400 `organization_required` — a perfectly landed recording that\n              // the host who made it could not play (MRI-C8).\n              setMedia(await host.api.fileMedia(fileId, \"meet.recording.play\"));\n            } catch (thrown) {\n              const failure = thrown as { message?: string; remedy?: string };\n              setError({\n                message: failure.message ?? \"The recording could not be loaded.\",\n                remedy: failure.remedy ?? PLAYBACK_RETRY_REMEDY,\n              });\n            } finally {\n              setLoading(false);\n            }\n          })();\n        }}\n      >\n        {loading ? \"Loading the recording…\" : \"Play the recording\"}\n      </button>\n    </div>\n  );\n}\n","\"use client\";\n\n/**\n * THE RINGING SURFACE — skin-EXTERNAL (CORE-DESIGN §5.3): an incoming call\n * rings on whatever page the person is on, outside any meeting skin.\n */\n\nimport { useEffect, type ReactNode } from \"react\";\nimport type { CallInvite } from \"../core/types\";\nimport { useCalls } from \"./hooks\";\nimport { useMeetCore } from \"./facade\";\nimport { MeetRoot } from \"./root\";\nimport { MeetAvatar, ControlButton, MeetSkinRoom } from \"../skins/meet/components\";\nimport { CameraOffIcon, PhoneOffIcon } from \"../skins/meet/icons\";\nimport { PhoneIcon } from \"@ai-matrx/design-system/icons\";\n\n// LOAD MARKER (heavy: must never load before the person engages) — read by the page-load trace; no import, no build edge.\nif (typeof window !== \"undefined\") performance.mark(\"load:heavy:Meet calls UI\", { detail: { home: [\"/meet\", \"/meetings\"] } });\n\n/**\n * Mount ONCE, high in the tree. Every incoming call rings here, on whatever\n * surface the user is on (R2).\n */\nexport function IncomingCallHost(): ReactNode {\n  const calls = useCalls();\n  const { call, phase, actions } = useMeetCore();\n\n  // A call I left is over: its screen closes (the meeting machine is back at the start).\n  useEffect(() => {\n    if (call !== null && phase === \"left\") actions.dismissCall();\n  }, [call, phase, actions]);\n\n  // §3.6: an outcome is said, then the card goes away on its own.\n  const outcome = call !== null && (phase === \"call_declined\" || phase === \"call_missed\" || phase === \"call_busy\" || phase === \"answered_elsewhere\");\n  useEffect(() => {\n    if (!outcome) return undefined;\n    const timer = setTimeout(() => actions.dismissCall(), 5_000);\n    return () => clearTimeout(timer);\n  }, [outcome, actions]);\n\n  // §3.6: an ANSWERED call runs on the same machine and the same skin as a meeting.\n  const inCall = call !== null && (phase === \"joining\" || phase === \"in_call\" || phase === \"disconnected\" || phase === \"removed\" || phase === \"superseded\");\n  return (\n    <>\n      {inCall && call !== null ? (\n        <div className=\"mx-meet__call-overlay\" data-meet-call={call.invite.id}>\n          <MeetRoot>\n            <MeetSkinRoom roomName={call.invite.roomName} onLeave={actions.dismissCall} />\n          </MeetRoot>\n        </div>\n      ) : null}\n      {calls.incoming.length > 0 || (call !== null && (phase === \"ringing_out\" || outcome)) ? (\n        <div className=\"mx-meet__ringing-stack\">\n          {call !== null && phase === \"ringing_out\" ? <OutgoingCallCard invite={call.invite} /> : null}\n          {outcome && call !== null ? <CallOutcomeCard invite={call.invite} /> : null}\n          {calls.incoming.map((invite) => (\n            <IncomingCallCard key={invite.id} invite={invite} />\n          ))}\n        </div>\n      ) : null}\n    </>\n  );\n}\n\n/** §3.6 `ringing_out`: the caller sees who they are calling, and can cancel. */\nexport function OutgoingCallCard({ invite }: { invite: CallInvite }): ReactNode {\n  const calls = useCalls();\n  return (\n    <section className=\"mx-meet__ringing\" role=\"status\" aria-label=\"Calling\" data-meet-notice=\"ringing-out\">\n      <MeetAvatar name={invite.callerName} url={invite.callerAvatarUrl} size={56} />\n      <div className=\"mx-meet__ringing-text\">\n        <strong>Calling…</strong>\n        <span>{invite.mode === \"video\" ? \"Video call\" : \"Voice call\"}</span>\n      </div>\n      <div className=\"mx-meet__ringing-actions\">\n        <ControlButton label=\"Cancel call\" danger onClick={() => void calls.cancel(invite)}>\n          <PhoneOffIcon />\n        </ControlButton>\n      </div>\n    </section>\n  );\n}\n\n/** §3.6: declined · missed · busy · answered on another device — said once, then gone. */\nfunction CallOutcomeCard({ invite }: { invite: CallInvite }): ReactNode {\n  const { phase, actions, call } = useMeetCore();\n  const outgoing = call?.direction === \"outgoing\";\n  const text =\n    phase === \"call_declined\"\n      ? \"Call declined\"\n      : phase === \"call_busy\"\n        ? \"They're on another call\"\n        : phase === \"answered_elsewhere\"\n          ? \"Answered on another device\"\n          : outgoing\n            ? \"No answer\"\n            : `Missed call from ${invite.callerName}`;\n  return (\n    <section className=\"mx-meet__ringing\" role=\"status\" aria-label={text} data-meet-call-outcome={phase}>\n      <div className=\"mx-meet__ringing-text\">\n        <strong>{text}</strong>\n      </div>\n      <div className=\"mx-meet__ringing-actions\">\n        <ControlButton label=\"Close\" onClick={actions.dismissCall}>\n          <PhoneOffIcon />\n        </ControlButton>\n      </div>\n    </section>\n  );\n}\n\nexport function IncomingCallCard({ invite }: { invite: CallInvite }): ReactNode {\n  const calls = useCalls();\n  return (\n    <section className=\"mx-meet__ringing\" role=\"alertdialog\" aria-label=\"Incoming call\">\n      <MeetAvatar name={invite.callerName} url={invite.callerAvatarUrl} size={56} />\n      <div className=\"mx-meet__ringing-text\">\n        <strong>{invite.callerName}</strong>\n        <span>{invite.mode === \"video\" ? \"Incoming video call\" : \"Incoming call\"}</span>\n      </div>\n      <div className=\"mx-meet__ringing-actions\">\n        <ControlButton label=\"Decline\" danger onClick={() => void calls.decline(invite)}>\n          <PhoneOffIcon />\n        </ControlButton>\n        {invite.mode === \"video\" ? (\n          <ControlButton\n            label=\"Accept without video\"\n            onClick={() => void calls.accept({ ...invite, mode: \"audio\" })}\n          >\n            <CameraOffIcon />\n          </ControlButton>\n        ) : null}\n        <ControlButton label=\"Accept\" onClick={() => void calls.accept(invite)}>\n          <PhoneIcon width={20} height={20} strokeWidth={1.75} />\n        </ControlButton>\n      </div>\n    </section>\n  );\n}\n\n","/**\n * THE MESSAGING SEAM — a call invitation is an ACTIONABLE MESSAGE (D8).\n *\n * `@ai-matrx/messaging` deliberately knows nothing about meetings; its action\n * registry exists so packages like this one can add a kind without messaging\n * learning about them. This file is that registration, and it is the whole\n * coupling between the two packages.\n *\n * Why an invitation is a message and not only a ring: a ring is EPHEMERAL. If\n * you were away from your desk, a broadcast that expired is gone, and \"someone\n * tried to reach me\" is exactly the information you most needed. The message is\n * the durable half — it is still in the thread tomorrow, with the outcome\n * stamped on it.\n *\n * 🚨 **THE PAYLOAD IS NOT AUTHORIZATION.** The chip's payload says what was\n * ASKED, never what is ALLOWED. The handler re-resolves the invite through the\n * repository (an auth-checked RPC) before it joins anything. Trusting the\n * payload would turn any message anyone can send into a room grant.\n *\n * Idempotence is the registry's, not ours: two tabs and a double tap settle\n * ONCE and share one receipt.\n */\n\nimport type { ActionHandler, ActionReceipt } from \"@ai-matrx/messaging\";\nimport type { CallCenter } from \"./calls\";\nimport { MeetError } from \"./errors\";\nimport type { MeetRepository } from \"./repository\";\nimport { asCallId, asUserId, type CallInvite, type CallMode } from \"./types\";\n\nexport const CALL_INVITE_KIND = \"meet.call-invite\";\nexport const CALL_INVITE_VERSION = 1;\n\nexport interface CallInvitePayload {\n  readonly invite_id: string;\n  readonly room_name: string;\n  readonly mode: CallMode;\n  readonly caller_name: string;\n  readonly expires_at: string;\n}\n\n/** The `action_data` a caller attaches to the invitation message. */\nexport function callInviteAction(invite: CallInvite): {\n  readonly kind: string;\n  readonly version: number;\n  readonly payload: CallInvitePayload;\n} {\n  return {\n    kind: CALL_INVITE_KIND,\n    version: CALL_INVITE_VERSION,\n    payload: {\n      invite_id: invite.id,\n      room_name: invite.roomName,\n      mode: invite.mode,\n      caller_name: invite.callerName,\n      expires_at: invite.expiresAt,\n    },\n  };\n}\n\n/** The message body. Readable on a surface that cannot render the chips. */\nexport function callInviteText(invite: CallInvite): string {\n  return invite.mode === \"video\"\n    ? `${invite.callerName} started a video call`\n    : `${invite.callerName} started an audio call`;\n}\n\nexport interface CallInviteHandlerOptions {\n  calls: CallCenter;\n  repository: MeetRepository;\n  /** Called after a successful accept, with the room to enter. */\n  onJoin: (invite: CallInvite) => void | Promise<void>;\n  now?: (() => number) | undefined;\n}\n\nexport function createCallInviteHandler(\n  options: CallInviteHandlerOptions,\n): ActionHandler<CallInvitePayload> {\n  const now = options.now ?? (() => Date.now());\n\n  return {\n    kind: CALL_INVITE_KIND,\n    versions: [CALL_INVITE_VERSION],\n    choices: (payload) => {\n      // An EXPIRED invite renders no chips. Offering \"Join\" for a call that\n      // ended twenty minutes ago is a dead end with a friendly face.\n      if (Date.parse(payload.expires_at) < now()) return [];\n      return [\n        { id: \"join\", label: payload.mode === \"video\" ? \"Join video\" : \"Join call\", icon: payload.mode === \"video\" ? \"video\" : \"phone\", tone: \"primary\" },\n        { id: \"decline\", label: \"Decline\", tone: \"neutral\" },\n      ];\n    },\n    summarize: (payload) =>\n      payload.mode === \"video\"\n        ? `${payload.caller_name} started a video call`\n        : `${payload.caller_name} started an audio call`,\n    execute: async (payload, context): Promise<ActionReceipt> => {\n      const settledAt = new Date(now()).toISOString();\n      const inviteId = asCallId(payload.invite_id);\n\n      // RE-RESOLVE. The payload told us what to look for; the database tells us\n      // whether it is still true and whether this actor may act on it.\n      // `context.actorId` is messaging's branded UserId; ours is a distinct\n      // brand over the same string. Re-branding through the constructor is the\n      // honest crossing — a cast between two brands would compile today and\n      // hide a genuine mismatch the day either package changes its identity.\n      const pending = await options.repository.pendingInvites(asUserId(String(context.actorId)));\n      const live = pending.find((invite) => invite.id === inviteId) ?? null;\n\n      if (live === null) {\n        return {\n          kind: CALL_INVITE_KIND,\n          messageId: context.messageId,\n          actorId: context.actorId,\n          outcome: \"unavailable\",\n          label: \"This call has ended\",\n          settledAt,\n          detail:\n            \"The invite is no longer ringing — it was answered elsewhere, canceled, or it \" +\n            \"timed out. The chips are replaced by the outcome rather than left clickable.\",\n        };\n      }\n\n      if (context.choice === \"decline\") {\n        await options.calls.decline(inviteId);\n        return {\n          kind: CALL_INVITE_KIND,\n          messageId: context.messageId,\n          actorId: context.actorId,\n          outcome: \"declined\",\n          label: \"Declined\",\n          settledAt,\n        };\n      }\n\n      const accepted = await options.calls.accept(inviteId, live.mode);\n      await options.onJoin(accepted);\n      return {\n        kind: CALL_INVITE_KIND,\n        messageId: context.messageId,\n        actorId: context.actorId,\n        outcome: \"applied\",\n        label: \"Joined\",\n        settledAt,\n      };\n    },\n  };\n}\n\n/**\n * A meeting invitation — the scheduled twin. Deliberately NOT the same kind: a\n * scheduled meeting's chip must never say \"Join call\" three days early, and a\n * receiver that only understands calls must render NOTHING for it rather than a\n * button it cannot honor.\n */\nexport const MEETING_INVITE_KIND = \"meet.meeting-invite\";\nexport const MEETING_INVITE_VERSION = 1;\n\nexport interface MeetingInvitePayload {\n  readonly meeting_id: string;\n  readonly slug: string;\n  readonly title: string;\n  readonly scheduled_for: string | null;\n  readonly link: string;\n}\n\nexport function meetingInviteAction(payload: MeetingInvitePayload): {\n  readonly kind: string;\n  readonly version: number;\n  readonly payload: MeetingInvitePayload;\n} {\n  return { kind: MEETING_INVITE_KIND, version: MEETING_INVITE_VERSION, payload };\n}\n\nexport interface MeetingInviteHandlerOptions {\n  onOpen: (payload: MeetingInvitePayload) => void | Promise<void>;\n  now?: (() => number) | undefined;\n}\n\nexport function createMeetingInviteHandler(\n  options: MeetingInviteHandlerOptions,\n): ActionHandler<MeetingInvitePayload> {\n  const now = options.now ?? (() => Date.now());\n  return {\n    kind: MEETING_INVITE_KIND,\n    versions: [MEETING_INVITE_VERSION],\n    // A DURABLE LINK NEVER EXPIRES (R3) — the chip stays useful after the\n    // meeting too, because that is when people go looking for the notes.\n    choices: () => [{ id: \"open\", label: \"Open meeting\", tone: \"primary\" }],\n    summarize: (payload) =>\n      payload.scheduled_for === null\n        ? payload.title\n        : `${payload.title} — ${payload.scheduled_for}`,\n    execute: async (payload, context): Promise<ActionReceipt> => {\n      if (payload.slug.length === 0) {\n        throw new MeetError(\n          \"invalid-response\",\n          \"meet.meeting-invite: the payload carries no slug\",\n          \"A meeting invitation without a durable slug cannot be opened. Fix the sender; \" +\n            \"never synthesize a link on the receiving side.\",\n        );\n      }\n      await options.onOpen(payload);\n      return {\n        kind: MEETING_INVITE_KIND,\n        messageId: context.messageId,\n        actorId: context.actorId,\n        outcome: \"applied\",\n        label: \"Opened\",\n        settledAt: new Date(now()).toISOString(),\n      };\n    },\n  };\n}\n","/**\n * MEET WAVE 1 — the two server calls a management screen makes (0.8).\n *\n * Every WRITE (schedule, edit, reschedule, cancel, archive, occurrence change,\n * invite, answer) goes straight to the database through `MeetRepository` — the\n * database decides who may. What a browser cannot do is send an email with a\n * calendar object in it, so after any of those writes a screen calls\n * `announceMeeting`: the server tells each invitee exactly what they have not\n * been told (invitation, update or cancellation, each with its `.ics`), and\n * re-queues reminders. It is idempotent — call it after every save.\n */\n\nimport type { MeetApi } from \"./api\";\nimport { refusalFromResponse } from \"./ai\";\nimport { MeetError } from \"./errors\";\nimport { MEET_ROUTES, meetingPath } from \"./tokens\";\nimport type { MeetingId } from \"./types\";\n\nexport interface AnnounceResult {\n  readonly invitations: number;\n  readonly updates: number;\n  readonly cancellations: number;\n  readonly alreadyCurrent: number;\n  readonly remindersQueued: number;\n  readonly remindersCancelled: number;\n}\n\nfunction refusal(response: Response, operation: string): Promise<MeetError> {\n  return refusalFromResponse(\n    response,\n    operation,\n    \"The meeting itself is saved — only the telling failed. Try again; the call is idempotent.\",\n  );\n}\n\nfunction count(body: Record<string, unknown>, key: string): number {\n  const value = body[key];\n  return typeof value === \"number\" ? value : 0;\n}\n\n/** Bring every invitee's inbox and calendar up to date. The host, a co-host or an editor. */\nexport async function announceMeeting(api: MeetApi, meetingId: MeetingId): Promise<AnnounceResult> {\n  const operation = \"meet.announceMeeting\";\n  const response = await api.request({\n    path: meetingPath(MEET_ROUTES.meetingAnnounce, meetingId),\n    method: \"POST\",\n    requireAuth: true,\n    operation,\n  });\n  if (!response.ok) throw await refusal(response, operation);\n  const body = (await response.json()) as Record<string, unknown>;\n  return {\n    invitations: count(body, \"invitations\"),\n    updates: count(body, \"updates\"),\n    cancellations: count(body, \"cancellations\"),\n    alreadyCurrent: count(body, \"already_current\"),\n    remindersQueued: count(body, \"reminders_queued\"),\n    remindersCancelled: count(body, \"reminders_cancelled\"),\n  };\n}\n\n/**\n * Put a one-off meeting on the caller's own connected Google Calendar. GATED by\n * the server to Google's review accounts while the Calendar scope is in review —\n * a refusal is a `forbidden` MeetError carrying the server's sentence. Everyone\n * already gets the meeting into any calendar through the invitation's `.ics`.\n */\nexport async function pushMeetingToGoogleCalendar(\n  api: MeetApi,\n  meetingId: MeetingId,\n  target: { connectionId: string; calendarId?: string },\n): Promise<Record<string, unknown>> {\n  const operation = \"meet.pushMeetingToGoogleCalendar\";\n  const response = await api.request({\n    path: meetingPath(MEET_ROUTES.meetingGoogleCalendar, meetingId),\n    method: \"POST\",\n    requireAuth: true,\n    operation,\n    body: { connection_id: target.connectionId, calendar_id: target.calendarId ?? \"primary\" },\n  });\n  if (!response.ok) throw await refusal(response, operation);\n  return (await response.json()) as Record<string, unknown>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["ms","tabId","import_react","text","row","refusal","text","import_global_slot","ms","pending","current","deviceId","options","num","text","count","text","byId","existing","ms","readState","refusal","import_session_identity","createDataSessionIdentity","import_core","deviceId","text","refusal","byId","media","now","text","deviceId","refusal","text","module","text","deviceId","import_react","import_jsx_runtime","copied","import_react","import_core","when","refusal","upsert","count","text","refusal","import_react","import_controls","import_react","import_react","import_format","import_format","clock","count","import_react","text","import_jsx_runtime","import_react","import_react","import_jsx_runtime","GMicIcon","GMicOffIcon","GCameraIcon","GCameraOffIcon","GScreenShareIcon","GPhoneOffIcon","GHandIcon","GChatIcon","GPeopleIcon","GRecordIcon","GCaptionsIcon","GNotesIcon","GSettingsIcon","GWifiLowIcon","GSmileIcon","GKeyboardIcon","GSpotlightIcon","GSpeakerIcon","GFlagIcon","GActivitiesIcon","GPollIcon","GQuestionIcon","GWhiteboardIcon","GBreakoutIcon","GUpvoteIcon","GEraserIcon","GHighlighterIcon","GUndo2Icon","GChevronUpIcon","import_icons","import_jsx_runtime","text","ms","count","import_icons","import_jsx_runtime","text","ControlSelect","refusal","deviceId","observe","ms","import_react","import_design_system","import_jsx_runtime","notice","import_jsx_runtime","observe","when","import_react","import_icons","import_jsx_runtime","text"]}