@usero/sdk 1.1.9 → 1.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts","../../src/plugins/user-test.ts"],"names":[],"mappings":"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AAA;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;AAAA;AAAA;AAAA;AAAA;A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","file":"user-test.js","sourcesContent":["// Shared types used by both the vanilla and React entry points.\n// Keep this file framework-free so the vanilla bundle never pulls react.\n\nexport type FeedbackRating = 1 | 2 | 3 | 4\n\nexport interface FeedbackMetadata {\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\ttimestamp: number\n}\n\nexport interface ScreenshotData {\n\tfileName: string\n\turl: string\n\tfileSize: number\n\twidth?: number\n\theight?: number\n\tmimeType: string\n}\n\nexport interface FeedbackSubmission {\n\tclientId: string\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\tenvironment?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata?: Record<string, unknown>\n\t// Legacy gzipped + base64-encoded rrweb event stream. The pre-chunked\n\t// session-replay plugin attached this on submit. The chunked-upload\n\t// plugin (>= 0.4.0) does NOT set this — it ships events out-of-band\n\t// via the chunk endpoints and points at the resulting session replay\n\t// via `sessionReplayId` + `replayOffsetMs`. Kept on the wire one\n\t// release for backward compat with old SaaS deployments that only\n\t// know how to ingest the legacy field.\n\treplayEvents?: string\n\t// Pointer to a SessionReplay row created by the session-replay\n\t// plugin's chunked-upload pipeline, plus the offset within that\n\t// recording at submit time so the dashboard can deep-link.\n\tsessionReplayId?: string\n\treplayOffsetMs?: number\n}\n\nexport interface FeedbackData {\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata: FeedbackMetadata\n}\n\n// Customer-supplied identity for the session-replay / identify pipeline.\n// Use the declarative form: pass `user` on the React widget (the SDK\n// diffs and auto-fires identify), or supply `getUser` on the vanilla\n// init (the SDK polls it at session start). An imperative `identify()`\n// call exists as an escape hatch only and is intentionally not\n// documented as the headline API.\nexport type UseroUserTraitValue = string | number | boolean | null\nexport type UseroUserTraits = Record<string, UseroUserTraitValue>\nexport interface UseroUser {\n\tid: string\n\temail?: string\n\tdisplayName?: string\n\ttraits?: UseroUserTraits\n}\n\nexport type WidgetPosition = 'right' | 'left'\n\nexport interface WidgetTheme {\n\tprimary: string\n\tbackground: string\n\ttext: string\n\tborder: string\n\tshadow: string\n}\n\n// Forward-declared to avoid a circular import. The plugin module imports\n// FeedbackSubmission from this file, so we can't import UseroPlugin back\n// up here without a cycle. Keeping the prop typed as an opaque object with\n// the minimal shape the widget actually inspects works fine for consumers.\nexport interface FeedbackWidgetProps {\n\tclientId: string\n\tposition?: WidgetPosition\n\ttheme?: Partial<WidgetTheme>\n\ttitle?: string\n\tplaceholder?: string\n\tshowEmailOption?: boolean\n\tshowScreenshotOption?: boolean\n\tenvironment?: string\n\tbaseUrl?: string\n\tmetadata?: Record<string, unknown>\n\tplugins?: ReadonlyArray<import('./plugin').UseroPlugin>\n\t// Declarative identity. React: pass the current user (or null on\n\t// logout) and the SDK auto-fires identify when the resolved id\n\t// transitions. Vanilla: pass a getter so the SDK can resolve user at\n\t// session start / chunk boundaries. Pass at most one. The SDK never\n\t// invokes both.\n\tuser?: UseroUser | null\n\tgetUser?: () => UseroUser | null | undefined\n\tonSubmit?: (feedback: FeedbackData) => void\n\tonError?: (error: Error) => void\n\tonOpen?: () => void\n\tonClose?: () => void\n}\n\nexport interface SubmissionResponse {\n\tsuccess: boolean\n\terror?: string\n\tid?: string\n\tmessage?: string\n\tdata?: unknown\n}\n\nexport const EMOJI_MAP: Record<FeedbackRating, string> = {\n\t1: '😞',\n\t2: '😐',\n\t3: '😊',\n\t4: '🤩',\n}\n\nexport const RATING_LABELS: Record<FeedbackRating, string> = {\n\t1: 'Needs work',\n\t2: \"It's okay\",\n\t3: 'Pretty good',\n\t4: 'Amazing!',\n}\n\nexport const EMOJI_BACKGROUNDS: Record<FeedbackRating, string> = {\n\t1: 'linear-gradient(135deg,#ff6b6b14,#ff6b6b1f)',\n\t2: 'linear-gradient(135deg,#9ca3af0f,#9ca3af1a)',\n\t3: 'linear-gradient(135deg,#3b82f614,#3b82f61f)',\n\t4: 'linear-gradient(135deg,#f59e0b14,#f59e0b1f)',\n}\n\nexport const DEFAULT_API_URL = 'https://usero.io'\n\nexport const DEFAULT_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#ffffff',\n\ttext: '#374151',\n\tborder: '#e5e7eb',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n}\n\nexport const DARK_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#1f2937',\n\ttext: '#f9fafb',\n\tborder: '#374151',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)',\n}\n\nexport function mergeTheme(customTheme: Partial<WidgetTheme> = {}): WidgetTheme {\n\treturn { ...DEFAULT_THEME, ...customTheme }\n}\n","// User-testing-mode plugin for the Usero widget.\n//\n// Activates ONLY when the host page URL carries `?usero_test=<slug>`. When\n// active, it:\n// 1. Creates a UserTestSession on the SaaS side via\n// POST /api/user-test-sessions\n// 2. Starts a MediaRecorder on the user's microphone (Opus in WebM) and\n// ships chunks every `chunkSeconds` to\n// PUT /api/user-test-sessions/:id/chunk?index=N\n// 3. Renders a small floating \"recording\" indicator with a Finish button\n// bottom-center so the tester can stop on their own.\n// 4. On Finish (or `pagehide` / `visibilitychange` -> hidden), flushes any\n// buffered chunks and calls POST /api/user-test-sessions/:id/finalise.\n//\n// Mic-permission denied is non-fatal: the session is still created (the\n// session-replay plugin keeps recording in parallel) and the indicator\n// shows a \"no audio\" hint. The SaaS side detects audio presence from the\n// first chunk; if no chunks land, hasAudio stays false there too.\n//\n// Bundle hygiene: this module is a subpath export and does NOT depend on\n// rrweb or any other heavy dep — just the native MediaRecorder API. The\n// floating UI is shadow-DOM scoped so host page CSS can't leak in.\n//\n// Privacy: only the microphone is recorded. We never read DOM text, never\n// touch the camera, and never persist audio in the browser past the\n// IndexedDB fallback (cleared on successful upload).\n\nimport type { UseroPlugin, PluginContext } from '../plugin'\nimport { DEFAULT_API_URL } from '../types'\n\nexport interface UserTestOptions {\n\t// URL query param the welcome page appends to redirect testers back.\n\t// Default `usero_test`. Match SaaS side if you ever change it.\n\tqueryParam?: string\n\t// Audio chunk length in seconds. Smaller = more partial-data resilience\n\t// but more requests. Default 10.\n\tchunkSeconds?: number\n\t// API origin. Override for self-hosted or local dev. Defaults to the\n\t// shared SDK constant (https://usero.io).\n\tapiUrl?: string\n\t// Override the tester-name shown on the SaaS side. Normally the welcome\n\t// page collects this and stores it in localStorage; the plugin reads it\n\t// from there. This option lets a host site bypass that.\n\ttesterName?: string\n\t// Hide the floating indicator. The plugin still records and finalises\n\t// on `pagehide`, but the tester gets no on-page UI. Useful if the host\n\t// page wants to render its own.\n\thideIndicator?: boolean\n}\n\ninterface UserTestTask {\n\tid: string\n\tprompt: string\n\tsortOrder: number\n}\n\ninterface MutedSegment {\n\tstartMs: number\n\tendMs: number\n}\n\ninterface InFlightNote {\n\tatMs: number\n\ttext: string\n\tacked: boolean\n\tserverId?: string\n}\n\ninterface RecorderStore {\n\tcancelled: boolean\n\tslug: string\n\tsessionId: string | null\n\tclientId: string | null\n\trecorder: MediaRecorder | null\n\tstream: MediaStream | null\n\tchunkIndex: number\n\tuploadQueue: Promise<void>\n\tpendingUploads: number\n\tstartedAt: number\n\tindicator: HTMLElement | null\n\tindicatorRoot: ShadowRoot | null\n\tindicatorState: 'recording' | 'finishing' | 'done' | 'no-audio' | 'error'\n\tpageHideHandler: (() => void) | null\n\tvisibilityHandler: (() => void) | null\n\toptions: Required<UserTestOptions>\n\ttasks: UserTestTask[]\n\ttasksPanelOpen: boolean\n\toutsidePointerHandler: ((event: PointerEvent) => void) | null\n\tkeydownHandler: ((event: KeyboardEvent) => void) | null\n\t// Mic mute\n\thasMicPermission: boolean\n\t// True while getUserMedia is in flight (pending). Distinguishes the\n\t// \"connecting\" chip state (granted users, promise not yet resolved) from\n\t// the genuinely-failed terminal \"none\" state. Init true; cleared on every\n\t// success/failure exit of startRecording.\n\tmicAcquiring: boolean\n\t// Why mic acquisition failed, for actionable terminal copy. 'blocked' =\n\t// permission denied (NotAllowedError), 'not-found' = no device\n\t// (NotFoundError), 'unsupported' = MediaRecorder/getUserMedia missing or\n\t// constructor threw. Null while acquiring or once granted.\n\tmicFailReason: 'blocked' | 'not-found' | 'unsupported' | null\n\tmuted: boolean\n\tmutedSinceMs: number | null\n\tmutedSegments: MutedSegment[]\n\tmuteToastShown: boolean\n\tmuteToastTimers: number[]\n\t// In-flight notes\n\tnotes: InFlightNote[]\n\tnotesPopoverOpen: boolean\n\tnotePopoverAtMs: number | null\n\t// End-of-test comment (collected on thanks screen)\n\tendNote: string\n\t// Re-entry guard for finishFlow.\n\tfinishFlowRan: boolean\n\t// Offset (ms) into the session-replay recording at the moment THIS\n\t// user-test session started. Captured once at start (not at finalise)\n\t// so it pins the test timeline to the recording timeline. Null when no\n\t// replay is active (plugin not loaded, sampled out, or host predates\n\t// the core accessor); finalise then omits replayOffsetMs.\n\treplayOffsetAtStartMs: number | null\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<UserTestOptions, 'testerName' | 'apiUrl'>> & {\n\ttesterName: string\n\tapiUrl: string\n} = {\n\tqueryParam: 'usero_test',\n\t// 10s (not 30) so at most ~10s of audio is at risk if the tab is torn\n\t// down before a flush, and so a session shorter than the old 30s window\n\t// still emits at least one chunk (previously its single buffered chunk was\n\t// never flushed and its audio was lost). Tradeoff: ~3x the R2 writes /\n\t// upload requests per session; 10s is an acceptable balance, don't go lower.\n\tchunkSeconds: 10,\n\tapiUrl: DEFAULT_API_URL,\n\ttesterName: '',\n\thideIndicator: false,\n}\n\nconst TESTER_NAME_STORAGE_KEY = 'usero:user-test:tester-name'\nconst TASKS_PANEL_OPEN_STORAGE_KEY = 'usero:user-test:tasks-panel-open'\nconst IDB_NAME = 'usero-user-test'\nconst IDB_STORE = 'pending-chunks'\n\ninterface PendingChunk {\n\tid: string\n\tsessionId: string\n\tapiUrl: string\n\tchunkIndex: number\n\tblob: Blob\n\tcreatedAt: number\n}\n\nfunction readTesterName(override: string): string | undefined {\n\tif (override) return override\n\ttry {\n\t\tconst stored = window.localStorage?.getItem(TESTER_NAME_STORAGE_KEY)\n\t\tif (stored && stored.trim()) return stored.trim().slice(0, 120)\n\t} catch {\n\t\t// Storage access can throw in some sandboxed iframes — ignore.\n\t}\n\treturn undefined\n}\n\n// Read the `uts` (user-test session) id the entry screen appends when it\n// creates the session server-side. When present, the SDK ADOPTS that session\n// instead of minting its own (so the session has the participant's email from\n// creation, no double-session). Absent for open tests using the old link\n// shape, where the SDK falls back to createSession.\nfunction getAdoptSessionId(): string | null {\n\tif (typeof window === 'undefined' || typeof window.location === 'undefined') return null\n\ttry {\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst raw = params.get('uts')\n\t\tif (!raw) return null\n\t\tconst cleaned = raw.trim().slice(0, 64)\n\t\t// Session ids are cuids: lowercase alphanumerics. Reject anything else.\n\t\tif (!/^[a-z0-9]+$/i.test(cleaned)) return null\n\t\treturn cleaned\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getTestSlug(queryParam: string): string | null {\n\tif (typeof window === 'undefined' || typeof window.location === 'undefined') return null\n\ttry {\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst slug = params.get(queryParam)\n\t\tif (!slug) return null\n\t\tconst cleaned = slug.trim().slice(0, 64)\n\t\tif (!/^[a-z0-9-]+$/i.test(cleaned)) return null\n\t\treturn cleaned\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction isMediaRecorderSupported(): boolean {\n\treturn typeof window !== 'undefined' && typeof window.MediaRecorder !== 'undefined' && typeof navigator !== 'undefined' && !!navigator.mediaDevices?.getUserMedia\n}\n\nfunction pickMimeType(): string | undefined {\n\tconst candidates = ['audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/mp4']\n\tfor (const candidate of candidates) {\n\t\tif (typeof MediaRecorder !== 'undefined' && MediaRecorder.isTypeSupported?.(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn undefined\n}\n\n// IndexedDB helpers. Best-effort, never throw upstream — if IDB is missing\n// or quota-blown we just lose offline resilience but the live upload path\n// still runs.\nfunction idbOpen(): Promise<IDBDatabase | null> {\n\treturn new Promise(resolve => {\n\t\tif (typeof indexedDB === 'undefined') {\n\t\t\tresolve(null)\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst req = indexedDB.open(IDB_NAME, 1)\n\t\t\treq.onupgradeneeded = (): void => {\n\t\t\t\tconst db = req.result\n\t\t\t\tif (!db.objectStoreNames.contains(IDB_STORE)) {\n\t\t\t\t\tdb.createObjectStore(IDB_STORE, { keyPath: 'id' })\n\t\t\t\t}\n\t\t\t}\n\t\t\treq.onsuccess = (): void => resolve(req.result)\n\t\t\treq.onerror = (): void => resolve(null)\n\t\t} catch {\n\t\t\tresolve(null)\n\t\t}\n\t})\n}\n\nasync function idbStashChunk(chunk: PendingChunk): Promise<void> {\n\tconst db = await idbOpen()\n\tif (!db) return\n\tawait new Promise<void>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readwrite')\n\t\t\ttx.objectStore(IDB_STORE).put(chunk)\n\t\t\ttx.oncomplete = (): void => resolve()\n\t\t\ttx.onerror = (): void => resolve()\n\t\t\ttx.onabort = (): void => resolve()\n\t\t} catch {\n\t\t\tresolve()\n\t\t}\n\t})\n\tdb.close()\n}\n\nasync function idbDeleteChunk(id: string): Promise<void> {\n\tconst db = await idbOpen()\n\tif (!db) return\n\tawait new Promise<void>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readwrite')\n\t\t\ttx.objectStore(IDB_STORE).delete(id)\n\t\t\ttx.oncomplete = (): void => resolve()\n\t\t\ttx.onerror = (): void => resolve()\n\t\t\ttx.onabort = (): void => resolve()\n\t\t} catch {\n\t\t\tresolve()\n\t\t}\n\t})\n\tdb.close()\n}\n\nasync function idbListChunks(sessionId: string): Promise<PendingChunk[]> {\n\tconst db = await idbOpen()\n\tif (!db) return []\n\tconst items = await new Promise<PendingChunk[]>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readonly')\n\t\t\tconst req = tx.objectStore(IDB_STORE).getAll()\n\t\t\treq.onsuccess = (): void => {\n\t\t\t\tconst all = (req.result as PendingChunk[]) ?? []\n\t\t\t\tresolve(all.filter(c => c.sessionId === sessionId))\n\t\t\t}\n\t\t\treq.onerror = (): void => resolve([])\n\t\t} catch {\n\t\t\tresolve([])\n\t\t}\n\t})\n\tdb.close()\n\treturn items\n}\n\nasync function uploadChunkWithRetry(\n\tapiUrl: string,\n\tsessionId: string,\n\tindex: number,\n\tblob: Blob,\n\tlogger: PluginContext['logger'],\n\tmaxAttempts = 5,\n): Promise<boolean> {\n\tconst url = `${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/chunk?index=${index}`\n\tlet attempt = 0\n\twhile (attempt < maxAttempts) {\n\t\ttry {\n\t\t\tconst res = await fetch(url, {\n\t\t\t\tmethod: 'PUT',\n\t\t\t\tbody: blob,\n\t\t\t\theaders: { 'Content-Type': blob.type || 'audio/webm' },\n\t\t\t\tkeepalive: blob.size <= 60 * 1024, // browsers cap keepalive bodies\n\t\t\t})\n\t\t\tif (res.ok) return true\n\t\t\t// 4xx (other than 413) won't get better with retries; bail early.\n\t\t\tif (res.status >= 400 && res.status < 500 && res.status !== 408 && res.status !== 429) {\n\t\t\t\tlogger.error(`chunk ${index} rejected with ${res.status}`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger.warn(`chunk ${index} upload attempt ${attempt + 1} failed`, err)\n\t\t}\n\t\tattempt += 1\n\t\tconst backoff = Math.min(15000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250)\n\t\tawait new Promise(resolve => setTimeout(resolve, backoff))\n\t}\n\treturn false\n}\n\ninterface IndicatorCallbacks {\n\tonFinish: () => void\n\tonToggleTasks: () => void\n\tonToggleMute: () => void\n\tonOpenNote: () => void\n}\n\nfunction buildIndicator(host: HTMLElement, store: RecorderStore, callbacks: IndicatorCallbacks): ShadowRoot {\n\tconst root = host.attachShadow({ mode: 'closed' })\n\tconst style = document.createElement('style')\n\t// Compact, glassy dark pill. Mic chip is now a real button with three\n\t// states (recording / muted / no-mic). Notes button sits beside it.\n\tstyle.textContent = `\n\t\t:host { all: initial; }\n\t\t.anchor {\n\t\t\tposition: fixed;\n\t\t\tbottom: calc(env(safe-area-inset-bottom, 0px) + 16px);\n\t\t\tleft: 50%; transform: translateX(-50%);\n\t\t\tdisplay: flex; flex-direction: column; align-items: center; gap: 8px;\n\t\t\tz-index: 2147483646; max-width: calc(100vw - 32px);\n\t\t\tfont: 13px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n\t\t\tcolor: #fff;\n\t\t}\n\t\t.bar {\n\t\t\tdisplay: inline-flex; align-items: center; gap: 6px;\n\t\t\tpadding: 6px 8px 6px 6px;\n\t\t\tbackground: rgba(17,17,17,0.82);\n\t\t\tborder: 1px solid rgba(255,255,255,0.08);\n\t\t\tborder-radius: 999px;\n\t\t\tbox-shadow: 0 8px 24px rgba(0,0,0,0.22);\n\t\t\tbackdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);\n\t\t\tmax-width: 100%;\n\t\t}\n\t\t.panel {\n\t\t\tbackground: rgba(17,17,17,0.92);\n\t\t\tborder: 1px solid rgba(255,255,255,0.08);\n\t\t\tborder-radius: 14px; padding: 12px 14px 12px 8px;\n\t\t\tline-height: 1.45;\n\t\t\tbox-shadow: 0 12px 32px rgba(0,0,0,0.32);\n\t\t\tmax-height: min(60vh, 480px);\n\t\t\tmax-width: min(420px, calc(100vw - 32px));\n\t\t\twidth: max-content; overflow-y: auto;\n\t\t}\n\t\t.panel[hidden] { display: none; }\n\t\t.panel ol { margin: 0; padding-left: 26px; }\n\t\t.panel li { margin: 0 0 8px; }\n\t\t.panel li:last-child { margin: 0; }\n\n\t\t/* Mic chip: pill-within-pill with dot + label, doubles as mute toggle. */\n\t\t.mic {\n\t\t\tdisplay: inline-flex; align-items: center; gap: 7px;\n\t\t\tmin-height: 32px; min-width: 44px;\n\t\t\tpadding: 0 11px 0 10px;\n\t\t\tborder-radius: 999px;\n\t\t\tbackground: rgba(255,255,255,0.06);\n\t\t\tborder: 1px solid rgba(255,255,255,0.06);\n\t\t\tcolor: #fff; font: inherit;\n\t\t\tcursor: pointer; appearance: none;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n\t\t}\n\t\t.mic:hover { background: rgba(255,255,255,0.12); }\n\t\t.mic:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.mic[data-mic-state=\"muted\"] {\n\t\t\tbackground: rgba(251, 191, 36, 0.18);\n\t\t\tborder-color: rgba(251, 191, 36, 0.45);\n\t\t\tcolor: #fcd34d;\n\t\t}\n\t\t.mic[data-mic-state=\"muted\"]:hover { background: rgba(251, 191, 36, 0.26); }\n\t\t/* Connecting: getUserMedia pending. Steady amber tint reads as \"working\",\n\t\t distinct from the live red pulse and the failed state below. The icon\n\t\t gets a gentle non-pulsing breathe so it feels alive without alarming. */\n\t\t.mic[data-mic-state=\"connecting\"] {\n\t\t\tbackground: rgba(251, 191, 36, 0.14);\n\t\t\tborder-color: rgba(251, 191, 36, 0.32);\n\t\t\tcolor: #fcd34d;\n\t\t\tcursor: default;\n\t\t}\n\t\t.mic[data-mic-state=\"connecting\"]:hover { background: rgba(251, 191, 36, 0.14); }\n\t\t.mic[data-mic-state=\"connecting\"] .mic-icon {\n\t\t\tcolor: #fbbf24;\n\t\t\tanimation: micBreathe 1.4s ease-in-out infinite;\n\t\t}\n\t\t/* Failed terminal state, actionable. Tappable affordance: clearer border,\n\t\t pointer cursor, brightens on hover/focus to invite the retry tap. */\n\t\t.mic[data-mic-state=\"none\"] {\n\t\t\tbackground: rgba(255,255,255,0.05);\n\t\t\tborder-color: rgba(255,255,255,0.14);\n\t\t\tcolor: rgba(255,255,255,0.72);\n\t\t\tcursor: pointer;\n\t\t}\n\t\t.mic[data-mic-state=\"none\"]:hover {\n\t\t\tbackground: rgba(255,255,255,0.12);\n\t\t\tborder-color: rgba(255,255,255,0.24);\n\t\t\tcolor: #fff;\n\t\t}\n\t\t@keyframes micBreathe {\n\t\t\t0%, 100% { opacity: 0.55; }\n\t\t\t50% { opacity: 1; }\n\t\t}\n\t\t.mic-icon { width: 13px; height: 13px; display: inline-block; flex-shrink: 0; }\n\t\t.mic-label { font-weight: 500; letter-spacing: 0.01em; white-space: nowrap; }\n\n\t\t.dot {\n\t\t\twidth: 7px; height: 7px; border-radius: 50%;\n\t\t\tbackground: #ef4444;\n\t\t\tbox-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6);\n\t\t\tanimation: pulse 1.6s ease-out infinite;\n\t\t\tflex-shrink: 0;\n\t\t}\n\t\t.dot[data-state=\"no-audio\"] { background: #fbbf24; animation: none; }\n\t\t.dot[data-state=\"finishing\"] { background: #fbbf24; animation: none; }\n\t\t.dot[data-state=\"done\"] { background: #10b981; animation: none; }\n\t\t.dot[data-state=\"error\"] { background: #ef4444; animation: none; }\n\n\t\t.btn {\n\t\t\tappearance: none; border: 0; background: rgba(255,255,255,0.10);\n\t\t\tcolor: #fff; font: inherit; font-weight: 600;\n\t\t\tpadding: 6px 12px; min-height: 32px; border-radius: 999px; cursor: pointer;\n\t\t\ttransition: background 0.15s ease, transform 0.06s ease;\n\t\t\tdisplay: inline-flex; align-items: center; gap: 6px;\n\t\t}\n\t\t.btn:hover { background: rgba(255,255,255,0.20); }\n\t\t.btn:active { transform: scale(0.97); }\n\t\t.btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.btn[disabled] { opacity: 0.5; cursor: progress; }\n\t\t.tasks-btn[aria-expanded=\"true\"] { background: rgba(255,255,255,0.24); }\n\n\t\t/* Note button: icon-only, matches mic chip footprint */\n\t\t.note-btn {\n\t\t\twidth: 32px; min-height: 32px; padding: 0;\n\t\t\tbackground: rgba(255,255,255,0.06);\n\t\t\tborder: 1px solid rgba(255,255,255,0.06);\n\t\t\tborder-radius: 999px;\n\t\t\tdisplay: inline-flex; align-items: center; justify-content: center; gap: 4px;\n\t\t\tcolor: #fff; font: inherit; cursor: pointer; appearance: none;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease, width 0.18s ease;\n\t\t\toverflow: hidden;\n\t\t}\n\t\t.note-btn:hover { background: rgba(255,255,255,0.14); }\n\t\t.note-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.note-btn[data-has-notes=\"true\"] { width: auto; padding: 0 10px 0 9px; gap: 6px; }\n\t\t.note-btn[aria-expanded=\"true\"] { background: rgba(255,255,255,0.22); border-color: rgba(255,255,255,0.18); }\n\t\t.note-icon { width: 14px; height: 14px; display: inline-block; }\n\t\t.note-count { font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }\n\n\t\t.spacer { width: 1px; height: 18px; background: rgba(255,255,255,0.14); margin: 0 1px; }\n\n\t\t@media (max-width: 480px) {\n\t\t\t.bar { gap: 4px; padding: 5px 6px 5px 5px; }\n\t\t\t.btn { padding: 7px 12px; min-height: 38px; }\n\t\t\t.mic, .note-btn { min-height: 38px; }\n\t\t\t.note-btn { width: 38px; }\n\t\t\t.note-btn[data-has-notes=\"true\"] { width: auto; }\n\t\t}\n\n\t\t/* First-mute helper toast: sits above the pill, auto-dismisses */\n\t\t.toast {\n\t\t\tbackground: rgba(17,17,17,0.92);\n\t\t\tborder: 1px solid rgba(251, 191, 36, 0.45);\n\t\t\tcolor: #fff;\n\t\t\tpadding: 9px 14px; border-radius: 12px;\n\t\t\tmax-width: min(340px, calc(100vw - 32px));\n\t\t\tbox-shadow: 0 12px 28px rgba(0,0,0,0.28);\n\t\t\ttext-align: center; line-height: 1.4;\n\t\t\tanimation: toast-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);\n\t\t}\n\t\t.toast[data-leaving=\"true\"] { animation: toast-out 0.24s ease forwards; }\n\t\t.toast strong { color: #fcd34d; font-weight: 600; }\n\t\t@keyframes toast-in {\n\t\t\tfrom { opacity: 0; transform: translateY(6px); }\n\t\t\tto { opacity: 1; transform: translateY(0); }\n\t\t}\n\t\t@keyframes toast-out {\n\t\t\tto { opacity: 0; transform: translateY(4px); }\n\t\t}\n\n\t\t/* Notes popover */\n\t\t.note-popover {\n\t\t\tbackground: rgba(17,17,17,0.94);\n\t\t\tborder: 1px solid rgba(255,255,255,0.10);\n\t\t\tborder-radius: 14px; padding: 12px;\n\t\t\twidth: min(340px, calc(100vw - 32px));\n\t\t\tbox-shadow: 0 18px 40px rgba(0,0,0,0.36);\n\t\t\tdisplay: flex; flex-direction: column; gap: 10px;\n\t\t\tanimation: pop-in 0.18s cubic-bezier(0.2, 0.8, 0.2, 1);\n\t\t}\n\t\t.note-popover[hidden] { display: none; }\n\t\t@keyframes pop-in {\n\t\t\tfrom { opacity: 0; transform: translateY(6px) scale(0.98); }\n\t\t\tto { opacity: 1; transform: translateY(0) scale(1); }\n\t\t}\n\t\t.note-head {\n\t\t\tcolor: rgba(255,255,255,0.7); font-size: 12px;\n\t\t\tfont-weight: 500; letter-spacing: 0.02em;\n\t\t}\n\t\t.note-textarea {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tmin-height: 80px; resize: vertical;\n\t\t\tpadding: 10px 11px;\n\t\t\tbackground: rgba(0,0,0,0.35);\n\t\t\tborder: 1px solid rgba(255,255,255,0.10);\n\t\t\tborder-radius: 10px;\n\t\t\tcolor: #fff; font: inherit; font-size: 13.5px;\n\t\t\tline-height: 1.45;\n\t\t\ttransition: border-color 0.15s ease;\n\t\t}\n\t\t.note-textarea:focus { outline: none; border-color: rgba(255,255,255,0.32); }\n\t\t.note-textarea::placeholder { color: rgba(255,255,255,0.42); }\n\t\t.note-actions {\n\t\t\tdisplay: flex; align-items: center; justify-content: space-between; gap: 8px;\n\t\t}\n\t\t.note-actions .hint {\n\t\t\tcolor: rgba(255,255,255,0.45); font-size: 11px;\n\t\t}\n\t\t.note-actions .group { display: inline-flex; gap: 6px; }\n\t\t.note-actions .btn { padding: 6px 12px; font-size: 12.5px; min-height: 32px; }\n\t\t.btn-primary { background: #fff !important; color: #111; }\n\t\t.btn-primary:hover { background: rgba(255,255,255,0.85) !important; }\n\t\t.btn-ghost { background: transparent; color: rgba(255,255,255,0.7); }\n\t\t.btn-ghost:hover { background: rgba(255,255,255,0.10); color: #fff; }\n\n\t\t/* ---- Finished screen (complete + ended-early). Usero warm-stone palette,\n\t\t shadow-DOM scoped so host CSS can't leak in. Scrollable so the primary\n\t\t action stays reachable on a short phone with the keyboard open. ---- */\n\t\t.thanks {\n\t\t\tposition: fixed; inset: 0;\n\t\t\tdisplay: flex; align-items: flex-start; justify-content: center;\n\t\t\tbackground: rgba(28, 25, 23, 0.62);\n\t\t\tbackdrop-filter: blur(8px);\n\t\t\t-webkit-backdrop-filter: blur(8px);\n\t\t\tcolor: #1c1917;\n\t\t\tfont-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n\t\t\tz-index: 2147483647;\n\t\t\tpadding: 24px 16px calc(env(safe-area-inset-bottom, 0px) + 24px);\n\t\t\toverflow-y: auto;\n\t\t\t-webkit-overflow-scrolling: touch;\n\t\t}\n\t\t.thanks-card {\n\t\t\tbackground: #fff; color: #1c1917;\n\t\t\tborder-radius: 22px; padding: 30px 24px 24px;\n\t\t\tmax-width: 400px; width: 100%;\n\t\t\tmargin: auto 0;\n\t\t\tbox-shadow: 0 24px 60px rgba(28, 25, 23, 0.28), 0 2px 8px rgba(28, 25, 23, 0.12);\n\t\t\ttext-align: left;\n\t\t\tanimation: thanks-in 0.34s cubic-bezier(0.16, 1, 0.3, 1);\n\t\t}\n\t\t@keyframes thanks-in {\n\t\t\tfrom { opacity: 0; transform: translateY(14px) scale(0.985); }\n\t\t\tto { opacity: 1; transform: translateY(0) scale(1); }\n\t\t}\n\t\t.thanks-card .head { text-align: center; }\n\t\t.thanks h2 {\n\t\t\tmargin: 0 0 7px; font-size: 22px; line-height: 1.2;\n\t\t\tfont-weight: 600; letter-spacing: -0.018em; color: #1c1917;\n\t\t}\n\t\t.thanks .lede {\n\t\t\tmargin: 0 auto 22px; font-size: 14.5px; line-height: 1.5;\n\t\t\tcolor: #57534e; text-align: center; max-width: 30ch;\n\t\t}\n\n\t\t/* Status medallion: green tick when complete, warm ring when ended early */\n\t\t.thanks .check {\n\t\t\twidth: 56px; height: 56px; border-radius: 50%;\n\t\t\tdisplay: grid; place-items: center;\n\t\t\tmargin: 0 auto 16px;\n\t\t}\n\t\t.thanks .check.ok {\n\t\t\tbackground: #ecfdf5;\n\t\t\tbox-shadow: inset 0 0 0 1px rgba(16,185,129,0.22);\n\t\t\tcolor: #059669;\n\t\t}\n\t\t.thanks .check.ok svg { width: 26px; height: 26px; }\n\t\t.thanks .check.early {\n\t\t\tbackground: #fff7ed;\n\t\t\tbox-shadow: inset 0 0 0 1px rgba(234,88,12,0.20);\n\t\t\tcolor: #ea580c;\n\t\t}\n\t\t.thanks .check.early svg { width: 24px; height: 24px; }\n\n\t\t/* Verified-checks list (complete) / progress list (ended early) */\n\t\t.thanks .checks {\n\t\t\tlist-style: none; margin: 0 0 4px; padding: 0;\n\t\t\tborder: 1px solid #f0eeec; border-radius: 14px;\n\t\t\tbackground: #fafaf9; overflow: hidden;\n\t\t}\n\t\t.thanks .checks li {\n\t\t\tdisplay: flex; align-items: center; gap: 11px;\n\t\t\tpadding: 12px 14px; font-size: 14px; color: #292524;\n\t\t\tborder-top: 1px solid #f0eeec;\n\t\t}\n\t\t.thanks .checks li:first-child { border-top: 0; }\n\t\t.thanks .checks .ic {\n\t\t\twidth: 20px; height: 20px; border-radius: 50%;\n\t\t\tdisplay: grid; place-items: center; flex-shrink: 0;\n\t\t}\n\t\t.thanks .checks .ic.done { background: #d1fae5; color: #059669; }\n\t\t.thanks .checks .ic.todo { background: #f5f5f4; color: #a8a29e; box-shadow: inset 0 0 0 1px #e7e5e4; }\n\t\t.thanks .checks .ic svg { width: 12px; height: 12px; }\n\t\t.thanks .checks li.muted-row { color: #78716c; }\n\n\t\t/* Payout block (complete) */\n\t\t.thanks .payout { margin-top: 20px; }\n\t\t.thanks .payout-q {\n\t\t\tfont-size: 12px; font-weight: 600; letter-spacing: 0.04em;\n\t\t\ttext-transform: uppercase; color: #a8a29e;\n\t\t\tmargin: 0 0 10px;\n\t\t}\n\t\t.thanks .pay-primary {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; cursor: pointer;\n\t\t\tbackground: #ea580c; color: #fff;\n\t\t\tpadding: 15px 18px; border-radius: 14px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 15.5px;\n\t\t\tline-height: 1.3; text-align: center;\n\t\t\tbox-shadow: 0 6px 16px rgba(234, 88, 12, 0.28);\n\t\t\ttransition: background 0.15s ease, transform 0.07s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .pay-primary:hover { background: #c2410c; }\n\t\t.thanks .pay-primary:active { transform: scale(0.985); }\n\t\t.thanks .pay-primary:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .pay-primary[disabled] { opacity: 0.6; cursor: progress; box-shadow: none; }\n\t\t.thanks .pay-primary .amt { font-variant-numeric: tabular-nums; }\n\t\t.thanks .pay-alt {\n\t\t\tdisplay: block; width: 100%;\n\t\t\tmargin-top: 12px; padding: 4px;\n\t\t\tbackground: none; border: 0; cursor: pointer;\n\t\t\tfont: inherit; font-size: 13px; font-weight: 500;\n\t\t\tcolor: #78716c; text-align: center;\n\t\t\ttext-decoration: underline; text-underline-offset: 2px;\n\t\t\ttransition: color 0.15s ease;\n\t\t}\n\t\t.thanks .pay-alt:hover { color: #44403c; }\n\t\t.thanks .pay-alt:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; border-radius: 6px; }\n\t\t.thanks [hidden] { display: none !important; }\n\n\t\t/* Alternate-email expander */\n\t\t.thanks .pay-edit { margin-top: 14px; animation: pop-in 0.2s cubic-bezier(0.2,0.8,0.2,1); }\n\t\t.thanks .pay-edit[hidden] { display: none; }\n\t\t.thanks .pay-label {\n\t\t\tdisplay: block; margin: 0 0 7px;\n\t\t\tfont-size: 13px; font-weight: 500; color: #44403c;\n\t\t}\n\t\t.thanks .pay-input {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tpadding: 12px 13px;\n\t\t\tbackground: #fff; border: 1px solid #e7e5e4; border-radius: 11px;\n\t\t\tfont: inherit; font-size: 15px; color: #1c1917;\n\t\t\ttransition: border-color 0.15s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .pay-input:focus {\n\t\t\toutline: none; border-color: #ea580c;\n\t\t\tbox-shadow: 0 0 0 3px rgba(234, 88, 12, 0.16);\n\t\t}\n\t\t.thanks .pay-input::placeholder { color: #a8a29e; }\n\t\t.thanks .pay-eta {\n\t\t\tmargin: 14px 0 0; font-size: 12px; line-height: 1.45;\n\t\t\tcolor: #a8a29e; text-align: center;\n\t\t}\n\n\t\t/* Ended-early \"what unlocks the reward\" note */\n\t\t.thanks .early-note {\n\t\t\tdisplay: flex; align-items: flex-start; gap: 10px;\n\t\t\tmargin-top: 18px; padding: 13px 14px;\n\t\t\tbackground: #fff7ed; border: 1px solid #fed7aa; border-radius: 13px;\n\t\t\tfont-size: 13.5px; line-height: 1.45; color: #9a3412;\n\t\t}\n\t\t.thanks .early-note svg { width: 17px; height: 17px; flex-shrink: 0; margin-top: 1px; color: #ea580c; }\n\t\t.thanks .early-actions { margin-top: 18px; display: flex; flex-direction: column; gap: 10px; }\n\t\t.thanks .resume-btn {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; cursor: pointer;\n\t\t\tbackground: #ea580c; color: #fff;\n\t\t\tpadding: 15px 18px; border-radius: 14px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 15.5px;\n\t\t\tbox-shadow: 0 6px 16px rgba(234, 88, 12, 0.28);\n\t\t\ttransition: background 0.15s ease, transform 0.07s ease;\n\t\t}\n\t\t.thanks .resume-btn:hover { background: #c2410c; }\n\t\t.thanks .resume-btn:active { transform: scale(0.985); }\n\t\t.thanks .resume-btn:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .exit-btn {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; background: none; cursor: pointer;\n\t\t\tpadding: 4px; font: inherit; font-size: 13px; line-height: 1.45;\n\t\t\tcolor: #78716c; text-align: center;\n\t\t}\n\t\t.thanks .exit-btn:hover { color: #44403c; }\n\t\t.thanks .exit-btn:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; border-radius: 6px; }\n\n\t\t/* End-of-test note (shown after payout is set, complete path only) */\n\t\t.thanks .note-section {\n\t\t\tmargin-top: 22px; padding-top: 20px;\n\t\t\tborder-top: 1px solid #f0eeec;\n\t\t}\n\t\t.thanks .end-label {\n\t\t\tdisplay: block; margin: 0 0 8px;\n\t\t\tfont-size: 13px; font-weight: 500; color: #44403c;\n\t\t}\n\t\t.thanks .end-textarea {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tmin-height: 84px; resize: vertical;\n\t\t\tpadding: 12px 13px;\n\t\t\tbackground: #fafaf9;\n\t\t\tborder: 1px solid #e7e5e4;\n\t\t\tborder-radius: 12px;\n\t\t\tfont: inherit; font-size: 14.5px; line-height: 1.5;\n\t\t\tcolor: #1c1917;\n\t\t\ttransition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .end-textarea:focus {\n\t\t\toutline: none; border-color: #ea580c; background: #fff;\n\t\t\tbox-shadow: 0 0 0 3px rgba(234, 88, 12, 0.14);\n\t\t}\n\t\t.thanks .end-textarea::placeholder { color: #a8a29e; }\n\t\t.thanks .end-actions {\n\t\t\tdisplay: flex; gap: 10px; margin-top: 14px;\n\t\t}\n\t\t.thanks .end-actions button {\n\t\t\tflex: 1;\n\t\t\tappearance: none; border: 1px solid #e7e5e4;\n\t\t\tbackground: #fff; color: #44403c;\n\t\t\tpadding: 12px 14px; border-radius: 12px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 14px;\n\t\t\tcursor: pointer;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease;\n\t\t}\n\t\t.thanks .end-actions button:hover { background: #fafaf9; border-color: #d6d3d1; }\n\t\t.thanks .end-actions button.primary {\n\t\t\tbackground: #1c1917; color: #fff; border-color: #1c1917; flex: 1.4;\n\t\t}\n\t\t.thanks .end-actions button.primary:hover { background: #292524; border-color: #292524; }\n\t\t.thanks .end-actions button:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .end-hint {\n\t\t\tmargin: 11px 0 0; font-size: 11.5px; color: #a8a29e; text-align: center;\n\t\t}\n\t\t.thanks .end-sent {\n\t\t\tmargin-top: 16px; text-align: center; color: #57534e; font-size: 13.5px; line-height: 1.45;\n\t\t}\n\t\t@media (prefers-reduced-motion: reduce) {\n\t\t\t.thanks-card, .thanks .pay-edit { animation: none; }\n\t\t}\n\n\t\t@keyframes pulse {\n\t\t\t0% { box-shadow: 0 0 0 0 rgba(239,68,68,0.55); }\n\t\t\t70% { box-shadow: 0 0 0 10px rgba(239,68,68,0); }\n\t\t\t100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); }\n\t\t}\n\t\t@media (prefers-reduced-motion: reduce) {\n\t\t\t.dot { animation: none; }\n\t\t\t.toast, .note-popover { animation: none; }\n\t\t}\n\t`\n\tconst anchor = document.createElement('div')\n\tanchor.className = 'anchor'\n\n\tconst panel = document.createElement('div')\n\tpanel.className = 'panel'\n\tpanel.hidden = true\n\n\t// Toast slot: helper messages render here above the bar.\n\tconst toastSlot = document.createElement('div')\n\ttoastSlot.className = 'toast-slot'\n\n\t// Notes popover slot: rendered above the bar when open.\n\tconst notePopover = document.createElement('div')\n\tnotePopover.className = 'note-popover'\n\tnotePopover.hidden = true\n\n\tconst bar = document.createElement('div')\n\tbar.className = 'bar'\n\tbar.setAttribute('role', 'status')\n\tbar.setAttribute('aria-live', 'polite')\n\n\t// Mic chip = real button. Three states driven by data-mic-state.\n\tconst micBtn = document.createElement('button')\n\tmicBtn.type = 'button'\n\tmicBtn.className = 'mic'\n\tmicBtn.setAttribute('data-mic-state', 'recording')\n\tmicBtn.setAttribute('aria-pressed', 'false')\n\tmicBtn.setAttribute('aria-label', 'Mute microphone')\n\n\tconst dot = document.createElement('span')\n\tdot.className = 'dot'\n\tdot.setAttribute('data-state', store.indicatorState)\n\n\tconst micIcon = document.createElement('span')\n\tmicIcon.className = 'mic-icon'\n\tmicIcon.innerHTML = MIC_ICON_SVG\n\tmicIcon.setAttribute('aria-hidden', 'true')\n\n\tconst micLabel = document.createElement('span')\n\tmicLabel.className = 'mic-label'\n\tmicLabel.textContent = 'Recording'\n\n\tmicBtn.appendChild(dot)\n\tmicBtn.appendChild(micIcon)\n\tmicBtn.appendChild(micLabel)\n\tmicBtn.addEventListener('click', callbacks.onToggleMute)\n\tbar.appendChild(micBtn)\n\n\t// Notes button: icon-only by default, grows to show count once notes exist.\n\tconst noteBtn = document.createElement('button')\n\tnoteBtn.type = 'button'\n\tnoteBtn.className = 'note-btn'\n\tnoteBtn.setAttribute('aria-label', 'Add a timestamped note')\n\tnoteBtn.setAttribute('aria-expanded', 'false')\n\tnoteBtn.setAttribute('data-has-notes', 'false')\n\tnoteBtn.innerHTML = `<span class=\"note-icon\" aria-hidden=\"true\">${NOTE_ICON_SVG}</span><span class=\"note-count\" hidden></span>`\n\tnoteBtn.addEventListener('click', callbacks.onOpenNote)\n\tbar.appendChild(noteBtn)\n\n\tconst spacer = document.createElement('span')\n\tspacer.className = 'spacer'\n\tbar.appendChild(spacer)\n\n\tconst btn = document.createElement('button')\n\tbtn.type = 'button'\n\tbtn.className = 'btn finish-btn'\n\tbtn.textContent = 'Finish'\n\tbtn.addEventListener('click', callbacks.onFinish)\n\tbar.appendChild(btn)\n\n\tif (store.tasks.length > 0) installTasksToggle(bar, btn, store, callbacks.onToggleTasks)\n\n\tanchor.appendChild(panel)\n\tanchor.appendChild(toastSlot)\n\tanchor.appendChild(notePopover)\n\tanchor.appendChild(bar)\n\n\troot.appendChild(style)\n\troot.appendChild(anchor)\n\treturn root\n}\n\n// Inline SVGs kept tiny. currentColor so they inherit the chip text color.\nconst MIC_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\"><path d=\"M8 1.5a2 2 0 0 0-2 2v4a2 2 0 1 0 4 0v-4a2 2 0 0 0-2-2Z\" fill=\"currentColor\"/><path d=\"M4 7.5a4 4 0 0 0 8 0M8 11.5v3M5.5 14.5h5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`\nconst MIC_MUTED_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\"><path d=\"M8 1.5a2 2 0 0 0-2 2v3.2L10 11V3.5a2 2 0 0 0-2-2Z\" fill=\"currentColor\"/><path d=\"M4 7.5a4 4 0 0 0 6.5 3.12M12 7.5a4 4 0 0 1-.3 1.5M8 11.5v3M5.5 14.5h5M2 2l12 12\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`\nconst NOTE_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\"><path d=\"M3 3.5A1.5 1.5 0 0 1 4.5 2h7A1.5 1.5 0 0 1 13 3.5V10a1.5 1.5 0 0 1-1.5 1.5H7L4 14v-2.5h-.5A1.5 1.5 0 0 1 2 10V3.5A1.5 1.5 0 0 1 3.5 3\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\n// Thanks-screen icons: bold tick (medallion + done rows) and a clock (ended early).\nconst TICK_ICON_SVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 12.5 10 17.5 19 7\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst TICK_SM_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 8.5 6.5 11.5 12.5 5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst CLOCK_ICON_SVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"12\" cy=\"12\" r=\"8.4\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M12 7.5V12l3 2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst SPARK_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 1.5 9.5 6.5 14.5 8 9.5 9.5 8 14.5 6.5 9.5 1.5 8 6.5 6.5Z\" fill=\"currentColor\"/></svg>`\n\nfunction installTasksToggle(bar: HTMLElement, finishBtn: HTMLElement, store: RecorderStore, onToggleTasks: () => void): void {\n\tconst tasksBtn = document.createElement('button')\n\ttasksBtn.type = 'button'\n\ttasksBtn.className = 'btn tasks-btn'\n\ttasksBtn.textContent = `Tasks (${store.tasks.length})`\n\ttasksBtn.setAttribute('aria-expanded', store.tasksPanelOpen ? 'true' : 'false')\n\ttasksBtn.addEventListener('click', onToggleTasks)\n\tbar.insertBefore(tasksBtn, finishBtn)\n}\n\nfunction renderTasksPanel(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst panel = root.querySelector('.panel')\n\tif (!(panel instanceof HTMLElement)) return\n\t// Build content once.\n\tif (!panel.firstChild && store.tasks.length > 0) {\n\t\tconst ol = document.createElement('ol')\n\t\tfor (const task of store.tasks) {\n\t\t\tconst li = document.createElement('li')\n\t\t\tli.textContent = task.prompt\n\t\t\tol.appendChild(li)\n\t\t}\n\t\tpanel.appendChild(ol)\n\t}\n\tpanel.hidden = !store.tasksPanelOpen\n\tconst tasksBtn = root.querySelector('.tasks-btn')\n\tif (tasksBtn instanceof HTMLElement) {\n\t\ttasksBtn.setAttribute('aria-expanded', store.tasksPanelOpen ? 'true' : 'false')\n\t}\n}\n\nfunction readTasksPanelOpen(): boolean {\n\ttry { return window.sessionStorage?.getItem(TASKS_PANEL_OPEN_STORAGE_KEY) === '1' } catch { return false }\n}\nfunction writeTasksPanelOpen(open: boolean): void {\n\ttry { window.sessionStorage?.setItem(TASKS_PANEL_OPEN_STORAGE_KEY, open ? '1' : '0') } catch { /* ignore */ }\n}\n\nfunction micChipState(store: RecorderStore): 'recording' | 'muted' | 'none' | 'connecting' | 'inactive' {\n\tif (store.indicatorState === 'finishing' || store.indicatorState === 'done' || store.indicatorState === 'error') {\n\t\treturn 'inactive'\n\t}\n\tif (!store.hasMicPermission) {\n\t\t// Pending getUserMedia: show \"connecting\" so granted users never flash\n\t\t// the failure copy. Once startRecording resolves or rejects it clears\n\t\t// micAcquiring, and we fall through to the terminal \"none\" state.\n\t\tif (store.micAcquiring) return 'connecting'\n\t\treturn 'none'\n\t}\n\treturn store.muted ? 'muted' : 'recording'\n}\n\nfunction renderIndicatorState(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst dot = root.querySelector('.dot')\n\tconst mic = root.querySelector<HTMLButtonElement>('.mic')\n\tconst micIcon = root.querySelector('.mic-icon')\n\tconst micLabel = root.querySelector('.mic-label')\n\tconst btn = root.querySelector<HTMLButtonElement>('.finish-btn')\n\tif (!(dot instanceof HTMLElement) || !mic || !(micIcon instanceof HTMLElement) || !(micLabel instanceof HTMLElement) || !btn) return\n\n\tdot.setAttribute('data-state', store.indicatorState)\n\tconst chipState = micChipState(store)\n\tmic.setAttribute('data-mic-state', chipState === 'inactive' ? 'none' : chipState)\n\t// Distinguish \"acquiring\" (genuinely failed, actionable) from \"connecting\"\n\t// at the attribute level so the dot/visuals key off the right state. The\n\t// failed terminal chip is a retry affordance; mark it so CSS can style it.\n\tmic.removeAttribute('data-mic-fail')\n\tif (chipState === 'none') mic.setAttribute('data-mic-fail', store.micFailReason ?? 'blocked')\n\n\t// Finish-button copy is driven by the indicatorState (network / lifecycle).\n\tswitch (store.indicatorState) {\n\t\tcase 'recording':\n\t\tcase 'no-audio':\n\t\t\tbtn.textContent = 'Finish'\n\t\t\tbtn.disabled = false\n\t\t\tbreak\n\t\tcase 'finishing':\n\t\t\tbtn.textContent = 'Saving'\n\t\t\tbtn.disabled = true\n\t\t\tbreak\n\t\tcase 'done':\n\t\t\tbtn.textContent = 'Done'\n\t\t\tbtn.disabled = true\n\t\t\tbreak\n\t\tcase 'error':\n\t\t\tbtn.textContent = 'Retry'\n\t\t\tbtn.disabled = false\n\t\t\tbreak\n\t}\n\n\t// Mic chip copy + icon. Replay continues in all states; the chip only\n\t// describes the audio track.\n\tswitch (chipState) {\n\t\tcase 'recording':\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent = 'Recording'\n\t\t\tmic.setAttribute('aria-label', 'Mute microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\tcase 'muted':\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tmicLabel.textContent = 'Muted'\n\t\t\tmic.setAttribute('aria-label', 'Unmute microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'true')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\tcase 'connecting':\n\t\t\t// getUserMedia still pending. Granted users sit here briefly instead\n\t\t\t// of flashing the failure copy. Not yet a toggle, so unfocusable.\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent = 'Connecting mic'\n\t\t\tmic.setAttribute('aria-label', 'Connecting microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.setAttribute('tabindex', '-1')\n\t\t\tbreak\n\t\tcase 'none': {\n\t\t\t// Genuinely failed terminal state. Actionable: the chip is a button\n\t\t\t// that re-attempts mic acquisition. Keyboard-focusable (no tabindex\n\t\t\t// -1). Replay keeps recording regardless.\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tconst failLabel =\n\t\t\t\tstore.micFailReason === 'not-found' ? 'No mic found, tap to retry' :\n\t\t\t\t'Mic blocked, tap to retry'\n\t\t\tconst failAria =\n\t\t\t\tstore.micFailReason === 'not-found'\n\t\t\t\t\t? 'No microphone found, tap to retry. Replay continues.'\n\t\t\t\t\t: 'Microphone blocked, tap to retry. Replay continues.'\n\t\t\tmicLabel.textContent = failLabel\n\t\t\tmic.setAttribute('aria-label', failAria)\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\t}\n\t\tcase 'inactive':\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent =\n\t\t\t\tstore.indicatorState === 'finishing' ? 'Saving' :\n\t\t\t\tstore.indicatorState === 'done' ? 'Saved' :\n\t\t\t\t'Save failed'\n\t\t\tmic.setAttribute('aria-label', 'Recording stopped')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.setAttribute('tabindex', '-1')\n\t\t\tbreak\n\t}\n}\n\nfunction renderNotesCount(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst noteBtn = root.querySelector('.note-btn')\n\tconst count = root.querySelector('.note-count')\n\tif (!(noteBtn instanceof HTMLElement) || !(count instanceof HTMLElement)) return\n\tconst n = store.notes.length\n\tnoteBtn.setAttribute('data-has-notes', n > 0 ? 'true' : 'false')\n\tif (n > 0) {\n\t\tcount.textContent = String(n)\n\t\tcount.hidden = false\n\t\tnoteBtn.setAttribute('aria-label', `Add a timestamped note (${n} so far)`)\n\t} else {\n\t\tcount.textContent = ''\n\t\tcount.hidden = true\n\t\tnoteBtn.setAttribute('aria-label', 'Add a timestamped note')\n\t}\n}\n\nfunction showMuteToast(store: RecorderStore): void {\n\tif (store.muteToastShown) return\n\tstore.muteToastShown = true\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst slot = root.querySelector('.toast-slot')\n\tif (!(slot instanceof HTMLElement)) return\n\tslot.innerHTML = ''\n\tconst toast = document.createElement('div')\n\ttoast.className = 'toast'\n\ttoast.setAttribute('role', 'status')\n\ttoast.innerHTML = `<strong>Mic off.</strong> Screen is still recording. Tap to unmute.`\n\tslot.appendChild(toast)\n\tconst outer = window.setTimeout(() => {\n\t\tif (!toast.isConnected) return\n\t\ttoast.setAttribute('data-leaving', 'true')\n\t\tconst inner = window.setTimeout(() => {\n\t\t\tif (toast.isConnected) toast.remove()\n\t\t}, 260)\n\t\tstore.muteToastTimers.push(inner)\n\t}, 3000)\n\tstore.muteToastTimers.push(outer)\n}\n\nfunction openNotePopover(store: RecorderStore, onSave: (text: string) => void, onCancel: () => void): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst pop = root.querySelector('.note-popover')\n\tconst noteBtn = root.querySelector('.note-btn')\n\tif (!(pop instanceof HTMLElement) || !(noteBtn instanceof HTMLElement)) return\n\n\tstore.notesPopoverOpen = true\n\tstore.notePopoverAtMs = Date.now() - store.startedAt\n\tnoteBtn.setAttribute('aria-expanded', 'true')\n\n\tpop.innerHTML = ''\n\tconst head = document.createElement('div')\n\thead.className = 'note-head'\n\thead.innerHTML = `<span>Add a note</span>`\n\n\tconst form = document.createElement('form')\n\tform.style.cssText = 'display:flex;flex-direction:column;gap:10px;margin:0;'\n\tform.noValidate = true\n\n\tconst ta = document.createElement('textarea')\n\tta.className = 'note-textarea'\n\tta.placeholder = 'What just happened? Confusing? Surprising? Broken?'\n\tta.rows = 3\n\tta.setAttribute('aria-label', 'Note text')\n\n\tconst actions = document.createElement('div')\n\tactions.className = 'note-actions'\n\tconst hint = document.createElement('span')\n\thint.className = 'hint'\n\thint.innerHTML = '<kbd style=\"font-family:inherit\">Cmd</kbd>+Enter to save'\n\tconst group = document.createElement('div')\n\tgroup.className = 'group'\n\tconst cancelBtn = document.createElement('button')\n\tcancelBtn.type = 'button'\n\tcancelBtn.className = 'btn btn-ghost'\n\tcancelBtn.textContent = 'Cancel'\n\tconst saveBtn = document.createElement('button')\n\tsaveBtn.type = 'submit'\n\tsaveBtn.className = 'btn btn-primary'\n\tsaveBtn.textContent = 'Save'\n\tgroup.appendChild(cancelBtn)\n\tgroup.appendChild(saveBtn)\n\tactions.appendChild(hint)\n\tactions.appendChild(group)\n\n\tform.appendChild(ta)\n\tform.appendChild(actions)\n\n\tpop.appendChild(head)\n\tpop.appendChild(form)\n\tpop.hidden = false\n\n\tconst submit = (): void => {\n\t\tconst text = ta.value.trim()\n\t\tif (!text) { onCancel(); return }\n\t\tonSave(text)\n\t}\n\tform.addEventListener('submit', e => { e.preventDefault(); submit() })\n\tcancelBtn.addEventListener('click', () => onCancel())\n\tta.addEventListener('keydown', e => {\n\t\tif ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n\t\t\te.preventDefault()\n\t\t\tsubmit()\n\t\t} else if (e.key === 'Escape') {\n\t\t\te.preventDefault()\n\t\t\tonCancel()\n\t\t}\n\t})\n\n\t// Autofocus on next frame so animation can finish without scroll jank.\n\twindow.requestAnimationFrame(() => { ta.focus({ preventScroll: true }) })\n}\n\nfunction closeNotePopover(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst pop = root.querySelector('.note-popover')\n\tconst noteBtn = root.querySelector('.note-btn')\n\tif (pop instanceof HTMLElement) {\n\t\tpop.hidden = true\n\t\tpop.innerHTML = ''\n\t}\n\tif (noteBtn instanceof HTMLElement) noteBtn.setAttribute('aria-expanded', 'false')\n\tstore.notesPopoverOpen = false\n\tstore.notePopoverAtMs = null\n}\n\n// Escape user-controlled strings before they touch innerHTML. The payout email\n// comes from our own DB, but it originated as participant input, so treat it as\n// untrusted and never interpolate it raw into markup.\nfunction escapeHtml(value: string): string {\n\treturn value\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;')\n\t\t.replace(/\"/g, '&quot;')\n\t\t.replace(/'/g, '&#39;')\n}\n\nfunction isValidEmail(value: string): boolean {\n\t// Pragmatic check; the server re-validates with zod .email().\n\treturn /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n}\n\ninterface ThanksOptions {\n\t// Payment summary from the first finalise response. Null when the server is\n\t// older / didn't return it: we fall back to the neutral note-only screen.\n\tpayment: PaymentSummary | null\n\t// Confirm the participant's payout destination. Resolves true on success.\n\tonPayout: (destination: string | null) => Promise<boolean>\n\t// End-of-test wrap-up note (complete path). Throws on failure so the UI can retry.\n\tonSubmitNote: (text: string) => Promise<void> | void\n\tonSkip: () => void\n\t// Re-arm recording and dismiss the overlay (ended-early path \"Resume\").\n\tonResume: () => void\n}\n\nfunction showThanksScreen(root: ShadowRoot, opts: ThanksOptions): void {\n\tconst overlay = document.createElement('div')\n\toverlay.className = 'thanks'\n\toverlay.setAttribute('role', 'dialog')\n\toverlay.setAttribute('aria-modal', 'true')\n\n\tconst card = document.createElement('div')\n\tcard.className = 'thanks-card'\n\toverlay.appendChild(card)\n\troot.appendChild(overlay)\n\n\t// Ended-early branch: warmer, non-punishing, keep Resume primary.\n\tif (opts.payment && !opts.payment.qualified) {\n\t\trenderEndedEarly(card, opts)\n\t\treturn\n\t}\n\n\t// Complete branch (also the fallback when payment is null: a clean \"saved\"\n\t// confirmation with the wrap-up note, no payout block since we have no data).\n\trenderComplete(card, opts)\n}\n\n// Builds the verified-checks list. `done` rows get the green tick; an unfinished\n// tasks row (ended-early) gets the hollow todo dot.\nfunction checksList(rows: Array<{ label: string; done: boolean; muted?: boolean }>): string {\n\tconst items = rows\n\t\t.map(r => {\n\t\t\tconst icClass = r.done ? 'ic done' : 'ic todo'\n\t\t\tconst icon = r.done ? TICK_SM_SVG : ''\n\t\t\tconst liClass = r.muted ? ' class=\"muted-row\"' : ''\n\t\t\treturn `<li${liClass}><span class=\"${icClass}\" aria-hidden=\"true\">${icon}</span><span>${escapeHtml(r.label)}</span></li>`\n\t\t})\n\t\t.join('')\n\treturn `<ul class=\"checks\">${items}</ul>`\n}\n\nfunction renderComplete(card: HTMLElement, opts: ThanksOptions): void {\n\tconst payment = opts.payment\n\tconst reward = payment?.reward ?? null\n\tconst defaultEmail = payment?.payoutEmail ?? null\n\tconst tasksTotal = payment?.tasksTotal ?? 0\n\n\tconst head = document.createElement('div')\n\thead.className = 'head'\n\tconst lede = reward\n\t\t? `We have your recording. Confirm where to send your ${escapeHtml(reward)} and the team will review it shortly.`\n\t\t: 'We have your recording. Thanks for taking the time to walk us through it.'\n\thead.innerHTML = `\n\t\t<div class=\"check ok\" aria-hidden=\"true\">${TICK_ICON_SVG}</div>\n\t\t<h2>You're done.</h2>\n\t\t<p class=\"lede\">${lede}</p>\n\t\t${tasksTotal > 0\n\t\t\t? checksList([\n\t\t\t\t\t{ label: tasksTotal === 1 ? '1 task completed' : `All ${tasksTotal} tasks completed`, done: true },\n\t\t\t\t\t{ label: 'Voice recording captured', done: true },\n\t\t\t\t\t{ label: 'Screen replay uploaded', done: true },\n\t\t\t\t])\n\t\t\t: checksList([\n\t\t\t\t\t{ label: 'Voice recording captured', done: true },\n\t\t\t\t\t{ label: 'Screen replay uploaded', done: true },\n\t\t\t\t])}\n\t`\n\tcard.appendChild(head)\n\n\t// If we have no payment data (older server) skip payout entirely and go\n\t// straight to the wrap-up note.\n\tif (!payment) {\n\t\tappendNoteSection(card, opts, 'Your session was saved. Anything you would add?')\n\t\treturn\n\t}\n\n\trenderPayout(card, opts, reward, defaultEmail)\n}\n\n// Payout capture: one-tap default to the sign-up email, with a quieter expander\n// to use a different email. Progressive disclosure (the default path is not a form).\nfunction renderPayout(card: HTMLElement, opts: ThanksOptions, reward: string | null, defaultEmail: string | null): void {\n\tconst wrap = document.createElement('div')\n\twrap.className = 'payout'\n\n\tconst rewardLabel = reward ?? 'my reward'\n\tconst haveDefault = !!defaultEmail && isValidEmail(defaultEmail)\n\n\twrap.innerHTML = `\n\t\t<p class=\"payout-q\">Where should we send ${escapeHtml(reward ?? 'your reward')}?</p>\n\t\t<button type=\"button\" class=\"pay-primary\" ${haveDefault ? '' : 'hidden'}>\n\t\t\tSend <span class=\"amt\">${escapeHtml(rewardLabel)}</span>${haveDefault ? ` to ${escapeHtml(defaultEmail as string)}` : ''}\n\t\t</button>\n\t\t<button type=\"button\" class=\"pay-alt\">${haveDefault ? 'Use a different email' : 'Add your payout email'}</button>\n\t\t<div class=\"pay-edit\" ${haveDefault ? 'hidden' : ''}>\n\t\t\t<label class=\"pay-label\" for=\"usero-payout-email\">Payout email</label>\n\t\t\t<input id=\"usero-payout-email\" class=\"pay-input\" type=\"email\" inputmode=\"email\"\n\t\t\t\tautocomplete=\"email\" placeholder=\"you@example.com\" value=\"${haveDefault ? '' : escapeHtml(defaultEmail ?? '')}\" />\n\t\t</div>\n\t\t<p class=\"pay-eta\">Reward arrives within about 2 days of the team reviewing it.</p>\n\t`\n\tcard.appendChild(wrap)\n\n\tconst primary = wrap.querySelector<HTMLButtonElement>('.pay-primary')\n\tconst altLink = wrap.querySelector<HTMLButtonElement>('.pay-alt')\n\tconst editBox = wrap.querySelector<HTMLElement>('.pay-edit')\n\tconst emailInput = wrap.querySelector<HTMLInputElement>('.pay-input')\n\tif (!primary || !altLink || !editBox || !emailInput) return\n\n\tconst confirm = async (destination: string | null): Promise<void> => {\n\t\tprimary.disabled = true\n\t\taltLink.style.pointerEvents = 'none'\n\t\tconst ok = await opts.onPayout(destination)\n\t\t// Whatever the network outcome, the session is payable (server defaults to\n\t\t// the sign-up email). Move the participant forward rather than trapping them.\n\t\twrap.remove()\n\t\tconst confirmedTo = destination ?? defaultEmail\n\t\tconst sentMsg = confirmedTo\n\t\t\t? `${reward ? `${reward} is` : \"Your reward is\"} set to go to ${confirmedTo}.`\n\t\t\t: 'Your reward is on its way.'\n\t\tconst note = ok ? sentMsg : `${sentMsg} (We will retry sending the details.)`\n\t\tappendNoteSection(card, opts, `${note} Anything you would add before you go?`)\n\t}\n\n\t// One-tap default path.\n\tprimary.addEventListener('click', () => { void confirm(null) })\n\n\t// Expander: reveal the email field, focus it, submit on Enter.\n\tconst openEditor = (): void => {\n\t\tprimary.hidden = true\n\t\taltLink.hidden = true\n\t\teditBox.hidden = false\n\t\t// Append a confirm button under the input on first open.\n\t\tif (!editBox.querySelector('.pay-confirm')) {\n\t\t\tconst btn = document.createElement('button')\n\t\t\tbtn.type = 'button'\n\t\t\tbtn.className = 'pay-primary pay-confirm'\n\t\t\tbtn.style.marginTop = '12px'\n\t\t\tbtn.textContent = reward ? `Send ${reward} here` : 'Use this email'\n\t\t\teditBox.appendChild(btn)\n\t\t\tbtn.addEventListener('click', () => void submitEmail())\n\t\t}\n\t\twindow.requestAnimationFrame(() => emailInput.focus({ preventScroll: true }))\n\t}\n\n\tconst submitEmail = async (): Promise<void> => {\n\t\tconst value = emailInput.value.trim().toLowerCase()\n\t\tif (!isValidEmail(value)) {\n\t\t\temailInput.focus()\n\t\t\temailInput.style.borderColor = '#dc2626'\n\t\t\treturn\n\t\t}\n\t\tawait confirm(value)\n\t}\n\n\taltLink.addEventListener('click', openEditor)\n\temailInput.addEventListener('input', () => { emailInput.style.borderColor = '' })\n\temailInput.addEventListener('keydown', e => {\n\t\tif (e.key === 'Enter') { e.preventDefault(); void submitEmail() }\n\t})\n}\n\nfunction renderEndedEarly(card: HTMLElement, opts: ThanksOptions): void {\n\tconst payment = opts.payment\n\tconst done = payment?.tasksDone ?? 0\n\tconst total = payment?.tasksTotal ?? 0\n\tconst reward = payment?.reward ?? null\n\n\tconst head = document.createElement('div')\n\thead.className = 'head'\n\tconst lede = total > 0\n\t\t? `We saw ${done} of ${total} ${total === 1 ? 'task' : 'tasks'} finished. No worries, you can pick up right where you left off.`\n\t\t: 'It looks like the session ended before you finished. No worries, you can pick up where you left off.'\n\thead.innerHTML = `\n\t\t<div class=\"check early\" aria-hidden=\"true\">${CLOCK_ICON_SVG}</div>\n\t\t<h2>Looks like you stopped early</h2>\n\t\t<p class=\"lede\">${lede}</p>\n\t`\n\tcard.appendChild(head)\n\n\t// Per-task progress when we know the counts: done rows ticked, the rest hollow.\n\tif (total > 0) {\n\t\tconst rows: Array<{ label: string; done: boolean }> = []\n\t\tfor (let i = 0; i < total; i += 1) {\n\t\t\trows.push({ label: `Task ${i + 1}`, done: i < done })\n\t\t}\n\t\tconst list = document.createElement('div')\n\t\tlist.innerHTML = checksList(rows)\n\t\tconst ul = list.firstElementChild\n\t\tif (ul) card.appendChild(ul)\n\t}\n\n\tconst note = document.createElement('div')\n\tnote.className = 'early-note'\n\tnote.innerHTML = `${SPARK_ICON_SVG}<span><strong style=\"font-weight:600\">Resume the test.</strong> ${\n\t\treward ? `Your ${escapeHtml(reward)} reward unlocks` : 'The reward unlocks'\n\t} once all ${total > 0 ? total : 'the'} ${total === 1 ? 'task is' : 'tasks are'} done.</span>`\n\tcard.appendChild(note)\n\n\tconst actions = document.createElement('div')\n\tactions.className = 'early-actions'\n\tconst resume = document.createElement('button')\n\tresume.type = 'button'\n\tresume.className = 'resume-btn'\n\tresume.textContent = 'Resume where I left off'\n\tconst exit = document.createElement('button')\n\texit.type = 'button'\n\texit.className = 'exit-btn'\n\texit.textContent = \"Thanks for trying. No reward this time since the tasks weren't finished.\"\n\tactions.appendChild(resume)\n\tactions.appendChild(exit)\n\tcard.appendChild(actions)\n\n\tresume.addEventListener('click', () => {\n\t\tconst overlay = card.closest('.thanks')\n\t\tif (overlay instanceof HTMLElement) overlay.remove()\n\t\topts.onResume()\n\t})\n\texit.addEventListener('click', () => {\n\t\tcard.innerHTML = ''\n\t\tconst sent = document.createElement('p')\n\t\tsent.className = 'end-sent'\n\t\tsent.textContent = 'Thanks for giving it a go. You can close this tab now.'\n\t\tcard.appendChild(sent)\n\t})\n}\n\n// The wrap-up note section, shared by the complete path (after payout) and the\n// older-server fallback. Mirrors the prior behaviour: Cmd/Ctrl+Enter to send,\n// retry on failure, skip allowed.\nfunction appendNoteSection(card: HTMLElement, opts: ThanksOptions, prompt: string): void {\n\tconst section = document.createElement('div')\n\tsection.className = 'note-section'\n\n\tconst form = document.createElement('form')\n\tform.noValidate = true\n\tform.innerHTML = `\n\t\t<label class=\"end-label\" for=\"usero-end-note\">${escapeHtml(prompt)}</label>\n\t\t<textarea\n\t\t\tid=\"usero-end-note\"\n\t\t\tclass=\"end-textarea\"\n\t\t\trows=\"3\"\n\t\t\tplaceholder=\"Confusing bits, things you liked, what you'd change...\"\n\t\t></textarea>\n\t\t<div class=\"end-actions\">\n\t\t\t<button type=\"button\" class=\"skip\">Skip</button>\n\t\t\t<button type=\"submit\" class=\"primary\">Send feedback</button>\n\t\t</div>\n\t\t<p class=\"end-hint\">Cmd or Ctrl plus Enter to send. Either button is fine.</p>\n\t`\n\tsection.appendChild(form)\n\tcard.appendChild(section)\n\n\tconst ta = form.querySelector<HTMLTextAreaElement>('#usero-end-note')\n\tconst skipBtn = form.querySelector<HTMLButtonElement>('button.skip')\n\tif (!ta || !skipBtn) return\n\n\tconst swapToSent = (message: string): void => {\n\t\tsection.remove()\n\t\tconst sent = document.createElement('p')\n\t\tsent.className = 'end-sent'\n\t\tsent.textContent = message\n\t\tcard.appendChild(sent)\n\t}\n\n\tconst ERROR_CLASS = 'end-error'\n\tconst showError = (message: string): void => {\n\t\tconst prior = form.querySelector(`.${ERROR_CLASS}`)\n\t\tif (prior) prior.remove()\n\t\tconst err = document.createElement('p')\n\t\terr.className = ERROR_CLASS\n\t\terr.textContent = message\n\t\terr.setAttribute('role', 'alert')\n\t\terr.style.cssText = 'margin:10px 0 0;font-size:12.5px;color:#b91c1c;text-align:center;'\n\t\tform.appendChild(err)\n\t}\n\n\tconst submit = async (): Promise<void> => {\n\t\tconst text = ta.value.trim()\n\t\tta.disabled = true\n\t\tskipBtn.disabled = true\n\t\tconst submitBtn = form.querySelector<HTMLButtonElement>('button.primary')\n\t\tif (submitBtn) submitBtn.disabled = true\n\t\tif (text) {\n\t\t\ttry {\n\t\t\t\tawait Promise.race([\n\t\t\t\t\tPromise.resolve(opts.onSubmitNote(text)),\n\t\t\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\t\t\twindow.setTimeout(() => reject(new Error('timeout')), 30000)\n\t\t\t\t\t}),\n\t\t\t\t])\n\t\t\t\tswapToSent('Thanks. You can close this tab.')\n\t\t\t} catch {\n\t\t\t\tta.disabled = false\n\t\t\t\tskipBtn.disabled = false\n\t\t\t\tif (submitBtn) submitBtn.disabled = false\n\t\t\t\tshowError(\"Couldn't save your note. Try again?\")\n\t\t\t}\n\t\t} else {\n\t\t\topts.onSkip()\n\t\t\tswapToSent('All set. You can close this tab.')\n\t\t}\n\t}\n\n\tform.addEventListener('submit', e => { e.preventDefault(); void submit() })\n\tskipBtn.addEventListener('click', () => { ta.value = ''; void submit() })\n\tta.addEventListener('keydown', e => {\n\t\tif ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n\t\t\te.preventDefault()\n\t\t\tvoid submit()\n\t\t}\n\t})\n\n\twindow.requestAnimationFrame(() => { ta.focus({ preventScroll: true }) })\n}\n\nfunction parseTasks(raw: unknown): UserTestTask[] {\n\tif (!Array.isArray(raw)) return []\n\tconst out = raw.flatMap((item: unknown): UserTestTask[] => {\n\t\tconst t = item as { id?: unknown; prompt?: unknown; sortOrder?: unknown }\n\t\tif (!t || typeof t.id !== 'string' || typeof t.prompt !== 'string' || typeof t.sortOrder !== 'number') return []\n\t\treturn [{ id: t.id, prompt: t.prompt, sortOrder: t.sortOrder }]\n\t})\n\tout.sort((a, b) => a.sortOrder - b.sortOrder)\n\treturn out\n}\n\nasync function createSession(\n\tapiUrl: string,\n\tslug: string,\n\ttesterName: string | undefined,\n): Promise<{ sessionId: string; clientId: string; tasks: UserTestTask[] } | null> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ slug, ...(testerName ? { testerName } : {}) }),\n\t\t})\n\t\tif (!res.ok) return null\n\t\tconst json = (await res.json()) as { sessionId?: unknown; clientId?: unknown; tasks?: unknown }\n\t\tif (typeof json.sessionId !== 'string' || typeof json.clientId !== 'string') return null\n\t\treturn { sessionId: json.sessionId, clientId: json.clientId, tasks: parseTasks(json.tasks) }\n\t} catch {\n\t\treturn null\n\t}\n}\n\n// Adopt an existing session the entry screen already created (carried via the\n// `uts` URL param). GET the clientId + tasks for it; we do NOT create a new\n// session. Returns null on any failure so the caller can surface the error\n// state (we deliberately do NOT silently fall back to createSession here: a\n// present-but-unresolvable uts means something is wrong, and creating a second\n// anonymous session is exactly the double-session bug we're avoiding).\nasync function adoptSession(\n\tapiUrl: string,\n\tsessionId: string,\n): Promise<{ sessionId: string; clientId: string; tasks: UserTestTask[] } | null> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/adopt`, {\n\t\t\tmethod: 'GET',\n\t\t})\n\t\tif (!res.ok) return null\n\t\tconst json = (await res.json()) as { sessionId?: unknown; clientId?: unknown; tasks?: unknown }\n\t\tif (typeof json.sessionId !== 'string' || typeof json.clientId !== 'string') return null\n\t\treturn { sessionId: json.sessionId, clientId: json.clientId, tasks: parseTasks(json.tasks) }\n\t} catch {\n\t\treturn null\n\t}\n}\n\ninterface FinaliseNote {\n\tatMs: number\n\ttext: string\n}\n\n// Participant-facing payment summary the finalise endpoint returns on the FIRST\n// call. Drives the finished screen: `qualified` picks the complete vs ended-early\n// layout, `reward` is the formatted headline (e.g. \"$15\"), `payoutEmail` seeds the\n// one-tap payout default, tasksDone/tasksTotal drive the ended-early missing line.\n// Every field is optional so an older server (no `payment` block) degrades to the\n// neutral \"thanks, saved\" screen rather than throwing.\ninterface PaymentSummary {\n\tqualified: boolean\n\treward: string | null\n\tpayoutEmail: string | null\n\ttasksDone: number\n\ttasksTotal: number\n}\n\ninterface FinaliseResult {\n\tok: boolean\n\t// Only present on the first finalise call (the server computes it once).\n\tpayment: PaymentSummary | null\n}\n\nfunction parsePaymentSummary(raw: unknown): PaymentSummary | null {\n\tif (typeof raw !== 'object' || raw === null) return null\n\tconst p = raw as {\n\t\tqualified?: unknown\n\t\treward?: unknown\n\t\tpayoutEmail?: unknown\n\t\ttasksDone?: unknown\n\t\ttasksTotal?: unknown\n\t}\n\tif (typeof p.qualified !== 'boolean') return null\n\treturn {\n\t\tqualified: p.qualified,\n\t\treward: typeof p.reward === 'string' ? p.reward : null,\n\t\tpayoutEmail: typeof p.payoutEmail === 'string' ? p.payoutEmail : null,\n\t\ttasksDone: typeof p.tasksDone === 'number' ? p.tasksDone : 0,\n\t\ttasksTotal: typeof p.tasksTotal === 'number' ? p.tasksTotal : 0,\n\t}\n}\n\nasync function finaliseSession(\n\tapiUrl: string,\n\tsessionId: string,\n\tdurationSeconds: number,\n\textras: {\n\t\tmutedSegments?: MutedSegment[]\n\t\tendNote?: string | null\n\t\tnotes?: FinaliseNote[]\n\t\t// Replay linkage. sdkSessionId is the primary, always-available key:\n\t\t// the server resolves the SessionReplay by (clientId + sdkSessionId)\n\t\t// and sets UserTestSession.sessionReplayId. replayOffsetMs is the\n\t\t// offset captured at session start, only present when replay was\n\t\t// active. Both optional so older servers tolerate their absence and a\n\t\t// test with no replay still finalises cleanly.\n\t\tsdkSessionId?: string\n\t\treplayOffsetMs?: number\n\t} = {},\n): Promise<FinaliseResult> {\n\ttry {\n\t\tconst body: Record<string, unknown> = {\n\t\t\tdurationSeconds: Math.max(0, Math.round(durationSeconds)),\n\t\t}\n\t\tif (extras.mutedSegments && extras.mutedSegments.length > 0) {\n\t\t\tbody.mutedSegments = extras.mutedSegments\n\t\t}\n\t\tconst trimmedEndNote = extras.endNote?.trim()\n\t\tif (trimmedEndNote) body.endNote = trimmedEndNote\n\t\tif (extras.notes && extras.notes.length > 0) {\n\t\t\t// Server caps at 200; trim defensively here too.\n\t\t\tbody.notes = extras.notes.slice(0, 200).map(n => ({\n\t\t\t\tatMs: Math.max(0, Math.round(n.atMs)),\n\t\t\t\ttext: n.text,\n\t\t\t}))\n\t\t}\n\t\tif (extras.sdkSessionId) body.sdkSessionId = extras.sdkSessionId\n\t\tif (typeof extras.replayOffsetMs === 'number') {\n\t\t\tbody.replayOffsetMs = Math.max(0, Math.round(extras.replayOffsetMs))\n\t\t}\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/finalise`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify(body),\n\t\t\tkeepalive: true,\n\t\t})\n\t\tif (!res.ok) return { ok: false, payment: null }\n\t\tlet payment: PaymentSummary | null = null\n\t\ttry {\n\t\t\tconst json = (await res.json()) as { payment?: unknown }\n\t\t\tpayment = parsePaymentSummary(json.payment)\n\t\t} catch {\n\t\t\t// Older server or non-JSON body: degrade to neutral thanks screen.\n\t\t}\n\t\treturn { ok: true, payment }\n\t} catch {\n\t\treturn { ok: false, payment: null }\n\t}\n}\n\n// POST the participant's payout destination to the SaaS side. Best-effort with a\n// single retry; the destination defaults server-side to the testerEmail when we\n// send only `method`, so a dropped call still leaves a payable session. Returns\n// ok so the UI can confirm or surface a soft error.\nasync function postPayout(\n\tapiUrl: string,\n\tsessionId: string,\n\tdestination: string | null,\n\tlogger: PluginContext['logger'],\n): Promise<boolean> {\n\tconst url = `${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/payout`\n\tconst body: Record<string, unknown> = { method: 'email' }\n\tif (destination) body.destination = destination\n\tfor (let attempt = 0; attempt < 2; attempt += 1) {\n\t\ttry {\n\t\t\tconst res = await fetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tkeepalive: true,\n\t\t\t})\n\t\t\tif (res.ok) return true\n\t\t\t// 4xx won't improve on retry (bad email, etc.).\n\t\t\tif (res.status >= 400 && res.status < 500) {\n\t\t\t\tlogger.warn(`payout rejected with ${res.status}`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger.warn(`payout attempt ${attempt + 1} failed`, err)\n\t\t}\n\t\tawait new Promise(resolve => setTimeout(resolve, 400 + Math.floor(Math.random() * 200)))\n\t}\n\treturn false\n}\n\ninterface PostNoteResult {\n\tok: boolean\n\tid?: string\n\ttransient: boolean // true on network error / 5xx — eligible for retry\n}\n\nasync function postNoteOnce(\n\tapiUrl: string,\n\tsessionId: string,\n\tatMs: number,\n\ttext: string,\n\tlogger: PluginContext['logger'],\n): Promise<PostNoteResult> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/notes`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ atMs: Math.max(0, Math.round(atMs)), text }),\n\t\t\tkeepalive: true,\n\t\t})\n\t\tif (!res.ok) {\n\t\t\tlogger.warn(`note POST rejected with ${res.status}`)\n\t\t\treturn { ok: false, transient: res.status >= 500 || res.status === 408 || res.status === 429 }\n\t\t}\n\t\t// Best-effort id extraction; failures here don't matter for ack.\n\t\tlet id: string | undefined\n\t\ttry {\n\t\t\tconst json = (await res.json()) as { id?: unknown }\n\t\t\tif (typeof json.id === 'string') id = json.id\n\t\t} catch { /* ignore */ }\n\t\treturn { ok: true, id, transient: false }\n\t} catch (err) {\n\t\tlogger.warn('note POST failed', err)\n\t\treturn { ok: false, transient: true }\n\t}\n}\n\n// One immediate retry on transient errors. If still failing, defer to\n// finalise batching via the un-acked notes channel.\nasync function postNoteWithRetry(\n\tapiUrl: string,\n\tsessionId: string,\n\tatMs: number,\n\ttext: string,\n\tlogger: PluginContext['logger'],\n): Promise<PostNoteResult> {\n\tconst first = await postNoteOnce(apiUrl, sessionId, atMs, text, logger)\n\tif (first.ok || !first.transient) return first\n\tawait new Promise(resolve => setTimeout(resolve, 400 + Math.floor(Math.random() * 200)))\n\treturn postNoteOnce(apiUrl, sessionId, atMs, text, logger)\n}\n\n\nasync function flushPendingFromIdb(store: RecorderStore, ctx: PluginContext): Promise<void> {\n\tif (!store.sessionId) return\n\tconst pending = await idbListChunks(store.sessionId)\n\tfor (const chunk of pending) {\n\t\tconst ok = await uploadChunkWithRetry(chunk.apiUrl, chunk.sessionId, chunk.chunkIndex, chunk.blob, ctx.logger, 3)\n\t\tif (ok) await idbDeleteChunk(chunk.id)\n\t}\n}\n\nfunction enqueueChunk(store: RecorderStore, ctx: PluginContext, blob: Blob): void {\n\tif (store.cancelled || !store.sessionId || blob.size === 0) return\n\tconst index = store.chunkIndex\n\tstore.chunkIndex += 1\n\tstore.pendingUploads += 1\n\tconst sessionId = store.sessionId\n\tconst apiUrl = store.options.apiUrl\n\n\tstore.uploadQueue = store.uploadQueue.then(async () => {\n\t\tconst ok = await uploadChunkWithRetry(apiUrl, sessionId, index, blob, ctx.logger)\n\t\tif (!ok) {\n\t\t\tctx.logger.warn(`chunk ${index} stashed for offline retry`)\n\t\t\tawait idbStashChunk({\n\t\t\t\tid: `${sessionId}:${index}:${Date.now()}`,\n\t\t\t\tsessionId,\n\t\t\t\tapiUrl,\n\t\t\t\tchunkIndex: index,\n\t\t\t\tblob,\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t})\n\t\t}\n\t\tstore.pendingUploads -= 1\n\t})\n}\n\nasync function startRecording(store: RecorderStore, ctx: PluginContext): Promise<void> {\n\t// Re-entrant: the failed chip re-invokes this to retry. Reset to the\n\t// pending state so the chip shows \"connecting\" again during the attempt.\n\tstore.micAcquiring = true\n\tstore.micFailReason = null\n\trenderIndicatorState(store)\n\tif (!isMediaRecorderSupported()) {\n\t\tctx.logger.warn('MediaRecorder not supported, continuing without audio')\n\t\tstore.micAcquiring = false\n\t\tstore.micFailReason = 'unsupported'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tlet stream: MediaStream\n\ttry {\n\t\tstream = await navigator.mediaDevices.getUserMedia({ audio: true })\n\t} catch (err) {\n\t\tctx.logger.warn('mic permission denied or unavailable', err)\n\t\tstore.micAcquiring = false\n\t\t// Distinguish denied (blocked) from no-device (not-found) for copy.\n\t\tconst name = err instanceof Error ? err.name : ''\n\t\tstore.micFailReason = name === 'NotFoundError' || name === 'DevicesNotFoundError' ? 'not-found' : 'blocked'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tstore.stream = stream\n\tstore.hasMicPermission = true\n\tstore.micAcquiring = false\n\tstore.micFailReason = null\n\tconst mimeType = pickMimeType()\n\tlet recorder: MediaRecorder\n\ttry {\n\t\trecorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream)\n\t} catch (err) {\n\t\tctx.logger.error('MediaRecorder construction failed', err)\n\t\tstream.getTracks().forEach(t => t.stop())\n\t\tstore.stream = null\n\t\tstore.hasMicPermission = false\n\t\tstore.micAcquiring = false\n\t\tstore.micFailReason = 'unsupported'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tstore.recorder = recorder\n\trecorder.addEventListener('dataavailable', event => {\n\t\tif (event.data && event.data.size > 0) {\n\t\t\tenqueueChunk(store, ctx, event.data)\n\t\t}\n\t})\n\trecorder.addEventListener('error', event => {\n\t\tctx.logger.error('MediaRecorder error', event)\n\t})\n\t// `timeslice` makes the recorder emit a self-contained chunk every N ms.\n\trecorder.start(store.options.chunkSeconds * 1000)\n\t// On a successful (re)acquire, restore the live recording indicator. A\n\t// prior failed attempt left indicatorState at 'no-audio' (steady amber\n\t// dot); now that audio is live the dot should pulse red again.\n\tif (store.indicatorState === 'no-audio') {\n\t\tstore.indicatorState = 'recording'\n\t}\n\trenderIndicatorState(store)\n}\n\nfunction toggleMute(store: RecorderStore): boolean {\n\tif (!store.stream || !store.hasMicPermission) return false\n\tconst tracks = store.stream.getAudioTracks()\n\tif (tracks.length === 0) return false\n\tconst nowMs = Date.now() - store.startedAt\n\tif (!store.muted) {\n\t\t// Going muted: disable each audio track. MediaRecorder keeps running;\n\t\t// the disabled track produces silence in the resulting WebM. We do NOT\n\t\t// pause the recorder so the single-stream lifecycle stays simple.\n\t\tfor (const t of tracks) t.enabled = false\n\t\tstore.muted = true\n\t\tstore.mutedSinceMs = nowMs\n\t} else {\n\t\t// Coming back: close the muted segment, re-enable.\n\t\tconst startMs = store.mutedSinceMs ?? nowMs\n\t\tif (nowMs > startMs) {\n\t\t\tstore.mutedSegments.push({ startMs, endMs: nowMs })\n\t\t}\n\t\tstore.mutedSinceMs = null\n\t\tstore.muted = false\n\t\tfor (const t of tracks) t.enabled = true\n\t}\n\treturn true\n}\n\nfunction flushMuteIfActive(store: RecorderStore): void {\n\tif (!store.muted || store.mutedSinceMs === null) return\n\tconst nowMs = Date.now() - store.startedAt\n\tif (nowMs > store.mutedSinceMs) {\n\t\tstore.mutedSegments.push({ startMs: store.mutedSinceMs, endMs: nowMs })\n\t}\n\tstore.mutedSinceMs = null\n}\n\nfunction stopRecording(store: RecorderStore): void {\n\tconst recorder = store.recorder\n\tif (recorder && recorder.state !== 'inactive') {\n\t\ttry {\n\t\t\trecorder.requestData()\n\t\t} catch {\n\t\t\t// requestData throws if state is invalid; ignore.\n\t\t}\n\t\ttry {\n\t\t\trecorder.stop()\n\t\t} catch {\n\t\t\t// already stopped\n\t\t}\n\t}\n\tstore.recorder = null\n\tif (store.stream) {\n\t\tstore.stream.getTracks().forEach(t => t.stop())\n\t\tstore.stream = null\n\t}\n}\n\nasync function finishFlow(store: RecorderStore, ctx: PluginContext, opts: { showThanks: boolean }): Promise<void> {\n\tif (store.cancelled) return\n\t// Short-circuit re-entry. The pagehide handler and the manual Finish click\n\t// can race; server is also idempotent on a second finalise call, but doing\n\t// the local work twice (flushing mute, draining queues, etc.) is wasted.\n\tif (store.finishFlowRan) return\n\tif (store.indicatorState === 'finishing' || store.indicatorState === 'done') return\n\tstore.finishFlowRan = true\n\tstore.indicatorState = 'finishing'\n\tflushMuteIfActive(store)\n\trenderIndicatorState(store)\n\n\tstopRecording(store)\n\t// Wait for the queued uploads to drain. Each upload already has its own\n\t// retry/backoff; this just lets them finish before finalise fires.\n\tawait store.uploadQueue\n\tawait flushPendingFromIdb(store, ctx)\n\n\tconst durationSeconds = (Date.now() - store.startedAt) / 1000\n\t// Replay linkage, computed once and sent on every finalise call for this\n\t// session. sdkSessionId is the core-owned per-tab id (the primary key the\n\t// server uses to resolve the SessionReplay); replayOffsetMs is the offset\n\t// captured at session start, only set when replay was active. Both degrade\n\t// gracefully to absent. Sending it on the second (end-note) finalise too\n\t// is harmless: the server stores idempotently.\n\tconst replayLinkage: { sdkSessionId?: string; replayOffsetMs?: number } = {}\n\tconst linkageSdkSessionId = ctx.getSdkSessionId ? ctx.getSdkSessionId() : undefined\n\tif (linkageSdkSessionId) replayLinkage.sdkSessionId = linkageSdkSessionId\n\tif (store.replayOffsetAtStartMs !== null) {\n\t\treplayLinkage.replayOffsetMs = store.replayOffsetAtStartMs\n\t}\n\t// Payment summary from the first finalise response drives the finished screen\n\t// (complete vs ended-early, reward headline, one-tap payout default).\n\tlet payment: PaymentSummary | null = null\n\tif (store.sessionId) {\n\t\t// First finalise carries durationSeconds + mutedSegments + any un-acked\n\t\t// notes (recovery channel). End-of-test note is sent via a second\n\t\t// finalise call from the thanks screen.\n\t\tconst unackedNotes = store.notes.filter(n => !n.acked).map(n => ({ atMs: n.atMs, text: n.text }))\n\t\tconst result = await finaliseSession(store.options.apiUrl, store.sessionId, durationSeconds, {\n\t\t\tmutedSegments: store.mutedSegments,\n\t\t\tnotes: unackedNotes,\n\t\t\t...replayLinkage,\n\t\t})\n\t\tif (result.ok) {\n\t\t\tpayment = result.payment\n\t\t\t// Mark the un-acked notes we just shipped as acked so the second\n\t\t\t// finalise call doesn't resend them.\n\t\t\tfor (const n of store.notes) {\n\t\t\t\tif (!n.acked) n.acked = true\n\t\t\t}\n\t\t}\n\t\tstore.indicatorState = result.ok ? 'done' : 'error'\n\t} else {\n\t\tstore.indicatorState = 'error'\n\t}\n\trenderIndicatorState(store)\n\n\tif (opts.showThanks && store.indicatorRoot && store.indicatorState === 'done') {\n\t\tshowThanksScreen(store.indicatorRoot, {\n\t\t\tpayment,\n\t\t\tonPayout: async destination => {\n\t\t\t\tif (!store.sessionId) return false\n\t\t\t\treturn postPayout(store.options.apiUrl, store.sessionId, destination, ctx.logger)\n\t\t\t},\n\t\t\tonResume: () => {\n\t\t\t\t// Re-arm an ended-early session: the recording was already stopped +\n\t\t\t\t// finalised, so resuming starts a fresh recording leg under the same\n\t\t\t\t// sessionId. The server is idempotent on a later finalise; the new\n\t\t\t\t// audio chunks continue the same R2 prefix. Reset the finish guard\n\t\t\t\t// and timeline anchor so the next Finish re-evaluates completion.\n\t\t\t\tstore.finishFlowRan = false\n\t\t\t\tstore.indicatorState = 'recording'\n\t\t\t\tstore.startedAt = Date.now()\n\t\t\t\tstore.muted = false\n\t\t\t\tstore.mutedSinceMs = null\n\t\t\t\trenderIndicatorState(store)\n\t\t\t\tvoid startRecording(store, ctx)\n\t\t\t},\n\t\t\tonSubmitNote: async text => {\n\t\t\t\tif (!store.sessionId) return\n\t\t\t\tstore.endNote = text\n\t\t\t\t// Second finalise only carries the late-binding fields. mutedSegments\n\t\t\t\t// already landed on call 1, server stores idempotently, no need to\n\t\t\t\t// resend. Include any notes that arrived (or failed to ack) between\n\t\t\t\t// the two calls.\n\t\t\t\tconst stillUnacked = store.notes.filter(n => !n.acked).map(n => ({ atMs: n.atMs, text: n.text }))\n\t\t\t\tconst result = await finaliseSession(store.options.apiUrl, store.sessionId, durationSeconds, {\n\t\t\t\t\tendNote: text,\n\t\t\t\t\tnotes: stillUnacked,\n\t\t\t\t\t...replayLinkage,\n\t\t\t\t})\n\t\t\t\tif (!result.ok) throw new Error('finalise failed')\n\t\t\t\tfor (const n of store.notes) {\n\t\t\t\t\tif (!n.acked) n.acked = true\n\t\t\t\t}\n\t\t\t},\n\t\t\tonSkip: () => { /* nothing to send */ },\n\t\t})\n\t}\n}\n\nexport function userTest(options: UserTestOptions = {}): UseroPlugin {\n\tconst merged: Required<UserTestOptions> = {\n\t\tqueryParam: options.queryParam ?? DEFAULT_OPTIONS.queryParam,\n\t\tchunkSeconds: options.chunkSeconds ?? DEFAULT_OPTIONS.chunkSeconds,\n\t\tapiUrl: options.apiUrl ?? DEFAULT_OPTIONS.apiUrl,\n\t\ttesterName: options.testerName ?? DEFAULT_OPTIONS.testerName,\n\t\thideIndicator: options.hideIndicator ?? DEFAULT_OPTIONS.hideIndicator,\n\t}\n\n\treturn {\n\t\tname: 'user-test',\n\t\tonInit(ctx) {\n\t\t\tif (typeof window === 'undefined' || typeof document === 'undefined') return\n\t\t\tconst slug = getTestSlug(merged.queryParam)\n\t\t\tif (!slug) return\n\n\t\t\tconst apiUrl = merged.apiUrl || ctx.baseUrl || DEFAULT_API_URL\n\t\t\tconst store: RecorderStore = {\n\t\t\t\tcancelled: false,\n\t\t\t\tslug,\n\t\t\t\tsessionId: null,\n\t\t\t\tclientId: null,\n\t\t\t\trecorder: null,\n\t\t\t\tstream: null,\n\t\t\t\tchunkIndex: 0,\n\t\t\t\tuploadQueue: Promise.resolve(),\n\t\t\t\tpendingUploads: 0,\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tindicator: null,\n\t\t\t\tindicatorRoot: null,\n\t\t\t\tindicatorState: 'recording',\n\t\t\t\tpageHideHandler: null,\n\t\t\t\tvisibilityHandler: null,\n\t\t\t\toptions: { ...merged, apiUrl },\n\t\t\t\ttasks: [],\n\t\t\t\ttasksPanelOpen: readTasksPanelOpen(),\n\t\t\t\toutsidePointerHandler: null,\n\t\t\t\tkeydownHandler: null,\n\t\t\t\thasMicPermission: false,\n\t\t\t\tmicAcquiring: true,\n\t\t\t\tmicFailReason: null,\n\t\t\t\tmuted: false,\n\t\t\t\tmutedSinceMs: null,\n\t\t\t\tmutedSegments: [],\n\t\t\t\tmuteToastShown: false,\n\t\t\t\tmuteToastTimers: [],\n\t\t\t\tnotes: [],\n\t\t\t\tnotesPopoverOpen: false,\n\t\t\t\tnotePopoverAtMs: null,\n\t\t\t\tendNote: '',\n\t\t\t\tfinishFlowRan: false,\n\t\t\t\treplayOffsetAtStartMs: null,\n\t\t\t}\n\t\t\tctx.setStore(store)\n\n\t\t\tconst onFinish = (): void => {\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: true })\n\t\t\t}\n\n\t\t\tconst setPanelOpen = (open: boolean): void => {\n\t\t\t\tif (store.tasksPanelOpen === open) return\n\t\t\t\tstore.tasksPanelOpen = open\n\t\t\t\twriteTasksPanelOpen(open)\n\t\t\t\trenderTasksPanel(store)\n\t\t\t}\n\n\t\t\tconst onToggleTasks = (): void => setPanelOpen(!store.tasksPanelOpen)\n\n\t\t\tconst onToggleMute = (): void => {\n\t\t\t\tif (!store.hasMicPermission) {\n\t\t\t\t\t// In the failed terminal state the chip is a retry button:\n\t\t\t\t\t// re-attempt mic acquisition. Ignore taps while still\n\t\t\t\t\t// acquiring (connecting state is unfocusable anyway).\n\t\t\t\t\tif (!store.micAcquiring && store.indicatorState !== 'finishing' && store.indicatorState !== 'done' && store.indicatorState !== 'error') {\n\t\t\t\t\t\tvoid startRecording(store, ctx)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst ok = toggleMute(store)\n\t\t\t\tif (!ok) return\n\t\t\t\tif (store.muted) showMuteToast(store)\n\t\t\t\trenderIndicatorState(store)\n\t\t\t}\n\n\t\t\tconst closeNote = (): void => closeNotePopover(store)\n\t\t\tconst onOpenNote = (): void => {\n\t\t\t\tif (store.notesPopoverOpen) { closeNote(); return }\n\t\t\t\topenNotePopover(\n\t\t\t\t\tstore,\n\t\t\t\t\ttext => {\n\t\t\t\t\t\tconst atMs = store.notePopoverAtMs ?? Math.max(0, Date.now() - store.startedAt)\n\t\t\t\t\t\tconst note: InFlightNote = { atMs, text, acked: false }\n\t\t\t\t\t\tstore.notes.push(note)\n\t\t\t\t\t\tcloseNote()\n\t\t\t\t\t\trenderNotesCount(store)\n\t\t\t\t\t\t// UI never blocks on the POST. On success we mark the note\n\t\t\t\t\t\t// acked; on failure (after one retry) it stays unacked and\n\t\t\t\t\t\t// gets included in the finalise notes batch as a recovery\n\t\t\t\t\t\t// channel. Server dedupes by (sessionId, atMs, text).\n\t\t\t\t\t\tif (store.sessionId) {\n\t\t\t\t\t\t\tconst sessionId = store.sessionId\n\t\t\t\t\t\t\tvoid (async (): Promise<void> => {\n\t\t\t\t\t\t\t\tconst result = await postNoteWithRetry(store.options.apiUrl, sessionId, atMs, text, ctx.logger)\n\t\t\t\t\t\t\t\tif (result.ok) {\n\t\t\t\t\t\t\t\t\tnote.acked = true\n\t\t\t\t\t\t\t\t\tif (result.id) note.serverId = result.id\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t() => closeNote(),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (!merged.hideIndicator) {\n\t\t\t\tconst host = document.createElement('div')\n\t\t\t\thost.setAttribute('data-usero-user-test', 'true')\n\t\t\t\tdocument.body.appendChild(host)\n\t\t\t\tstore.indicator = host\n\t\t\t\tstore.indicatorRoot = buildIndicator(host, store, {\n\t\t\t\t\tonFinish,\n\t\t\t\t\tonToggleTasks,\n\t\t\t\t\tonToggleMute,\n\t\t\t\t\tonOpenNote,\n\t\t\t\t})\n\t\t\t\trenderIndicatorState(store)\n\t\t\t\trenderNotesCount(store)\n\t\t\t}\n\n\t\t\t// Outside-click + Escape close the tasks panel. Listen on document\n\t\t\t// (composedPath checks shadow ancestry so taps on the panel/pill\n\t\t\t// itself don't dismiss).\n\t\t\tconst outsidePointer = (event: PointerEvent): void => {\n\t\t\t\tconst host = store.indicator\n\t\t\t\tif (!host) return\n\t\t\t\tconst path = event.composedPath()\n\t\t\t\tif (path.includes(host)) return\n\t\t\t\tif (store.tasksPanelOpen) setPanelOpen(false)\n\t\t\t\tif (store.notesPopoverOpen) closeNote()\n\t\t\t}\n\t\t\tconst onKeydown = (event: KeyboardEvent): void => {\n\t\t\t\tif (event.key !== 'Escape') return\n\t\t\t\tif (store.tasksPanelOpen) setPanelOpen(false)\n\t\t\t\tif (store.notesPopoverOpen) closeNote()\n\t\t\t}\n\t\t\tstore.outsidePointerHandler = outsidePointer\n\t\t\tstore.keydownHandler = onKeydown\n\t\t\tdocument.addEventListener('pointerdown', outsidePointer, true)\n\t\t\tdocument.addEventListener('keydown', onKeydown)\n\n\t\t\tconst pageHide = (): void => {\n\t\t\t\t// Best-effort flush + finalise. We don't await here; the browser\n\t\t\t\t// is shutting the page down. `keepalive: true` on finalise lets\n\t\t\t\t// the request race the unload.\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: false })\n\t\t\t}\n\t\t\tstore.pageHideHandler = pageHide\n\t\t\twindow.addEventListener('pagehide', pageHide)\n\n\t\t\t// visibilitychange -> hidden is the reliable mobile unload backstop:\n\t\t\t// iOS frequently kills a backgrounded tab WITHOUT ever firing\n\t\t\t// pagehide, leaving the session stuck un-finalised. visibilitychange\n\t\t\t// fires far more consistently when the tab is backgrounded. It runs\n\t\t\t// the SAME finishFlow path as pagehide; finishFlow is idempotent (the\n\t\t\t// `finishFlowRan` + indicatorState short-circuit at its top), so the\n\t\t\t// manual Finish click, pagehide, and this handler can fire in any\n\t\t\t// order or concurrently and only the first does the work. Like\n\t\t\t// pagehide we don't await; finalise rides on `keepalive: true`.\n\t\t\tconst onVisibilityChange = (): void => {\n\t\t\t\tif (document.visibilityState !== 'hidden') return\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: false })\n\t\t\t}\n\t\t\tstore.visibilityHandler = onVisibilityChange\n\t\t\tdocument.addEventListener('visibilitychange', onVisibilityChange)\n\n\t\t\tvoid (async (): Promise<void> => {\n\t\t\t\t// If the entry screen created the session and passed `uts`, ADOPT\n\t\t\t\t// it (the participant's email is already attached server-side).\n\t\t\t\t// Otherwise fall back to creating one (open tests / old links).\n\t\t\t\tconst adoptId = getAdoptSessionId()\n\t\t\t\tconst created = adoptId\n\t\t\t\t\t? await adoptSession(apiUrl, adoptId)\n\t\t\t\t\t: await createSession(apiUrl, slug, readTesterName(merged.testerName))\n\t\t\t\tif (store.cancelled) return\n\t\t\t\tif (!created) {\n\t\t\t\t\tctx.logger.error(adoptId ? 'failed to adopt user-test session' : 'failed to create user-test session')\n\t\t\t\t\tstore.indicatorState = 'error'\n\t\t\t\t\trenderIndicatorState(store)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tstore.sessionId = created.sessionId\n\t\t\t\tstore.clientId = created.clientId\n\t\t\t\t// Capture the replay offset HERE at session start (not at\n\t\t\t\t// finalise) so it reflects when the test began relative to the\n\t\t\t\t// recording. The replay plugin publishes its start epoch into\n\t\t\t\t// the core; we read it via the context. If replay is not active\n\t\t\t\t// (plugin not loaded, sampled out, or an older host without the\n\t\t\t\t// accessor) we leave it null and the finalise body omits\n\t\t\t\t// replayOffsetMs. Anchored to store.startedAt (test start),\n\t\t\t\t// clamped >= 0 in case the test starts a hair before the replay\n\t\t\t\t// epoch is published.\n\t\t\t\tconst replayStartMs = ctx.getReplayStartMs ? ctx.getReplayStartMs() : null\n\t\t\t\tstore.replayOffsetAtStartMs =\n\t\t\t\t\treplayStartMs === null ? null : Math.max(0, store.startedAt - replayStartMs)\n\t\t\t\tstore.tasks = created.tasks\n\t\t\t\tif (store.tasks.length > 0 && store.indicatorRoot && !merged.hideIndicator) {\n\t\t\t\t\tconst bar = store.indicatorRoot.querySelector('.bar')\n\t\t\t\t\tconst finishBtn = bar?.querySelector('.finish-btn')\n\t\t\t\t\tif (bar instanceof HTMLElement && finishBtn instanceof HTMLElement && !bar.querySelector('.tasks-btn')) {\n\t\t\t\t\t\tinstallTasksToggle(bar, finishBtn, store, onToggleTasks)\n\t\t\t\t\t}\n\t\t\t\t\trenderTasksPanel(store)\n\t\t\t\t}\n\t\t\t\tawait startRecording(store, ctx)\n\t\t\t\trenderIndicatorState(store)\n\t\t\t})()\n\t\t},\n\t\tonDestroy(ctx) {\n\t\t\tconst store = ctx.getStore<RecorderStore>()\n\t\t\tif (!store) return\n\t\t\tstore.cancelled = true\n\t\t\tif (store.pageHideHandler) {\n\t\t\t\twindow.removeEventListener('pagehide', store.pageHideHandler)\n\t\t\t\tstore.pageHideHandler = null\n\t\t\t}\n\t\t\tif (store.visibilityHandler) {\n\t\t\t\tdocument.removeEventListener('visibilitychange', store.visibilityHandler)\n\t\t\t\tstore.visibilityHandler = null\n\t\t\t}\n\t\t\tstopRecording(store)\n\t\t\tif (store.outsidePointerHandler) {\n\t\t\t\tdocument.removeEventListener('pointerdown', store.outsidePointerHandler, true)\n\t\t\t\tstore.outsidePointerHandler = null\n\t\t\t}\n\t\t\tif (store.keydownHandler) {\n\t\t\t\tdocument.removeEventListener('keydown', store.keydownHandler)\n\t\t\t\tstore.keydownHandler = null\n\t\t\t}\n\t\t\tfor (const id of store.muteToastTimers) {\n\t\t\t\ttry { window.clearTimeout(id) } catch { /* ignore */ }\n\t\t\t}\n\t\t\tstore.muteToastTimers = []\n\t\t\tif (store.indicator && store.indicator.parentNode) {\n\t\t\t\tstore.indicator.parentNode.removeChild(store.indicator)\n\t\t\t}\n\t\t\tstore.indicator = null\n\t\t\tstore.indicatorRoot = null\n\t\t},\n\t}\n}\n\n// Internal helpers exposed for tests only. Not part of the public API.\nexport const __test__ = { getTestSlug, pickMimeType, isMediaRecorderSupported, micChipState }\n"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/plugins/user-test.ts"],"names":[],"mappings":"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AA;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;AAAA;AAAA;AAAA;AAAA;AA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","file":"user-test.js","sourcesContent":["// Shared types used by both the vanilla and React entry points.\n// Keep this file framework-free so the vanilla bundle never pulls react.\n\nexport type FeedbackRating = 1 | 2 | 3 | 4\n\nexport interface FeedbackMetadata {\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\ttimestamp: number\n}\n\nexport interface ScreenshotData {\n\tfileName: string\n\turl: string\n\tfileSize: number\n\twidth?: number\n\theight?: number\n\tmimeType: string\n}\n\nexport interface FeedbackSubmission {\n\tclientId: string\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tpageUrl: string\n\tpageTitle: string\n\treferrer?: string\n\tenvironment?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata?: Record<string, unknown>\n\t// Legacy gzipped + base64-encoded rrweb event stream. The pre-chunked\n\t// session-replay plugin attached this on submit. The chunked-upload\n\t// plugin (>= 0.4.0) does NOT set this — it ships events out-of-band\n\t// via the chunk endpoints and points at the resulting session replay\n\t// via `sessionReplayId` + `replayOffsetMs`. Kept on the wire one\n\t// release for backward compat with old SaaS deployments that only\n\t// know how to ingest the legacy field.\n\treplayEvents?: string\n\t// Pointer to a SessionReplay row created by the session-replay\n\t// plugin's chunked-upload pipeline, plus the offset within that\n\t// recording at submit time so the dashboard can deep-link.\n\tsessionReplayId?: string\n\treplayOffsetMs?: number\n}\n\nexport interface FeedbackData {\n\trating?: FeedbackRating\n\tcomment?: string\n\tuserEmail?: string\n\tscreenshots?: ScreenshotData[]\n\tmetadata: FeedbackMetadata\n}\n\n// Customer-supplied identity for the session-replay / identify pipeline.\n// Use the declarative form: pass `user` on the React widget (the SDK\n// diffs and auto-fires identify), or supply `getUser` on the vanilla\n// init (the SDK polls it at session start). An imperative `identify()`\n// call exists as an escape hatch only and is intentionally not\n// documented as the headline API.\nexport type UseroUserTraitValue = string | number | boolean | null\nexport type UseroUserTraits = Record<string, UseroUserTraitValue>\nexport interface UseroUser {\n\tid: string\n\temail?: string\n\tdisplayName?: string\n\ttraits?: UseroUserTraits\n}\n\nexport type WidgetPosition = 'right' | 'left'\n\nexport interface WidgetTheme {\n\tprimary: string\n\tbackground: string\n\ttext: string\n\tborder: string\n\tshadow: string\n}\n\n// Forward-declared to avoid a circular import. The plugin module imports\n// FeedbackSubmission from this file, so we can't import UseroPlugin back\n// up here without a cycle. Keeping the prop typed as an opaque object with\n// the minimal shape the widget actually inspects works fine for consumers.\nexport interface FeedbackWidgetProps {\n\tclientId: string\n\tposition?: WidgetPosition\n\ttheme?: Partial<WidgetTheme>\n\ttitle?: string\n\tplaceholder?: string\n\tshowEmailOption?: boolean\n\tshowScreenshotOption?: boolean\n\tenvironment?: string\n\tbaseUrl?: string\n\tmetadata?: Record<string, unknown>\n\tplugins?: ReadonlyArray<import('./plugin').UseroPlugin>\n\t// Declarative identity. React: pass the current user (or null on\n\t// logout) and the SDK auto-fires identify when the resolved id\n\t// transitions. Vanilla: pass a getter so the SDK can resolve user at\n\t// session start / chunk boundaries. Pass at most one. The SDK never\n\t// invokes both.\n\tuser?: UseroUser | null\n\tgetUser?: () => UseroUser | null | undefined\n\tonSubmit?: (feedback: FeedbackData) => void\n\tonError?: (error: Error) => void\n\tonOpen?: () => void\n\tonClose?: () => void\n}\n\nexport interface SubmissionResponse {\n\tsuccess: boolean\n\terror?: string\n\tid?: string\n\tmessage?: string\n\tdata?: unknown\n}\n\nexport const EMOJI_MAP: Record<FeedbackRating, string> = {\n\t1: '😞',\n\t2: '😐',\n\t3: '😊',\n\t4: '🤩',\n}\n\nexport const RATING_LABELS: Record<FeedbackRating, string> = {\n\t1: 'Needs work',\n\t2: \"It's okay\",\n\t3: 'Pretty good',\n\t4: 'Amazing!',\n}\n\nexport const EMOJI_BACKGROUNDS: Record<FeedbackRating, string> = {\n\t1: 'linear-gradient(135deg,#ff6b6b14,#ff6b6b1f)',\n\t2: 'linear-gradient(135deg,#9ca3af0f,#9ca3af1a)',\n\t3: 'linear-gradient(135deg,#3b82f614,#3b82f61f)',\n\t4: 'linear-gradient(135deg,#f59e0b14,#f59e0b1f)',\n}\n\nexport const DEFAULT_API_URL = 'https://usero.io'\n\nexport const DEFAULT_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#ffffff',\n\ttext: '#374151',\n\tborder: '#e5e7eb',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',\n}\n\nexport const DARK_THEME: WidgetTheme = {\n\tprimary: '#2563eb',\n\tbackground: '#1f2937',\n\ttext: '#f9fafb',\n\tborder: '#374151',\n\tshadow:\n\t\t'0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2)',\n}\n\nexport function mergeTheme(customTheme: Partial<WidgetTheme> = {}): WidgetTheme {\n\treturn { ...DEFAULT_THEME, ...customTheme }\n}\n","// User-testing-mode plugin for the Usero widget.\n//\n// Activates ONLY when the host page URL carries `?usero_test=<slug>`. When\n// active, it:\n// 1. Creates a UserTestSession on the SaaS side via\n// POST /api/user-test-sessions\n// 2. Starts a MediaRecorder on the user's microphone (Opus in WebM) and\n// ships chunks every `chunkSeconds` to\n// PUT /api/user-test-sessions/:id/chunk?index=N\n// 3. Renders a small floating \"recording\" indicator with a Finish button\n// bottom-center so the tester can stop on their own.\n// 4. On Finish (or `pagehide` / `visibilitychange` -> hidden), flushes any\n// buffered chunks and calls POST /api/user-test-sessions/:id/finalise.\n//\n// Mic-permission denied is non-fatal: the session is still created (the\n// session-replay plugin keeps recording in parallel) and the indicator\n// shows a \"no audio\" hint. The SaaS side detects audio presence from the\n// first chunk; if no chunks land, hasAudio stays false there too.\n//\n// Bundle hygiene: this module is a subpath export and does NOT depend on\n// rrweb or any other heavy dep — just the native MediaRecorder API. The\n// floating UI is shadow-DOM scoped so host page CSS can't leak in.\n//\n// Privacy: only the microphone is recorded. We never read DOM text, never\n// touch the camera, and never persist audio in the browser past the\n// IndexedDB fallback (cleared on successful upload).\n\nimport type { UseroPlugin, PluginContext } from '../plugin'\nimport { DEFAULT_API_URL } from '../types'\n\nexport interface UserTestOptions {\n\t// URL query param the welcome page appends to redirect testers back.\n\t// Default `usero_test`. Match SaaS side if you ever change it.\n\tqueryParam?: string\n\t// Audio chunk length in seconds. Smaller = more partial-data resilience\n\t// but more requests. Default 10.\n\tchunkSeconds?: number\n\t// API origin. Override for self-hosted or local dev. Defaults to the\n\t// shared SDK constant (https://usero.io).\n\tapiUrl?: string\n\t// Override the tester-name shown on the SaaS side. Normally the welcome\n\t// page collects this and stores it in localStorage; the plugin reads it\n\t// from there. This option lets a host site bypass that.\n\ttesterName?: string\n\t// Hide the floating indicator. The plugin still records and finalises\n\t// on `pagehide`, but the tester gets no on-page UI. Useful if the host\n\t// page wants to render its own.\n\thideIndicator?: boolean\n}\n\ninterface UserTestTask {\n\tid: string\n\tprompt: string\n\tsortOrder: number\n}\n\ninterface MutedSegment {\n\tstartMs: number\n\tendMs: number\n}\n\ninterface InFlightNote {\n\tatMs: number\n\ttext: string\n\tacked: boolean\n\tserverId?: string\n}\n\ninterface RecorderStore {\n\tcancelled: boolean\n\tslug: string\n\tsessionId: string | null\n\tclientId: string | null\n\trecorder: MediaRecorder | null\n\tstream: MediaStream | null\n\tchunkIndex: number\n\tuploadQueue: Promise<void>\n\tpendingUploads: number\n\tstartedAt: number\n\tindicator: HTMLElement | null\n\tindicatorRoot: ShadowRoot | null\n\tindicatorState: 'recording' | 'finishing' | 'done' | 'no-audio' | 'error'\n\tpageHideHandler: (() => void) | null\n\tvisibilityHandler: (() => void) | null\n\toptions: Required<UserTestOptions>\n\ttasks: UserTestTask[]\n\ttasksPanelOpen: boolean\n\toutsidePointerHandler: ((event: PointerEvent) => void) | null\n\tkeydownHandler: ((event: KeyboardEvent) => void) | null\n\t// Mic mute\n\thasMicPermission: boolean\n\t// True while getUserMedia is in flight (pending). Distinguishes the\n\t// \"connecting\" chip state (granted users, promise not yet resolved) from\n\t// the genuinely-failed terminal \"none\" state. Init true; cleared on every\n\t// success/failure exit of startRecording.\n\tmicAcquiring: boolean\n\t// Why mic acquisition failed, for actionable terminal copy. 'blocked' =\n\t// permission denied (NotAllowedError), 'not-found' = no device\n\t// (NotFoundError), 'unsupported' = MediaRecorder/getUserMedia missing or\n\t// constructor threw. Null while acquiring or once granted.\n\tmicFailReason: 'blocked' | 'not-found' | 'unsupported' | null\n\tmuted: boolean\n\tmutedSinceMs: number | null\n\tmutedSegments: MutedSegment[]\n\t// Silent-mic guard. micSilent is true while the live input is reading\n\t// digital silence (dead mic, or a virtual audio device delivering nothing).\n\t// Non-blocking: recording continues; the pill just warns. Auto-clears when\n\t// real audio returns. silenceMonitor holds the AnalyserNode teardown.\n\tmicSilent: boolean\n\tsilenceMonitor: { stop(): void } | null\n\tmuteToastShown: boolean\n\tmuteToastTimers: number[]\n\t// In-flight notes\n\tnotes: InFlightNote[]\n\tnotesPopoverOpen: boolean\n\tnotePopoverAtMs: number | null\n\t// End-of-test comment (collected on thanks screen)\n\tendNote: string\n\t// Re-entry guard for finishFlow.\n\tfinishFlowRan: boolean\n\t// Offset (ms) into the session-replay recording at the moment THIS\n\t// user-test session started. Captured once at start (not at finalise)\n\t// so it pins the test timeline to the recording timeline. Null when no\n\t// replay is active (plugin not loaded, sampled out, or host predates\n\t// the core accessor); finalise then omits replayOffsetMs.\n\treplayOffsetAtStartMs: number | null\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<UserTestOptions, 'testerName' | 'apiUrl'>> & {\n\ttesterName: string\n\tapiUrl: string\n} = {\n\tqueryParam: 'usero_test',\n\t// 10s (not 30) so at most ~10s of audio is at risk if the tab is torn\n\t// down before a flush, and so a session shorter than the old 30s window\n\t// still emits at least one chunk (previously its single buffered chunk was\n\t// never flushed and its audio was lost). Tradeoff: ~3x the R2 writes /\n\t// upload requests per session; 10s is an acceptable balance, don't go lower.\n\tchunkSeconds: 10,\n\tapiUrl: DEFAULT_API_URL,\n\ttesterName: '',\n\thideIndicator: false,\n}\n\nconst TESTER_NAME_STORAGE_KEY = 'usero:user-test:tester-name'\nconst TASKS_PANEL_OPEN_STORAGE_KEY = 'usero:user-test:tasks-panel-open'\nconst IDB_NAME = 'usero-user-test'\nconst IDB_STORE = 'pending-chunks'\n\ninterface PendingChunk {\n\tid: string\n\tsessionId: string\n\tapiUrl: string\n\tchunkIndex: number\n\tblob: Blob\n\tcreatedAt: number\n}\n\nfunction readTesterName(override: string): string | undefined {\n\tif (override) return override\n\ttry {\n\t\tconst stored = window.localStorage?.getItem(TESTER_NAME_STORAGE_KEY)\n\t\tif (stored && stored.trim()) return stored.trim().slice(0, 120)\n\t} catch {\n\t\t// Storage access can throw in some sandboxed iframes — ignore.\n\t}\n\treturn undefined\n}\n\n// Read the `uts` (user-test session) id the entry screen appends when it\n// creates the session server-side. When present, the SDK ADOPTS that session\n// instead of minting its own (so the session has the participant's email from\n// creation, no double-session). Absent for open tests using the old link\n// shape, where the SDK falls back to createSession.\nfunction getAdoptSessionId(): string | null {\n\tif (typeof window === 'undefined' || typeof window.location === 'undefined') return null\n\ttry {\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst raw = params.get('uts')\n\t\tif (!raw) return null\n\t\tconst cleaned = raw.trim().slice(0, 64)\n\t\t// Session ids are cuids: lowercase alphanumerics. Reject anything else.\n\t\tif (!/^[a-z0-9]+$/i.test(cleaned)) return null\n\t\treturn cleaned\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction getTestSlug(queryParam: string): string | null {\n\tif (typeof window === 'undefined' || typeof window.location === 'undefined') return null\n\ttry {\n\t\tconst params = new URLSearchParams(window.location.search)\n\t\tconst slug = params.get(queryParam)\n\t\tif (!slug) return null\n\t\tconst cleaned = slug.trim().slice(0, 64)\n\t\tif (!/^[a-z0-9-]+$/i.test(cleaned)) return null\n\t\treturn cleaned\n\t} catch {\n\t\treturn null\n\t}\n}\n\nfunction isMediaRecorderSupported(): boolean {\n\treturn typeof window !== 'undefined' && typeof window.MediaRecorder !== 'undefined' && typeof navigator !== 'undefined' && !!navigator.mediaDevices?.getUserMedia\n}\n\nfunction pickMimeType(): string | undefined {\n\tconst candidates = ['audio/webm;codecs=opus', 'audio/webm', 'audio/ogg;codecs=opus', 'audio/mp4']\n\tfor (const candidate of candidates) {\n\t\tif (typeof MediaRecorder !== 'undefined' && MediaRecorder.isTypeSupported?.(candidate)) {\n\t\t\treturn candidate\n\t\t}\n\t}\n\treturn undefined\n}\n\n// IndexedDB helpers. Best-effort, never throw upstream — if IDB is missing\n// or quota-blown we just lose offline resilience but the live upload path\n// still runs.\nfunction idbOpen(): Promise<IDBDatabase | null> {\n\treturn new Promise(resolve => {\n\t\tif (typeof indexedDB === 'undefined') {\n\t\t\tresolve(null)\n\t\t\treturn\n\t\t}\n\t\ttry {\n\t\t\tconst req = indexedDB.open(IDB_NAME, 1)\n\t\t\treq.onupgradeneeded = (): void => {\n\t\t\t\tconst db = req.result\n\t\t\t\tif (!db.objectStoreNames.contains(IDB_STORE)) {\n\t\t\t\t\tdb.createObjectStore(IDB_STORE, { keyPath: 'id' })\n\t\t\t\t}\n\t\t\t}\n\t\t\treq.onsuccess = (): void => resolve(req.result)\n\t\t\treq.onerror = (): void => resolve(null)\n\t\t} catch {\n\t\t\tresolve(null)\n\t\t}\n\t})\n}\n\nasync function idbStashChunk(chunk: PendingChunk): Promise<void> {\n\tconst db = await idbOpen()\n\tif (!db) return\n\tawait new Promise<void>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readwrite')\n\t\t\ttx.objectStore(IDB_STORE).put(chunk)\n\t\t\ttx.oncomplete = (): void => resolve()\n\t\t\ttx.onerror = (): void => resolve()\n\t\t\ttx.onabort = (): void => resolve()\n\t\t} catch {\n\t\t\tresolve()\n\t\t}\n\t})\n\tdb.close()\n}\n\nasync function idbDeleteChunk(id: string): Promise<void> {\n\tconst db = await idbOpen()\n\tif (!db) return\n\tawait new Promise<void>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readwrite')\n\t\t\ttx.objectStore(IDB_STORE).delete(id)\n\t\t\ttx.oncomplete = (): void => resolve()\n\t\t\ttx.onerror = (): void => resolve()\n\t\t\ttx.onabort = (): void => resolve()\n\t\t} catch {\n\t\t\tresolve()\n\t\t}\n\t})\n\tdb.close()\n}\n\nasync function idbListChunks(sessionId: string): Promise<PendingChunk[]> {\n\tconst db = await idbOpen()\n\tif (!db) return []\n\tconst items = await new Promise<PendingChunk[]>(resolve => {\n\t\ttry {\n\t\t\tconst tx = db.transaction(IDB_STORE, 'readonly')\n\t\t\tconst req = tx.objectStore(IDB_STORE).getAll()\n\t\t\treq.onsuccess = (): void => {\n\t\t\t\tconst all = (req.result as PendingChunk[]) ?? []\n\t\t\t\tresolve(all.filter(c => c.sessionId === sessionId))\n\t\t\t}\n\t\t\treq.onerror = (): void => resolve([])\n\t\t} catch {\n\t\t\tresolve([])\n\t\t}\n\t})\n\tdb.close()\n\treturn items\n}\n\nasync function uploadChunkWithRetry(\n\tapiUrl: string,\n\tsessionId: string,\n\tindex: number,\n\tblob: Blob,\n\tlogger: PluginContext['logger'],\n\tmaxAttempts = 5,\n): Promise<boolean> {\n\tconst url = `${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/chunk?index=${index}`\n\tlet attempt = 0\n\twhile (attempt < maxAttempts) {\n\t\ttry {\n\t\t\tconst res = await fetch(url, {\n\t\t\t\tmethod: 'PUT',\n\t\t\t\tbody: blob,\n\t\t\t\theaders: { 'Content-Type': blob.type || 'audio/webm' },\n\t\t\t\tkeepalive: blob.size <= 60 * 1024, // browsers cap keepalive bodies\n\t\t\t})\n\t\t\tif (res.ok) return true\n\t\t\t// 4xx (other than 413) won't get better with retries; bail early.\n\t\t\tif (res.status >= 400 && res.status < 500 && res.status !== 408 && res.status !== 429) {\n\t\t\t\tlogger.error(`chunk ${index} rejected with ${res.status}`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger.warn(`chunk ${index} upload attempt ${attempt + 1} failed`, err)\n\t\t}\n\t\tattempt += 1\n\t\tconst backoff = Math.min(15000, 500 * 2 ** attempt) + Math.floor(Math.random() * 250)\n\t\tawait new Promise(resolve => setTimeout(resolve, backoff))\n\t}\n\treturn false\n}\n\ninterface IndicatorCallbacks {\n\tonFinish: () => void\n\tonToggleTasks: () => void\n\tonToggleMute: () => void\n\tonOpenNote: () => void\n}\n\nfunction buildIndicator(host: HTMLElement, store: RecorderStore, callbacks: IndicatorCallbacks): ShadowRoot {\n\tconst root = host.attachShadow({ mode: 'closed' })\n\tconst style = document.createElement('style')\n\t// Compact, glassy dark pill. Mic chip is now a real button with three\n\t// states (recording / muted / no-mic). Notes button sits beside it.\n\tstyle.textContent = `\n\t\t:host { all: initial; }\n\t\t.anchor {\n\t\t\tposition: fixed;\n\t\t\tbottom: calc(env(safe-area-inset-bottom, 0px) + 16px);\n\t\t\tleft: 50%; transform: translateX(-50%);\n\t\t\tdisplay: flex; flex-direction: column; align-items: center; gap: 8px;\n\t\t\tz-index: 2147483646; max-width: calc(100vw - 32px);\n\t\t\tfont: 13px/1 -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n\t\t\tcolor: #fff;\n\t\t}\n\t\t.bar {\n\t\t\tdisplay: inline-flex; align-items: center; gap: 6px;\n\t\t\tpadding: 6px 8px 6px 6px;\n\t\t\tbackground: rgba(17,17,17,0.82);\n\t\t\tborder: 1px solid rgba(255,255,255,0.08);\n\t\t\tborder-radius: 999px;\n\t\t\tbox-shadow: 0 8px 24px rgba(0,0,0,0.22);\n\t\t\tbackdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);\n\t\t\tmax-width: 100%;\n\t\t}\n\t\t.panel {\n\t\t\tbackground: rgba(17,17,17,0.92);\n\t\t\tborder: 1px solid rgba(255,255,255,0.08);\n\t\t\tborder-radius: 14px; padding: 12px 14px 12px 8px;\n\t\t\tline-height: 1.45;\n\t\t\tbox-shadow: 0 12px 32px rgba(0,0,0,0.32);\n\t\t\tmax-height: min(60vh, 480px);\n\t\t\tmax-width: min(420px, calc(100vw - 32px));\n\t\t\twidth: max-content; overflow-y: auto;\n\t\t}\n\t\t.panel[hidden] { display: none; }\n\t\t.panel ol { margin: 0; padding-left: 26px; }\n\t\t.panel li { margin: 0 0 8px; }\n\t\t.panel li:last-child { margin: 0; }\n\n\t\t/* Mic chip: pill-within-pill with dot + label, doubles as mute toggle. */\n\t\t.mic {\n\t\t\tdisplay: inline-flex; align-items: center; gap: 7px;\n\t\t\tmin-height: 32px; min-width: 44px;\n\t\t\tpadding: 0 11px 0 10px;\n\t\t\tborder-radius: 999px;\n\t\t\tbackground: rgba(255,255,255,0.06);\n\t\t\tborder: 1px solid rgba(255,255,255,0.06);\n\t\t\tcolor: #fff; font: inherit;\n\t\t\tcursor: pointer; appearance: none;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n\t\t}\n\t\t.mic:hover { background: rgba(255,255,255,0.12); }\n\t\t.mic:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.mic[data-mic-state=\"muted\"] {\n\t\t\tbackground: rgba(251, 191, 36, 0.18);\n\t\t\tborder-color: rgba(251, 191, 36, 0.45);\n\t\t\tcolor: #fcd34d;\n\t\t}\n\t\t.mic[data-mic-state=\"muted\"]:hover { background: rgba(251, 191, 36, 0.26); }\n\t\t/* Connecting: getUserMedia pending. Steady amber tint reads as \"working\",\n\t\t distinct from the live red pulse and the failed state below. The icon\n\t\t gets a gentle non-pulsing breathe so it feels alive without alarming. */\n\t\t.mic[data-mic-state=\"connecting\"] {\n\t\t\tbackground: rgba(251, 191, 36, 0.14);\n\t\t\tborder-color: rgba(251, 191, 36, 0.32);\n\t\t\tcolor: #fcd34d;\n\t\t\tcursor: default;\n\t\t}\n\t\t.mic[data-mic-state=\"connecting\"]:hover { background: rgba(251, 191, 36, 0.14); }\n\t\t.mic[data-mic-state=\"connecting\"] .mic-icon {\n\t\t\tcolor: #fbbf24;\n\t\t\tanimation: micBreathe 1.4s ease-in-out infinite;\n\t\t}\n\t\t/* Failed terminal state, actionable. Tappable affordance: clearer border,\n\t\t pointer cursor, brightens on hover/focus to invite the retry tap. */\n\t\t.mic[data-mic-state=\"none\"] {\n\t\t\tbackground: rgba(255,255,255,0.05);\n\t\t\tborder-color: rgba(255,255,255,0.14);\n\t\t\tcolor: rgba(255,255,255,0.72);\n\t\t\tcursor: pointer;\n\t\t}\n\t\t.mic[data-mic-state=\"none\"]:hover {\n\t\t\tbackground: rgba(255,255,255,0.12);\n\t\t\tborder-color: rgba(255,255,255,0.24);\n\t\t\tcolor: #fff;\n\t\t}\n\t\t@keyframes micBreathe {\n\t\t\t0%, 100% { opacity: 0.55; }\n\t\t\t50% { opacity: 1; }\n\t\t}\n\t\t.mic-icon { width: 13px; height: 13px; display: inline-block; flex-shrink: 0; }\n\t\t.mic-label { font-weight: 500; letter-spacing: 0.01em; white-space: nowrap; }\n\n\t\t.dot {\n\t\t\twidth: 7px; height: 7px; border-radius: 50%;\n\t\t\tbackground: #ef4444;\n\t\t\tbox-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6);\n\t\t\tanimation: pulse 1.6s ease-out infinite;\n\t\t\tflex-shrink: 0;\n\t\t}\n\t\t.dot[data-state=\"no-audio\"] { background: #fbbf24; animation: none; }\n\t\t.dot[data-state=\"finishing\"] { background: #fbbf24; animation: none; }\n\t\t.dot[data-state=\"done\"] { background: #10b981; animation: none; }\n\t\t.dot[data-state=\"error\"] { background: #ef4444; animation: none; }\n\n\t\t.btn {\n\t\t\tappearance: none; border: 0; background: rgba(255,255,255,0.10);\n\t\t\tcolor: #fff; font: inherit; font-weight: 600;\n\t\t\tpadding: 6px 12px; min-height: 32px; border-radius: 999px; cursor: pointer;\n\t\t\ttransition: background 0.15s ease, transform 0.06s ease;\n\t\t\tdisplay: inline-flex; align-items: center; gap: 6px;\n\t\t}\n\t\t.btn:hover { background: rgba(255,255,255,0.20); }\n\t\t.btn:active { transform: scale(0.97); }\n\t\t.btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.btn[disabled] { opacity: 0.5; cursor: progress; }\n\t\t.tasks-btn[aria-expanded=\"true\"] { background: rgba(255,255,255,0.24); }\n\n\t\t/* Note button: icon-only, matches mic chip footprint */\n\t\t.note-btn {\n\t\t\twidth: 32px; min-height: 32px; padding: 0;\n\t\t\tbackground: rgba(255,255,255,0.06);\n\t\t\tborder: 1px solid rgba(255,255,255,0.06);\n\t\t\tborder-radius: 999px;\n\t\t\tdisplay: inline-flex; align-items: center; justify-content: center; gap: 4px;\n\t\t\tcolor: #fff; font: inherit; cursor: pointer; appearance: none;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease, width 0.18s ease;\n\t\t\toverflow: hidden;\n\t\t}\n\t\t.note-btn:hover { background: rgba(255,255,255,0.14); }\n\t\t.note-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\t\t.note-btn[data-has-notes=\"true\"] { width: auto; padding: 0 10px 0 9px; gap: 6px; }\n\t\t.note-btn[aria-expanded=\"true\"] { background: rgba(255,255,255,0.22); border-color: rgba(255,255,255,0.18); }\n\t\t.note-icon { width: 14px; height: 14px; display: inline-block; }\n\t\t.note-count { font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }\n\n\t\t.spacer { width: 1px; height: 18px; background: rgba(255,255,255,0.14); margin: 0 1px; }\n\n\t\t@media (max-width: 480px) {\n\t\t\t.bar { gap: 4px; padding: 5px 6px 5px 5px; }\n\t\t\t.btn { padding: 7px 12px; min-height: 38px; }\n\t\t\t.mic, .note-btn { min-height: 38px; }\n\t\t\t.note-btn { width: 38px; }\n\t\t\t.note-btn[data-has-notes=\"true\"] { width: auto; }\n\t\t}\n\n\t\t/* First-mute helper toast: sits above the pill, auto-dismisses */\n\t\t.toast {\n\t\t\tbackground: rgba(17,17,17,0.92);\n\t\t\tborder: 1px solid rgba(251, 191, 36, 0.45);\n\t\t\tcolor: #fff;\n\t\t\tpadding: 9px 14px; border-radius: 12px;\n\t\t\tmax-width: min(340px, calc(100vw - 32px));\n\t\t\tbox-shadow: 0 12px 28px rgba(0,0,0,0.28);\n\t\t\ttext-align: center; line-height: 1.4;\n\t\t\tanimation: toast-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);\n\t\t}\n\t\t.toast[data-leaving=\"true\"] { animation: toast-out 0.24s ease forwards; }\n\t\t.toast strong { color: #fcd34d; font-weight: 600; }\n\t\t@keyframes toast-in {\n\t\t\tfrom { opacity: 0; transform: translateY(6px); }\n\t\t\tto { opacity: 1; transform: translateY(0); }\n\t\t}\n\t\t@keyframes toast-out {\n\t\t\tto { opacity: 0; transform: translateY(4px); }\n\t\t}\n\n\t\t/* Notes popover */\n\t\t.note-popover {\n\t\t\tbackground: rgba(17,17,17,0.94);\n\t\t\tborder: 1px solid rgba(255,255,255,0.10);\n\t\t\tborder-radius: 14px; padding: 12px;\n\t\t\twidth: min(340px, calc(100vw - 32px));\n\t\t\tbox-shadow: 0 18px 40px rgba(0,0,0,0.36);\n\t\t\tdisplay: flex; flex-direction: column; gap: 10px;\n\t\t\tanimation: pop-in 0.18s cubic-bezier(0.2, 0.8, 0.2, 1);\n\t\t}\n\t\t.note-popover[hidden] { display: none; }\n\t\t@keyframes pop-in {\n\t\t\tfrom { opacity: 0; transform: translateY(6px) scale(0.98); }\n\t\t\tto { opacity: 1; transform: translateY(0) scale(1); }\n\t\t}\n\t\t.note-head {\n\t\t\tcolor: rgba(255,255,255,0.7); font-size: 12px;\n\t\t\tfont-weight: 500; letter-spacing: 0.02em;\n\t\t}\n\t\t.note-textarea {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tmin-height: 80px; resize: vertical;\n\t\t\tpadding: 10px 11px;\n\t\t\tbackground: rgba(0,0,0,0.35);\n\t\t\tborder: 1px solid rgba(255,255,255,0.10);\n\t\t\tborder-radius: 10px;\n\t\t\tcolor: #fff; font: inherit; font-size: 13.5px;\n\t\t\tline-height: 1.45;\n\t\t\ttransition: border-color 0.15s ease;\n\t\t}\n\t\t.note-textarea:focus { outline: none; border-color: rgba(255,255,255,0.32); }\n\t\t.note-textarea::placeholder { color: rgba(255,255,255,0.42); }\n\t\t.note-actions {\n\t\t\tdisplay: flex; align-items: center; justify-content: space-between; gap: 8px;\n\t\t}\n\t\t.note-actions .hint {\n\t\t\tcolor: rgba(255,255,255,0.45); font-size: 11px;\n\t\t}\n\t\t.note-actions .group { display: inline-flex; gap: 6px; }\n\t\t.note-actions .btn { padding: 6px 12px; font-size: 12.5px; min-height: 32px; }\n\t\t.btn-primary { background: #fff !important; color: #111; }\n\t\t.btn-primary:hover { background: rgba(255,255,255,0.85) !important; }\n\t\t.btn-ghost { background: transparent; color: rgba(255,255,255,0.7); }\n\t\t.btn-ghost:hover { background: rgba(255,255,255,0.10); color: #fff; }\n\n\t\t/* ---- Finished screen (complete + ended-early). Usero warm-stone palette,\n\t\t shadow-DOM scoped so host CSS can't leak in. Scrollable so the primary\n\t\t action stays reachable on a short phone with the keyboard open. ---- */\n\t\t.thanks {\n\t\t\tposition: fixed; inset: 0;\n\t\t\tdisplay: flex; align-items: flex-start; justify-content: center;\n\t\t\tbackground: rgba(28, 25, 23, 0.62);\n\t\t\tbackdrop-filter: blur(8px);\n\t\t\t-webkit-backdrop-filter: blur(8px);\n\t\t\tcolor: #1c1917;\n\t\t\tfont-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n\t\t\tz-index: 2147483647;\n\t\t\tpadding: 24px 16px calc(env(safe-area-inset-bottom, 0px) + 24px);\n\t\t\toverflow-y: auto;\n\t\t\t-webkit-overflow-scrolling: touch;\n\t\t}\n\t\t.thanks-card {\n\t\t\tbackground: #fff; color: #1c1917;\n\t\t\tborder-radius: 22px; padding: 30px 24px 24px;\n\t\t\tmax-width: 400px; width: 100%;\n\t\t\tmargin: auto 0;\n\t\t\tbox-shadow: 0 24px 60px rgba(28, 25, 23, 0.28), 0 2px 8px rgba(28, 25, 23, 0.12);\n\t\t\ttext-align: left;\n\t\t\tanimation: thanks-in 0.34s cubic-bezier(0.16, 1, 0.3, 1);\n\t\t}\n\t\t@keyframes thanks-in {\n\t\t\tfrom { opacity: 0; transform: translateY(14px) scale(0.985); }\n\t\t\tto { opacity: 1; transform: translateY(0) scale(1); }\n\t\t}\n\t\t.thanks-card .head { text-align: center; }\n\t\t.thanks h2 {\n\t\t\tmargin: 0 0 7px; font-size: 22px; line-height: 1.2;\n\t\t\tfont-weight: 600; letter-spacing: -0.018em; color: #1c1917;\n\t\t}\n\t\t.thanks .lede {\n\t\t\tmargin: 0 auto 22px; font-size: 14.5px; line-height: 1.5;\n\t\t\tcolor: #57534e; text-align: center; max-width: 30ch;\n\t\t}\n\n\t\t/* Status medallion: green tick when complete, warm ring when ended early */\n\t\t.thanks .check {\n\t\t\twidth: 56px; height: 56px; border-radius: 50%;\n\t\t\tdisplay: grid; place-items: center;\n\t\t\tmargin: 0 auto 16px;\n\t\t}\n\t\t.thanks .check.ok {\n\t\t\tbackground: #ecfdf5;\n\t\t\tbox-shadow: inset 0 0 0 1px rgba(16,185,129,0.22);\n\t\t\tcolor: #059669;\n\t\t}\n\t\t.thanks .check.ok svg { width: 26px; height: 26px; }\n\t\t.thanks .check.early {\n\t\t\tbackground: #fff7ed;\n\t\t\tbox-shadow: inset 0 0 0 1px rgba(234,88,12,0.20);\n\t\t\tcolor: #ea580c;\n\t\t}\n\t\t.thanks .check.early svg { width: 24px; height: 24px; }\n\n\t\t/* Verified-checks list (complete) / progress list (ended early) */\n\t\t.thanks .checks {\n\t\t\tlist-style: none; margin: 0 0 4px; padding: 0;\n\t\t\tborder: 1px solid #f0eeec; border-radius: 14px;\n\t\t\tbackground: #fafaf9; overflow: hidden;\n\t\t}\n\t\t.thanks .checks li {\n\t\t\tdisplay: flex; align-items: center; gap: 11px;\n\t\t\tpadding: 12px 14px; font-size: 14px; color: #292524;\n\t\t\tborder-top: 1px solid #f0eeec;\n\t\t}\n\t\t.thanks .checks li:first-child { border-top: 0; }\n\t\t.thanks .checks .ic {\n\t\t\twidth: 20px; height: 20px; border-radius: 50%;\n\t\t\tdisplay: grid; place-items: center; flex-shrink: 0;\n\t\t}\n\t\t.thanks .checks .ic.done { background: #d1fae5; color: #059669; }\n\t\t.thanks .checks .ic.todo { background: #f5f5f4; color: #a8a29e; box-shadow: inset 0 0 0 1px #e7e5e4; }\n\t\t.thanks .checks .ic svg { width: 12px; height: 12px; }\n\t\t.thanks .checks li.muted-row { color: #78716c; }\n\n\t\t/* Payout block (complete) */\n\t\t.thanks .payout { margin-top: 20px; }\n\t\t.thanks .payout-q {\n\t\t\tfont-size: 12px; font-weight: 600; letter-spacing: 0.04em;\n\t\t\ttext-transform: uppercase; color: #a8a29e;\n\t\t\tmargin: 0 0 10px;\n\t\t}\n\t\t.thanks .pay-primary {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; cursor: pointer;\n\t\t\tbackground: #ea580c; color: #fff;\n\t\t\tpadding: 15px 18px; border-radius: 14px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 15.5px;\n\t\t\tline-height: 1.3; text-align: center;\n\t\t\tbox-shadow: 0 6px 16px rgba(234, 88, 12, 0.28);\n\t\t\ttransition: background 0.15s ease, transform 0.07s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .pay-primary:hover { background: #c2410c; }\n\t\t.thanks .pay-primary:active { transform: scale(0.985); }\n\t\t.thanks .pay-primary:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .pay-primary[disabled] { opacity: 0.6; cursor: progress; box-shadow: none; }\n\t\t.thanks .pay-primary .amt { font-variant-numeric: tabular-nums; }\n\t\t.thanks .pay-alt {\n\t\t\tdisplay: block; width: 100%;\n\t\t\tmargin-top: 12px; padding: 4px;\n\t\t\tbackground: none; border: 0; cursor: pointer;\n\t\t\tfont: inherit; font-size: 13px; font-weight: 500;\n\t\t\tcolor: #78716c; text-align: center;\n\t\t\ttext-decoration: underline; text-underline-offset: 2px;\n\t\t\ttransition: color 0.15s ease;\n\t\t}\n\t\t.thanks .pay-alt:hover { color: #44403c; }\n\t\t.thanks .pay-alt:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; border-radius: 6px; }\n\t\t.thanks [hidden] { display: none !important; }\n\n\t\t/* Alternate-email expander */\n\t\t.thanks .pay-edit { margin-top: 14px; animation: pop-in 0.2s cubic-bezier(0.2,0.8,0.2,1); }\n\t\t.thanks .pay-edit[hidden] { display: none; }\n\t\t.thanks .pay-label {\n\t\t\tdisplay: block; margin: 0 0 7px;\n\t\t\tfont-size: 13px; font-weight: 500; color: #44403c;\n\t\t}\n\t\t.thanks .pay-input {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tpadding: 12px 13px;\n\t\t\tbackground: #fff; border: 1px solid #e7e5e4; border-radius: 11px;\n\t\t\tfont: inherit; font-size: 15px; color: #1c1917;\n\t\t\ttransition: border-color 0.15s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .pay-input:focus {\n\t\t\toutline: none; border-color: #ea580c;\n\t\t\tbox-shadow: 0 0 0 3px rgba(234, 88, 12, 0.16);\n\t\t}\n\t\t.thanks .pay-input::placeholder { color: #a8a29e; }\n\t\t.thanks .pay-eta {\n\t\t\tmargin: 14px 0 0; font-size: 12px; line-height: 1.45;\n\t\t\tcolor: #a8a29e; text-align: center;\n\t\t}\n\n\t\t/* Ended-early \"what unlocks the reward\" note */\n\t\t.thanks .early-note {\n\t\t\tdisplay: flex; align-items: flex-start; gap: 10px;\n\t\t\tmargin-top: 18px; padding: 13px 14px;\n\t\t\tbackground: #fff7ed; border: 1px solid #fed7aa; border-radius: 13px;\n\t\t\tfont-size: 13.5px; line-height: 1.45; color: #9a3412;\n\t\t}\n\t\t.thanks .early-note svg { width: 17px; height: 17px; flex-shrink: 0; margin-top: 1px; color: #ea580c; }\n\t\t.thanks .early-actions { margin-top: 18px; display: flex; flex-direction: column; gap: 10px; }\n\t\t.thanks .resume-btn {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; cursor: pointer;\n\t\t\tbackground: #ea580c; color: #fff;\n\t\t\tpadding: 15px 18px; border-radius: 14px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 15.5px;\n\t\t\tbox-shadow: 0 6px 16px rgba(234, 88, 12, 0.28);\n\t\t\ttransition: background 0.15s ease, transform 0.07s ease;\n\t\t}\n\t\t.thanks .resume-btn:hover { background: #c2410c; }\n\t\t.thanks .resume-btn:active { transform: scale(0.985); }\n\t\t.thanks .resume-btn:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .exit-btn {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tappearance: none; border: 0; background: none; cursor: pointer;\n\t\t\tpadding: 4px; font: inherit; font-size: 13px; line-height: 1.45;\n\t\t\tcolor: #78716c; text-align: center;\n\t\t}\n\t\t.thanks .exit-btn:hover { color: #44403c; }\n\t\t.thanks .exit-btn:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; border-radius: 6px; }\n\n\t\t/* End-of-test note (shown after payout is set, complete path only) */\n\t\t.thanks .note-section {\n\t\t\tmargin-top: 22px; padding-top: 20px;\n\t\t\tborder-top: 1px solid #f0eeec;\n\t\t}\n\t\t.thanks .end-label {\n\t\t\tdisplay: block; margin: 0 0 8px;\n\t\t\tfont-size: 13px; font-weight: 500; color: #44403c;\n\t\t}\n\t\t.thanks .end-textarea {\n\t\t\twidth: 100%; box-sizing: border-box;\n\t\t\tmin-height: 84px; resize: vertical;\n\t\t\tpadding: 12px 13px;\n\t\t\tbackground: #fafaf9;\n\t\t\tborder: 1px solid #e7e5e4;\n\t\t\tborder-radius: 12px;\n\t\t\tfont: inherit; font-size: 14.5px; line-height: 1.5;\n\t\t\tcolor: #1c1917;\n\t\t\ttransition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;\n\t\t}\n\t\t.thanks .end-textarea:focus {\n\t\t\toutline: none; border-color: #ea580c; background: #fff;\n\t\t\tbox-shadow: 0 0 0 3px rgba(234, 88, 12, 0.14);\n\t\t}\n\t\t.thanks .end-textarea::placeholder { color: #a8a29e; }\n\t\t.thanks .end-actions {\n\t\t\tdisplay: flex; gap: 10px; margin-top: 14px;\n\t\t}\n\t\t.thanks .end-actions button {\n\t\t\tflex: 1;\n\t\t\tappearance: none; border: 1px solid #e7e5e4;\n\t\t\tbackground: #fff; color: #44403c;\n\t\t\tpadding: 12px 14px; border-radius: 12px;\n\t\t\tfont: inherit; font-weight: 600; font-size: 14px;\n\t\t\tcursor: pointer;\n\t\t\ttransition: background 0.15s ease, border-color 0.15s ease;\n\t\t}\n\t\t.thanks .end-actions button:hover { background: #fafaf9; border-color: #d6d3d1; }\n\t\t.thanks .end-actions button.primary {\n\t\t\tbackground: #1c1917; color: #fff; border-color: #1c1917; flex: 1.4;\n\t\t}\n\t\t.thanks .end-actions button.primary:hover { background: #292524; border-color: #292524; }\n\t\t.thanks .end-actions button:focus-visible { outline: 2px solid #ea580c; outline-offset: 2px; }\n\t\t.thanks .end-hint {\n\t\t\tmargin: 11px 0 0; font-size: 11.5px; color: #a8a29e; text-align: center;\n\t\t}\n\t\t.thanks .end-sent {\n\t\t\tmargin-top: 16px; text-align: center; color: #57534e; font-size: 13.5px; line-height: 1.45;\n\t\t}\n\t\t@media (prefers-reduced-motion: reduce) {\n\t\t\t.thanks-card, .thanks .pay-edit { animation: none; }\n\t\t}\n\n\t\t@keyframes pulse {\n\t\t\t0% { box-shadow: 0 0 0 0 rgba(239,68,68,0.55); }\n\t\t\t70% { box-shadow: 0 0 0 10px rgba(239,68,68,0); }\n\t\t\t100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); }\n\t\t}\n\t\t@media (prefers-reduced-motion: reduce) {\n\t\t\t.dot { animation: none; }\n\t\t\t.toast, .note-popover { animation: none; }\n\t\t}\n\t`\n\tconst anchor = document.createElement('div')\n\tanchor.className = 'anchor'\n\n\tconst panel = document.createElement('div')\n\tpanel.className = 'panel'\n\tpanel.hidden = true\n\n\t// Toast slot: helper messages render here above the bar.\n\tconst toastSlot = document.createElement('div')\n\ttoastSlot.className = 'toast-slot'\n\n\t// Notes popover slot: rendered above the bar when open.\n\tconst notePopover = document.createElement('div')\n\tnotePopover.className = 'note-popover'\n\tnotePopover.hidden = true\n\n\tconst bar = document.createElement('div')\n\tbar.className = 'bar'\n\tbar.setAttribute('role', 'status')\n\tbar.setAttribute('aria-live', 'polite')\n\n\t// Mic chip = real button. Three states driven by data-mic-state.\n\tconst micBtn = document.createElement('button')\n\tmicBtn.type = 'button'\n\tmicBtn.className = 'mic'\n\tmicBtn.setAttribute('data-mic-state', 'recording')\n\tmicBtn.setAttribute('aria-pressed', 'false')\n\tmicBtn.setAttribute('aria-label', 'Mute microphone')\n\n\tconst dot = document.createElement('span')\n\tdot.className = 'dot'\n\tdot.setAttribute('data-state', store.indicatorState)\n\n\tconst micIcon = document.createElement('span')\n\tmicIcon.className = 'mic-icon'\n\tmicIcon.innerHTML = MIC_ICON_SVG\n\tmicIcon.setAttribute('aria-hidden', 'true')\n\n\tconst micLabel = document.createElement('span')\n\tmicLabel.className = 'mic-label'\n\tmicLabel.textContent = 'Recording'\n\n\tmicBtn.appendChild(dot)\n\tmicBtn.appendChild(micIcon)\n\tmicBtn.appendChild(micLabel)\n\tmicBtn.addEventListener('click', callbacks.onToggleMute)\n\tbar.appendChild(micBtn)\n\n\t// Notes button: icon-only by default, grows to show count once notes exist.\n\tconst noteBtn = document.createElement('button')\n\tnoteBtn.type = 'button'\n\tnoteBtn.className = 'note-btn'\n\tnoteBtn.setAttribute('aria-label', 'Add a timestamped note')\n\tnoteBtn.setAttribute('aria-expanded', 'false')\n\tnoteBtn.setAttribute('data-has-notes', 'false')\n\tnoteBtn.innerHTML = `<span class=\"note-icon\" aria-hidden=\"true\">${NOTE_ICON_SVG}</span><span class=\"note-count\" hidden></span>`\n\tnoteBtn.addEventListener('click', callbacks.onOpenNote)\n\tbar.appendChild(noteBtn)\n\n\tconst spacer = document.createElement('span')\n\tspacer.className = 'spacer'\n\tbar.appendChild(spacer)\n\n\tconst btn = document.createElement('button')\n\tbtn.type = 'button'\n\tbtn.className = 'btn finish-btn'\n\tbtn.textContent = 'Finish'\n\tbtn.addEventListener('click', callbacks.onFinish)\n\tbar.appendChild(btn)\n\n\tif (store.tasks.length > 0) installTasksToggle(bar, btn, store, callbacks.onToggleTasks)\n\n\tanchor.appendChild(panel)\n\tanchor.appendChild(toastSlot)\n\tanchor.appendChild(notePopover)\n\tanchor.appendChild(bar)\n\n\troot.appendChild(style)\n\troot.appendChild(anchor)\n\treturn root\n}\n\n// Inline SVGs kept tiny. currentColor so they inherit the chip text color.\nconst MIC_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\"><path d=\"M8 1.5a2 2 0 0 0-2 2v4a2 2 0 1 0 4 0v-4a2 2 0 0 0-2-2Z\" fill=\"currentColor\"/><path d=\"M4 7.5a4 4 0 0 0 8 0M8 11.5v3M5.5 14.5h5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`\nconst MIC_MUTED_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"13\" height=\"13\"><path d=\"M8 1.5a2 2 0 0 0-2 2v3.2L10 11V3.5a2 2 0 0 0-2-2Z\" fill=\"currentColor\"/><path d=\"M4 7.5a4 4 0 0 0 6.5 3.12M12 7.5a4 4 0 0 1-.3 1.5M8 11.5v3M5.5 14.5h5M2 2l12 12\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/></svg>`\nconst NOTE_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\"><path d=\"M3 3.5A1.5 1.5 0 0 1 4.5 2h7A1.5 1.5 0 0 1 13 3.5V10a1.5 1.5 0 0 1-1.5 1.5H7L4 14v-2.5h-.5A1.5 1.5 0 0 1 2 10V3.5A1.5 1.5 0 0 1 3.5 3\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\n// Thanks-screen icons: bold tick (medallion + done rows) and a clock (ended early).\nconst TICK_ICON_SVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 12.5 10 17.5 19 7\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst TICK_SM_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.5 8.5 6.5 11.5 12.5 5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst CLOCK_ICON_SVG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"12\" cy=\"12\" r=\"8.4\" stroke=\"currentColor\" stroke-width=\"2\"/><path d=\"M12 7.5V12l3 2\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`\nconst SPARK_ICON_SVG = `<svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M8 1.5 9.5 6.5 14.5 8 9.5 9.5 8 14.5 6.5 9.5 1.5 8 6.5 6.5Z\" fill=\"currentColor\"/></svg>`\n\nfunction installTasksToggle(bar: HTMLElement, finishBtn: HTMLElement, store: RecorderStore, onToggleTasks: () => void): void {\n\tconst tasksBtn = document.createElement('button')\n\ttasksBtn.type = 'button'\n\ttasksBtn.className = 'btn tasks-btn'\n\ttasksBtn.textContent = `Tasks (${store.tasks.length})`\n\ttasksBtn.setAttribute('aria-expanded', store.tasksPanelOpen ? 'true' : 'false')\n\ttasksBtn.addEventListener('click', onToggleTasks)\n\tbar.insertBefore(tasksBtn, finishBtn)\n}\n\nfunction renderTasksPanel(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst panel = root.querySelector('.panel')\n\tif (!(panel instanceof HTMLElement)) return\n\t// Build content once.\n\tif (!panel.firstChild && store.tasks.length > 0) {\n\t\tconst ol = document.createElement('ol')\n\t\tfor (const task of store.tasks) {\n\t\t\tconst li = document.createElement('li')\n\t\t\tli.textContent = task.prompt\n\t\t\tol.appendChild(li)\n\t\t}\n\t\tpanel.appendChild(ol)\n\t}\n\tpanel.hidden = !store.tasksPanelOpen\n\tconst tasksBtn = root.querySelector('.tasks-btn')\n\tif (tasksBtn instanceof HTMLElement) {\n\t\ttasksBtn.setAttribute('aria-expanded', store.tasksPanelOpen ? 'true' : 'false')\n\t}\n}\n\nfunction readTasksPanelOpen(): boolean {\n\ttry { return window.sessionStorage?.getItem(TASKS_PANEL_OPEN_STORAGE_KEY) === '1' } catch { return false }\n}\nfunction writeTasksPanelOpen(open: boolean): void {\n\ttry { window.sessionStorage?.setItem(TASKS_PANEL_OPEN_STORAGE_KEY, open ? '1' : '0') } catch { /* ignore */ }\n}\n\nfunction micChipState(store: RecorderStore): 'recording' | 'muted' | 'none' | 'connecting' | 'silent' | 'inactive' {\n\tif (store.indicatorState === 'finishing' || store.indicatorState === 'done' || store.indicatorState === 'error') {\n\t\treturn 'inactive'\n\t}\n\tif (!store.hasMicPermission) {\n\t\t// Pending getUserMedia: show \"connecting\" so granted users never flash\n\t\t// the failure copy. Once startRecording resolves or rejects it clears\n\t\t// micAcquiring, and we fall through to the terminal \"none\" state.\n\t\tif (store.micAcquiring) return 'connecting'\n\t\treturn 'none'\n\t}\n\tif (store.muted) return 'muted'\n\t// Permission granted and not muted, but the live track is reading digital\n\t// silence (dead mic or a virtual silent input device). Warn, non-blocking:\n\t// recording continues, this just prompts the participant to check their mic.\n\tif (store.micSilent) return 'silent'\n\treturn 'recording'\n}\n\nfunction renderIndicatorState(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst dot = root.querySelector('.dot')\n\tconst mic = root.querySelector<HTMLButtonElement>('.mic')\n\tconst micIcon = root.querySelector('.mic-icon')\n\tconst micLabel = root.querySelector('.mic-label')\n\tconst btn = root.querySelector<HTMLButtonElement>('.finish-btn')\n\tif (!(dot instanceof HTMLElement) || !mic || !(micIcon instanceof HTMLElement) || !(micLabel instanceof HTMLElement) || !btn) return\n\n\tdot.setAttribute('data-state', store.indicatorState)\n\tconst chipState = micChipState(store)\n\t// The silent-mic warning reuses the existing \"none\" warning treatment\n\t// (muted-grey, tappable retry affordance) rather than inventing a new visual\n\t// — same as the \"Mic blocked, tap to retry\" failed state, just different copy.\n\tconst micStateAttr = chipState === 'inactive' || chipState === 'silent' ? 'none' : chipState\n\tmic.setAttribute('data-mic-state', micStateAttr)\n\t// Distinguish \"acquiring\" (genuinely failed, actionable) from \"connecting\"\n\t// at the attribute level so the dot/visuals key off the right state. The\n\t// failed terminal chip is a retry affordance; mark it so CSS can style it.\n\tmic.removeAttribute('data-mic-fail')\n\tif (chipState === 'none') mic.setAttribute('data-mic-fail', store.micFailReason ?? 'blocked')\n\n\t// Finish-button copy is driven by the indicatorState (network / lifecycle).\n\tswitch (store.indicatorState) {\n\t\tcase 'recording':\n\t\tcase 'no-audio':\n\t\t\tbtn.textContent = 'Finish'\n\t\t\tbtn.disabled = false\n\t\t\tbreak\n\t\tcase 'finishing':\n\t\t\tbtn.textContent = 'Saving'\n\t\t\tbtn.disabled = true\n\t\t\tbreak\n\t\tcase 'done':\n\t\t\tbtn.textContent = 'Done'\n\t\t\tbtn.disabled = true\n\t\t\tbreak\n\t\tcase 'error':\n\t\t\tbtn.textContent = 'Retry'\n\t\t\tbtn.disabled = false\n\t\t\tbreak\n\t}\n\n\t// Mic chip copy + icon. Replay continues in all states; the chip only\n\t// describes the audio track.\n\tswitch (chipState) {\n\t\tcase 'recording':\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent = 'Recording'\n\t\t\tmic.setAttribute('aria-label', 'Mute microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\tcase 'muted':\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tmicLabel.textContent = 'Muted'\n\t\t\tmic.setAttribute('aria-label', 'Unmute microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'true')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\tcase 'connecting':\n\t\t\t// getUserMedia still pending. Granted users sit here briefly instead\n\t\t\t// of flashing the failure copy. Not yet a toggle, so unfocusable.\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent = 'Connecting mic'\n\t\t\tmic.setAttribute('aria-label', 'Connecting microphone')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.setAttribute('tabindex', '-1')\n\t\t\tbreak\n\t\tcase 'silent':\n\t\t\t// Permission granted, recording live, but the input is digital\n\t\t\t// silence (dead mic or a virtual silent device). Warn, non-blocking:\n\t\t\t// recording continues. Tappable so the participant can re-acquire the\n\t\t\t// mic after switching their input device. Auto-clears when real audio\n\t\t\t// returns (the monitor flips store.micSilent back to false).\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tmicLabel.textContent = \"We can't hear you, tap to recheck\"\n\t\t\tmic.setAttribute('aria-label', \"We can't hear your microphone. Check your input device, then tap to recheck. Recording continues.\")\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\tcase 'none': {\n\t\t\t// Genuinely failed terminal state. Actionable: the chip is a button\n\t\t\t// that re-attempts mic acquisition. Keyboard-focusable (no tabindex\n\t\t\t// -1). Replay keeps recording regardless.\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tconst failLabel =\n\t\t\t\tstore.micFailReason === 'not-found' ? 'No mic found, tap to retry' :\n\t\t\t\t'Mic blocked, tap to retry'\n\t\t\tconst failAria =\n\t\t\t\tstore.micFailReason === 'not-found'\n\t\t\t\t\t? 'No microphone found, tap to retry. Replay continues.'\n\t\t\t\t\t: 'Microphone blocked, tap to retry. Replay continues.'\n\t\t\tmicLabel.textContent = failLabel\n\t\t\tmic.setAttribute('aria-label', failAria)\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.removeAttribute('tabindex')\n\t\t\tbreak\n\t\t}\n\t\tcase 'inactive':\n\t\t\tmicIcon.innerHTML = MIC_ICON_SVG\n\t\t\tmicLabel.textContent =\n\t\t\t\tstore.indicatorState === 'finishing' ? 'Saving' :\n\t\t\t\tstore.indicatorState === 'done' ? 'Saved' :\n\t\t\t\t'Save failed'\n\t\t\tmic.setAttribute('aria-label', 'Recording stopped')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.setAttribute('tabindex', '-1')\n\t\t\tbreak\n\t}\n}\n\nfunction renderNotesCount(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst noteBtn = root.querySelector('.note-btn')\n\tconst count = root.querySelector('.note-count')\n\tif (!(noteBtn instanceof HTMLElement) || !(count instanceof HTMLElement)) return\n\tconst n = store.notes.length\n\tnoteBtn.setAttribute('data-has-notes', n > 0 ? 'true' : 'false')\n\tif (n > 0) {\n\t\tcount.textContent = String(n)\n\t\tcount.hidden = false\n\t\tnoteBtn.setAttribute('aria-label', `Add a timestamped note (${n} so far)`)\n\t} else {\n\t\tcount.textContent = ''\n\t\tcount.hidden = true\n\t\tnoteBtn.setAttribute('aria-label', 'Add a timestamped note')\n\t}\n}\n\nfunction showMuteToast(store: RecorderStore): void {\n\tif (store.muteToastShown) return\n\tstore.muteToastShown = true\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst slot = root.querySelector('.toast-slot')\n\tif (!(slot instanceof HTMLElement)) return\n\tslot.innerHTML = ''\n\tconst toast = document.createElement('div')\n\ttoast.className = 'toast'\n\ttoast.setAttribute('role', 'status')\n\ttoast.innerHTML = `<strong>Mic off.</strong> Screen is still recording. Tap to unmute.`\n\tslot.appendChild(toast)\n\tconst outer = window.setTimeout(() => {\n\t\tif (!toast.isConnected) return\n\t\ttoast.setAttribute('data-leaving', 'true')\n\t\tconst inner = window.setTimeout(() => {\n\t\t\tif (toast.isConnected) toast.remove()\n\t\t}, 260)\n\t\tstore.muteToastTimers.push(inner)\n\t}, 3000)\n\tstore.muteToastTimers.push(outer)\n}\n\nfunction openNotePopover(store: RecorderStore, onSave: (text: string) => void, onCancel: () => void): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst pop = root.querySelector('.note-popover')\n\tconst noteBtn = root.querySelector('.note-btn')\n\tif (!(pop instanceof HTMLElement) || !(noteBtn instanceof HTMLElement)) return\n\n\tstore.notesPopoverOpen = true\n\tstore.notePopoverAtMs = Date.now() - store.startedAt\n\tnoteBtn.setAttribute('aria-expanded', 'true')\n\n\tpop.innerHTML = ''\n\tconst head = document.createElement('div')\n\thead.className = 'note-head'\n\thead.innerHTML = `<span>Add a note</span>`\n\n\tconst form = document.createElement('form')\n\tform.style.cssText = 'display:flex;flex-direction:column;gap:10px;margin:0;'\n\tform.noValidate = true\n\n\tconst ta = document.createElement('textarea')\n\tta.className = 'note-textarea'\n\tta.placeholder = 'What just happened? Confusing? Surprising? Broken?'\n\tta.rows = 3\n\tta.setAttribute('aria-label', 'Note text')\n\n\tconst actions = document.createElement('div')\n\tactions.className = 'note-actions'\n\tconst hint = document.createElement('span')\n\thint.className = 'hint'\n\thint.innerHTML = '<kbd style=\"font-family:inherit\">Cmd</kbd>+Enter to save'\n\tconst group = document.createElement('div')\n\tgroup.className = 'group'\n\tconst cancelBtn = document.createElement('button')\n\tcancelBtn.type = 'button'\n\tcancelBtn.className = 'btn btn-ghost'\n\tcancelBtn.textContent = 'Cancel'\n\tconst saveBtn = document.createElement('button')\n\tsaveBtn.type = 'submit'\n\tsaveBtn.className = 'btn btn-primary'\n\tsaveBtn.textContent = 'Save'\n\tgroup.appendChild(cancelBtn)\n\tgroup.appendChild(saveBtn)\n\tactions.appendChild(hint)\n\tactions.appendChild(group)\n\n\tform.appendChild(ta)\n\tform.appendChild(actions)\n\n\tpop.appendChild(head)\n\tpop.appendChild(form)\n\tpop.hidden = false\n\n\tconst submit = (): void => {\n\t\tconst text = ta.value.trim()\n\t\tif (!text) { onCancel(); return }\n\t\tonSave(text)\n\t}\n\tform.addEventListener('submit', e => { e.preventDefault(); submit() })\n\tcancelBtn.addEventListener('click', () => onCancel())\n\tta.addEventListener('keydown', e => {\n\t\tif ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n\t\t\te.preventDefault()\n\t\t\tsubmit()\n\t\t} else if (e.key === 'Escape') {\n\t\t\te.preventDefault()\n\t\t\tonCancel()\n\t\t}\n\t})\n\n\t// Autofocus on next frame so animation can finish without scroll jank.\n\twindow.requestAnimationFrame(() => { ta.focus({ preventScroll: true }) })\n}\n\nfunction closeNotePopover(store: RecorderStore): void {\n\tconst root = store.indicatorRoot\n\tif (!root) return\n\tconst pop = root.querySelector('.note-popover')\n\tconst noteBtn = root.querySelector('.note-btn')\n\tif (pop instanceof HTMLElement) {\n\t\tpop.hidden = true\n\t\tpop.innerHTML = ''\n\t}\n\tif (noteBtn instanceof HTMLElement) noteBtn.setAttribute('aria-expanded', 'false')\n\tstore.notesPopoverOpen = false\n\tstore.notePopoverAtMs = null\n}\n\n// Escape user-controlled strings before they touch innerHTML. The payout email\n// comes from our own DB, but it originated as participant input, so treat it as\n// untrusted and never interpolate it raw into markup.\nfunction escapeHtml(value: string): string {\n\treturn value\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;')\n\t\t.replace(/\"/g, '&quot;')\n\t\t.replace(/'/g, '&#39;')\n}\n\nfunction isValidEmail(value: string): boolean {\n\t// Pragmatic check; the server re-validates with zod .email().\n\treturn /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)\n}\n\ninterface ThanksOptions {\n\t// Payment summary from the first finalise response. Null when the server is\n\t// older / didn't return it: we fall back to the neutral note-only screen.\n\tpayment: PaymentSummary | null\n\t// Confirm the participant's payout destination. Resolves true on success.\n\tonPayout: (destination: string | null) => Promise<boolean>\n\t// End-of-test wrap-up note (complete path). Throws on failure so the UI can retry.\n\tonSubmitNote: (text: string) => Promise<void> | void\n\tonSkip: () => void\n\t// Re-arm recording and dismiss the overlay (ended-early path \"Resume\").\n\tonResume: () => void\n}\n\nfunction showThanksScreen(root: ShadowRoot, opts: ThanksOptions): void {\n\tconst overlay = document.createElement('div')\n\toverlay.className = 'thanks'\n\toverlay.setAttribute('role', 'dialog')\n\toverlay.setAttribute('aria-modal', 'true')\n\n\tconst card = document.createElement('div')\n\tcard.className = 'thanks-card'\n\toverlay.appendChild(card)\n\troot.appendChild(overlay)\n\n\t// Ended-early branch: warmer, non-punishing, keep Resume primary.\n\tif (opts.payment && !opts.payment.qualified) {\n\t\trenderEndedEarly(card, opts)\n\t\treturn\n\t}\n\n\t// Complete branch (also the fallback when payment is null: a clean \"saved\"\n\t// confirmation with the wrap-up note, no payout block since we have no data).\n\trenderComplete(card, opts)\n}\n\n// Builds the verified-checks list. `done` rows get the green tick; an unfinished\n// tasks row (ended-early) gets the hollow todo dot.\nfunction checksList(rows: Array<{ label: string; done: boolean; muted?: boolean }>): string {\n\tconst items = rows\n\t\t.map(r => {\n\t\t\tconst icClass = r.done ? 'ic done' : 'ic todo'\n\t\t\tconst icon = r.done ? TICK_SM_SVG : ''\n\t\t\tconst liClass = r.muted ? ' class=\"muted-row\"' : ''\n\t\t\treturn `<li${liClass}><span class=\"${icClass}\" aria-hidden=\"true\">${icon}</span><span>${escapeHtml(r.label)}</span></li>`\n\t\t})\n\t\t.join('')\n\treturn `<ul class=\"checks\">${items}</ul>`\n}\n\nfunction renderComplete(card: HTMLElement, opts: ThanksOptions): void {\n\tconst payment = opts.payment\n\tconst reward = payment?.reward ?? null\n\tconst defaultEmail = payment?.payoutEmail ?? null\n\tconst tasksTotal = payment?.tasksTotal ?? 0\n\n\tconst head = document.createElement('div')\n\thead.className = 'head'\n\tconst lede = reward\n\t\t? `We have your recording. Confirm where to send your ${escapeHtml(reward)} and the team will review it shortly.`\n\t\t: 'We have your recording. Thanks for taking the time to walk us through it.'\n\thead.innerHTML = `\n\t\t<div class=\"check ok\" aria-hidden=\"true\">${TICK_ICON_SVG}</div>\n\t\t<h2>You're done.</h2>\n\t\t<p class=\"lede\">${lede}</p>\n\t\t${tasksTotal > 0\n\t\t\t? checksList([\n\t\t\t\t\t{ label: tasksTotal === 1 ? '1 task completed' : `All ${tasksTotal} tasks completed`, done: true },\n\t\t\t\t\t{ label: 'Voice recording captured', done: true },\n\t\t\t\t\t{ label: 'Screen replay uploaded', done: true },\n\t\t\t\t])\n\t\t\t: checksList([\n\t\t\t\t\t{ label: 'Voice recording captured', done: true },\n\t\t\t\t\t{ label: 'Screen replay uploaded', done: true },\n\t\t\t\t])}\n\t`\n\tcard.appendChild(head)\n\n\t// If we have no payment data (older server) skip payout entirely and go\n\t// straight to the wrap-up note.\n\tif (!payment) {\n\t\tappendNoteSection(card, opts, 'Your session was saved. Anything you would add?')\n\t\treturn\n\t}\n\n\trenderPayout(card, opts, reward, defaultEmail)\n}\n\n// Payout capture: one-tap default to the sign-up email, with a quieter expander\n// to use a different email. Progressive disclosure (the default path is not a form).\nfunction renderPayout(card: HTMLElement, opts: ThanksOptions, reward: string | null, defaultEmail: string | null): void {\n\tconst wrap = document.createElement('div')\n\twrap.className = 'payout'\n\n\tconst rewardLabel = reward ?? 'my reward'\n\tconst haveDefault = !!defaultEmail && isValidEmail(defaultEmail)\n\n\twrap.innerHTML = `\n\t\t<p class=\"payout-q\">Where should we send ${escapeHtml(reward ?? 'your reward')}?</p>\n\t\t<button type=\"button\" class=\"pay-primary\" ${haveDefault ? '' : 'hidden'}>\n\t\t\tSend <span class=\"amt\">${escapeHtml(rewardLabel)}</span>${haveDefault ? ` to ${escapeHtml(defaultEmail as string)}` : ''}\n\t\t</button>\n\t\t<button type=\"button\" class=\"pay-alt\">${haveDefault ? 'Use a different email' : 'Add your payout email'}</button>\n\t\t<div class=\"pay-edit\" ${haveDefault ? 'hidden' : ''}>\n\t\t\t<label class=\"pay-label\" for=\"usero-payout-email\">Payout email</label>\n\t\t\t<input id=\"usero-payout-email\" class=\"pay-input\" type=\"email\" inputmode=\"email\"\n\t\t\t\tautocomplete=\"email\" placeholder=\"you@example.com\" value=\"${haveDefault ? '' : escapeHtml(defaultEmail ?? '')}\" />\n\t\t</div>\n\t\t<p class=\"pay-eta\">Reward arrives within about 2 days of the team reviewing it.</p>\n\t`\n\tcard.appendChild(wrap)\n\n\tconst primary = wrap.querySelector<HTMLButtonElement>('.pay-primary')\n\tconst altLink = wrap.querySelector<HTMLButtonElement>('.pay-alt')\n\tconst editBox = wrap.querySelector<HTMLElement>('.pay-edit')\n\tconst emailInput = wrap.querySelector<HTMLInputElement>('.pay-input')\n\tif (!primary || !altLink || !editBox || !emailInput) return\n\n\tconst confirm = async (destination: string | null): Promise<void> => {\n\t\tprimary.disabled = true\n\t\taltLink.style.pointerEvents = 'none'\n\t\tconst ok = await opts.onPayout(destination)\n\t\t// Whatever the network outcome, the session is payable (server defaults to\n\t\t// the sign-up email). Move the participant forward rather than trapping them.\n\t\twrap.remove()\n\t\tconst confirmedTo = destination ?? defaultEmail\n\t\tconst sentMsg = confirmedTo\n\t\t\t? `${reward ? `${reward} is` : \"Your reward is\"} set to go to ${confirmedTo}.`\n\t\t\t: 'Your reward is on its way.'\n\t\tconst note = ok ? sentMsg : `${sentMsg} (We will retry sending the details.)`\n\t\tappendNoteSection(card, opts, `${note} Anything you would add before you go?`)\n\t}\n\n\t// One-tap default path.\n\tprimary.addEventListener('click', () => { void confirm(null) })\n\n\t// Expander: reveal the email field, focus it, submit on Enter.\n\tconst openEditor = (): void => {\n\t\tprimary.hidden = true\n\t\taltLink.hidden = true\n\t\teditBox.hidden = false\n\t\t// Append a confirm button under the input on first open.\n\t\tif (!editBox.querySelector('.pay-confirm')) {\n\t\t\tconst btn = document.createElement('button')\n\t\t\tbtn.type = 'button'\n\t\t\tbtn.className = 'pay-primary pay-confirm'\n\t\t\tbtn.style.marginTop = '12px'\n\t\t\tbtn.textContent = reward ? `Send ${reward} here` : 'Use this email'\n\t\t\teditBox.appendChild(btn)\n\t\t\tbtn.addEventListener('click', () => void submitEmail())\n\t\t}\n\t\twindow.requestAnimationFrame(() => emailInput.focus({ preventScroll: true }))\n\t}\n\n\tconst submitEmail = async (): Promise<void> => {\n\t\tconst value = emailInput.value.trim().toLowerCase()\n\t\tif (!isValidEmail(value)) {\n\t\t\temailInput.focus()\n\t\t\temailInput.style.borderColor = '#dc2626'\n\t\t\treturn\n\t\t}\n\t\tawait confirm(value)\n\t}\n\n\taltLink.addEventListener('click', openEditor)\n\temailInput.addEventListener('input', () => { emailInput.style.borderColor = '' })\n\temailInput.addEventListener('keydown', e => {\n\t\tif (e.key === 'Enter') { e.preventDefault(); void submitEmail() }\n\t})\n}\n\nfunction renderEndedEarly(card: HTMLElement, opts: ThanksOptions): void {\n\tconst payment = opts.payment\n\tconst done = payment?.tasksDone ?? 0\n\tconst total = payment?.tasksTotal ?? 0\n\tconst reward = payment?.reward ?? null\n\n\tconst head = document.createElement('div')\n\thead.className = 'head'\n\tconst lede = total > 0\n\t\t? `We saw ${done} of ${total} ${total === 1 ? 'task' : 'tasks'} finished. No worries, you can pick up right where you left off.`\n\t\t: 'It looks like the session ended before you finished. No worries, you can pick up where you left off.'\n\thead.innerHTML = `\n\t\t<div class=\"check early\" aria-hidden=\"true\">${CLOCK_ICON_SVG}</div>\n\t\t<h2>Looks like you stopped early</h2>\n\t\t<p class=\"lede\">${lede}</p>\n\t`\n\tcard.appendChild(head)\n\n\t// Per-task progress when we know the counts: done rows ticked, the rest hollow.\n\tif (total > 0) {\n\t\tconst rows: Array<{ label: string; done: boolean }> = []\n\t\tfor (let i = 0; i < total; i += 1) {\n\t\t\trows.push({ label: `Task ${i + 1}`, done: i < done })\n\t\t}\n\t\tconst list = document.createElement('div')\n\t\tlist.innerHTML = checksList(rows)\n\t\tconst ul = list.firstElementChild\n\t\tif (ul) card.appendChild(ul)\n\t}\n\n\tconst note = document.createElement('div')\n\tnote.className = 'early-note'\n\tnote.innerHTML = `${SPARK_ICON_SVG}<span><strong style=\"font-weight:600\">Resume the test.</strong> ${\n\t\treward ? `Your ${escapeHtml(reward)} reward unlocks` : 'The reward unlocks'\n\t} once all ${total > 0 ? total : 'the'} ${total === 1 ? 'task is' : 'tasks are'} done.</span>`\n\tcard.appendChild(note)\n\n\tconst actions = document.createElement('div')\n\tactions.className = 'early-actions'\n\tconst resume = document.createElement('button')\n\tresume.type = 'button'\n\tresume.className = 'resume-btn'\n\tresume.textContent = 'Resume where I left off'\n\tconst exit = document.createElement('button')\n\texit.type = 'button'\n\texit.className = 'exit-btn'\n\texit.textContent = \"Thanks for trying. No reward this time since the tasks weren't finished.\"\n\tactions.appendChild(resume)\n\tactions.appendChild(exit)\n\tcard.appendChild(actions)\n\n\tresume.addEventListener('click', () => {\n\t\tconst overlay = card.closest('.thanks')\n\t\tif (overlay instanceof HTMLElement) overlay.remove()\n\t\topts.onResume()\n\t})\n\texit.addEventListener('click', () => {\n\t\tcard.innerHTML = ''\n\t\tconst sent = document.createElement('p')\n\t\tsent.className = 'end-sent'\n\t\tsent.textContent = 'Thanks for giving it a go. You can close this tab now.'\n\t\tcard.appendChild(sent)\n\t})\n}\n\n// The wrap-up note section, shared by the complete path (after payout) and the\n// older-server fallback. Mirrors the prior behaviour: Cmd/Ctrl+Enter to send,\n// retry on failure, skip allowed.\nfunction appendNoteSection(card: HTMLElement, opts: ThanksOptions, prompt: string): void {\n\tconst section = document.createElement('div')\n\tsection.className = 'note-section'\n\n\tconst form = document.createElement('form')\n\tform.noValidate = true\n\tform.innerHTML = `\n\t\t<label class=\"end-label\" for=\"usero-end-note\">${escapeHtml(prompt)}</label>\n\t\t<textarea\n\t\t\tid=\"usero-end-note\"\n\t\t\tclass=\"end-textarea\"\n\t\t\trows=\"3\"\n\t\t\tplaceholder=\"Confusing bits, things you liked, what you'd change...\"\n\t\t></textarea>\n\t\t<div class=\"end-actions\">\n\t\t\t<button type=\"button\" class=\"skip\">Skip</button>\n\t\t\t<button type=\"submit\" class=\"primary\">Send feedback</button>\n\t\t</div>\n\t\t<p class=\"end-hint\">Cmd or Ctrl plus Enter to send. Either button is fine.</p>\n\t`\n\tsection.appendChild(form)\n\tcard.appendChild(section)\n\n\tconst ta = form.querySelector<HTMLTextAreaElement>('#usero-end-note')\n\tconst skipBtn = form.querySelector<HTMLButtonElement>('button.skip')\n\tif (!ta || !skipBtn) return\n\n\tconst swapToSent = (message: string): void => {\n\t\tsection.remove()\n\t\tconst sent = document.createElement('p')\n\t\tsent.className = 'end-sent'\n\t\tsent.textContent = message\n\t\tcard.appendChild(sent)\n\t}\n\n\tconst ERROR_CLASS = 'end-error'\n\tconst showError = (message: string): void => {\n\t\tconst prior = form.querySelector(`.${ERROR_CLASS}`)\n\t\tif (prior) prior.remove()\n\t\tconst err = document.createElement('p')\n\t\terr.className = ERROR_CLASS\n\t\terr.textContent = message\n\t\terr.setAttribute('role', 'alert')\n\t\terr.style.cssText = 'margin:10px 0 0;font-size:12.5px;color:#b91c1c;text-align:center;'\n\t\tform.appendChild(err)\n\t}\n\n\tconst submit = async (): Promise<void> => {\n\t\tconst text = ta.value.trim()\n\t\tta.disabled = true\n\t\tskipBtn.disabled = true\n\t\tconst submitBtn = form.querySelector<HTMLButtonElement>('button.primary')\n\t\tif (submitBtn) submitBtn.disabled = true\n\t\tif (text) {\n\t\t\ttry {\n\t\t\t\tawait Promise.race([\n\t\t\t\t\tPromise.resolve(opts.onSubmitNote(text)),\n\t\t\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\t\t\twindow.setTimeout(() => reject(new Error('timeout')), 30000)\n\t\t\t\t\t}),\n\t\t\t\t])\n\t\t\t\tswapToSent('Thanks. You can close this tab.')\n\t\t\t} catch {\n\t\t\t\tta.disabled = false\n\t\t\t\tskipBtn.disabled = false\n\t\t\t\tif (submitBtn) submitBtn.disabled = false\n\t\t\t\tshowError(\"Couldn't save your note. Try again?\")\n\t\t\t}\n\t\t} else {\n\t\t\topts.onSkip()\n\t\t\tswapToSent('All set. You can close this tab.')\n\t\t}\n\t}\n\n\tform.addEventListener('submit', e => { e.preventDefault(); void submit() })\n\tskipBtn.addEventListener('click', () => { ta.value = ''; void submit() })\n\tta.addEventListener('keydown', e => {\n\t\tif ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n\t\t\te.preventDefault()\n\t\t\tvoid submit()\n\t\t}\n\t})\n\n\twindow.requestAnimationFrame(() => { ta.focus({ preventScroll: true }) })\n}\n\nfunction parseTasks(raw: unknown): UserTestTask[] {\n\tif (!Array.isArray(raw)) return []\n\tconst out = raw.flatMap((item: unknown): UserTestTask[] => {\n\t\tconst t = item as { id?: unknown; prompt?: unknown; sortOrder?: unknown }\n\t\tif (!t || typeof t.id !== 'string' || typeof t.prompt !== 'string' || typeof t.sortOrder !== 'number') return []\n\t\treturn [{ id: t.id, prompt: t.prompt, sortOrder: t.sortOrder }]\n\t})\n\tout.sort((a, b) => a.sortOrder - b.sortOrder)\n\treturn out\n}\n\nasync function createSession(\n\tapiUrl: string,\n\tslug: string,\n\ttesterName: string | undefined,\n): Promise<{ sessionId: string; clientId: string; tasks: UserTestTask[] } | null> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ slug, ...(testerName ? { testerName } : {}) }),\n\t\t})\n\t\tif (!res.ok) return null\n\t\tconst json = (await res.json()) as { sessionId?: unknown; clientId?: unknown; tasks?: unknown }\n\t\tif (typeof json.sessionId !== 'string' || typeof json.clientId !== 'string') return null\n\t\treturn { sessionId: json.sessionId, clientId: json.clientId, tasks: parseTasks(json.tasks) }\n\t} catch {\n\t\treturn null\n\t}\n}\n\n// Adopt an existing session the entry screen already created (carried via the\n// `uts` URL param). GET the clientId + tasks for it; we do NOT create a new\n// session. Returns null on any failure so the caller can surface the error\n// state (we deliberately do NOT silently fall back to createSession here: a\n// present-but-unresolvable uts means something is wrong, and creating a second\n// anonymous session is exactly the double-session bug we're avoiding).\nasync function adoptSession(\n\tapiUrl: string,\n\tsessionId: string,\n): Promise<{ sessionId: string; clientId: string; tasks: UserTestTask[] } | null> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/adopt`, {\n\t\t\tmethod: 'GET',\n\t\t})\n\t\tif (!res.ok) return null\n\t\tconst json = (await res.json()) as { sessionId?: unknown; clientId?: unknown; tasks?: unknown }\n\t\tif (typeof json.sessionId !== 'string' || typeof json.clientId !== 'string') return null\n\t\treturn { sessionId: json.sessionId, clientId: json.clientId, tasks: parseTasks(json.tasks) }\n\t} catch {\n\t\treturn null\n\t}\n}\n\ninterface FinaliseNote {\n\tatMs: number\n\ttext: string\n}\n\n// Participant-facing payment summary the finalise endpoint returns on the FIRST\n// call. Drives the finished screen: `qualified` picks the complete vs ended-early\n// layout, `reward` is the formatted headline (e.g. \"$15\"), `payoutEmail` seeds the\n// one-tap payout default, tasksDone/tasksTotal drive the ended-early missing line.\n// Every field is optional so an older server (no `payment` block) degrades to the\n// neutral \"thanks, saved\" screen rather than throwing.\ninterface PaymentSummary {\n\tqualified: boolean\n\treward: string | null\n\tpayoutEmail: string | null\n\ttasksDone: number\n\ttasksTotal: number\n}\n\ninterface FinaliseResult {\n\tok: boolean\n\t// Only present on the first finalise call (the server computes it once).\n\tpayment: PaymentSummary | null\n}\n\nfunction parsePaymentSummary(raw: unknown): PaymentSummary | null {\n\tif (typeof raw !== 'object' || raw === null) return null\n\tconst p = raw as {\n\t\tqualified?: unknown\n\t\treward?: unknown\n\t\tpayoutEmail?: unknown\n\t\ttasksDone?: unknown\n\t\ttasksTotal?: unknown\n\t}\n\tif (typeof p.qualified !== 'boolean') return null\n\treturn {\n\t\tqualified: p.qualified,\n\t\treward: typeof p.reward === 'string' ? p.reward : null,\n\t\tpayoutEmail: typeof p.payoutEmail === 'string' ? p.payoutEmail : null,\n\t\ttasksDone: typeof p.tasksDone === 'number' ? p.tasksDone : 0,\n\t\ttasksTotal: typeof p.tasksTotal === 'number' ? p.tasksTotal : 0,\n\t}\n}\n\nasync function finaliseSession(\n\tapiUrl: string,\n\tsessionId: string,\n\tdurationSeconds: number,\n\textras: {\n\t\tmutedSegments?: MutedSegment[]\n\t\tendNote?: string | null\n\t\tnotes?: FinaliseNote[]\n\t\t// Replay linkage. sdkSessionId is the primary, always-available key:\n\t\t// the server resolves the SessionReplay by (clientId + sdkSessionId)\n\t\t// and sets UserTestSession.sessionReplayId. replayOffsetMs is the\n\t\t// offset captured at session start, only present when replay was\n\t\t// active. Both optional so older servers tolerate their absence and a\n\t\t// test with no replay still finalises cleanly.\n\t\tsdkSessionId?: string\n\t\treplayOffsetMs?: number\n\t} = {},\n): Promise<FinaliseResult> {\n\ttry {\n\t\tconst body: Record<string, unknown> = {\n\t\t\tdurationSeconds: Math.max(0, Math.round(durationSeconds)),\n\t\t}\n\t\tif (extras.mutedSegments && extras.mutedSegments.length > 0) {\n\t\t\tbody.mutedSegments = extras.mutedSegments\n\t\t}\n\t\tconst trimmedEndNote = extras.endNote?.trim()\n\t\tif (trimmedEndNote) body.endNote = trimmedEndNote\n\t\tif (extras.notes && extras.notes.length > 0) {\n\t\t\t// Server caps at 200; trim defensively here too.\n\t\t\tbody.notes = extras.notes.slice(0, 200).map(n => ({\n\t\t\t\tatMs: Math.max(0, Math.round(n.atMs)),\n\t\t\t\ttext: n.text,\n\t\t\t}))\n\t\t}\n\t\tif (extras.sdkSessionId) body.sdkSessionId = extras.sdkSessionId\n\t\tif (typeof extras.replayOffsetMs === 'number') {\n\t\t\tbody.replayOffsetMs = Math.max(0, Math.round(extras.replayOffsetMs))\n\t\t}\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/finalise`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify(body),\n\t\t\tkeepalive: true,\n\t\t})\n\t\tif (!res.ok) return { ok: false, payment: null }\n\t\tlet payment: PaymentSummary | null = null\n\t\ttry {\n\t\t\tconst json = (await res.json()) as { payment?: unknown }\n\t\t\tpayment = parsePaymentSummary(json.payment)\n\t\t} catch {\n\t\t\t// Older server or non-JSON body: degrade to neutral thanks screen.\n\t\t}\n\t\treturn { ok: true, payment }\n\t} catch {\n\t\treturn { ok: false, payment: null }\n\t}\n}\n\n// POST the participant's payout destination to the SaaS side. Best-effort with a\n// single retry; the destination defaults server-side to the testerEmail when we\n// send only `method`, so a dropped call still leaves a payable session. Returns\n// ok so the UI can confirm or surface a soft error.\nasync function postPayout(\n\tapiUrl: string,\n\tsessionId: string,\n\tdestination: string | null,\n\tlogger: PluginContext['logger'],\n): Promise<boolean> {\n\tconst url = `${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/payout`\n\tconst body: Record<string, unknown> = { method: 'email' }\n\tif (destination) body.destination = destination\n\tfor (let attempt = 0; attempt < 2; attempt += 1) {\n\t\ttry {\n\t\t\tconst res = await fetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tkeepalive: true,\n\t\t\t})\n\t\t\tif (res.ok) return true\n\t\t\t// 4xx won't improve on retry (bad email, etc.).\n\t\t\tif (res.status >= 400 && res.status < 500) {\n\t\t\t\tlogger.warn(`payout rejected with ${res.status}`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tlogger.warn(`payout attempt ${attempt + 1} failed`, err)\n\t\t}\n\t\tawait new Promise(resolve => setTimeout(resolve, 400 + Math.floor(Math.random() * 200)))\n\t}\n\treturn false\n}\n\ninterface PostNoteResult {\n\tok: boolean\n\tid?: string\n\ttransient: boolean // true on network error / 5xx — eligible for retry\n}\n\nasync function postNoteOnce(\n\tapiUrl: string,\n\tsessionId: string,\n\tatMs: number,\n\ttext: string,\n\tlogger: PluginContext['logger'],\n): Promise<PostNoteResult> {\n\ttry {\n\t\tconst res = await fetch(`${apiUrl.replace(/\\/$/, '')}/api/user-test-sessions/${encodeURIComponent(sessionId)}/notes`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\tbody: JSON.stringify({ atMs: Math.max(0, Math.round(atMs)), text }),\n\t\t\tkeepalive: true,\n\t\t})\n\t\tif (!res.ok) {\n\t\t\tlogger.warn(`note POST rejected with ${res.status}`)\n\t\t\treturn { ok: false, transient: res.status >= 500 || res.status === 408 || res.status === 429 }\n\t\t}\n\t\t// Best-effort id extraction; failures here don't matter for ack.\n\t\tlet id: string | undefined\n\t\ttry {\n\t\t\tconst json = (await res.json()) as { id?: unknown }\n\t\t\tif (typeof json.id === 'string') id = json.id\n\t\t} catch { /* ignore */ }\n\t\treturn { ok: true, id, transient: false }\n\t} catch (err) {\n\t\tlogger.warn('note POST failed', err)\n\t\treturn { ok: false, transient: true }\n\t}\n}\n\n// One immediate retry on transient errors. If still failing, defer to\n// finalise batching via the un-acked notes channel.\nasync function postNoteWithRetry(\n\tapiUrl: string,\n\tsessionId: string,\n\tatMs: number,\n\ttext: string,\n\tlogger: PluginContext['logger'],\n): Promise<PostNoteResult> {\n\tconst first = await postNoteOnce(apiUrl, sessionId, atMs, text, logger)\n\tif (first.ok || !first.transient) return first\n\tawait new Promise(resolve => setTimeout(resolve, 400 + Math.floor(Math.random() * 200)))\n\treturn postNoteOnce(apiUrl, sessionId, atMs, text, logger)\n}\n\n\nasync function flushPendingFromIdb(store: RecorderStore, ctx: PluginContext): Promise<void> {\n\tif (!store.sessionId) return\n\tconst pending = await idbListChunks(store.sessionId)\n\tfor (const chunk of pending) {\n\t\tconst ok = await uploadChunkWithRetry(chunk.apiUrl, chunk.sessionId, chunk.chunkIndex, chunk.blob, ctx.logger, 3)\n\t\tif (ok) await idbDeleteChunk(chunk.id)\n\t}\n}\n\nfunction enqueueChunk(store: RecorderStore, ctx: PluginContext, blob: Blob): void {\n\tif (store.cancelled || !store.sessionId || blob.size === 0) return\n\tconst index = store.chunkIndex\n\tstore.chunkIndex += 1\n\tstore.pendingUploads += 1\n\tconst sessionId = store.sessionId\n\tconst apiUrl = store.options.apiUrl\n\n\tstore.uploadQueue = store.uploadQueue.then(async () => {\n\t\tconst ok = await uploadChunkWithRetry(apiUrl, sessionId, index, blob, ctx.logger)\n\t\tif (!ok) {\n\t\t\tctx.logger.warn(`chunk ${index} stashed for offline retry`)\n\t\t\tawait idbStashChunk({\n\t\t\t\tid: `${sessionId}:${index}:${Date.now()}`,\n\t\t\t\tsessionId,\n\t\t\t\tapiUrl,\n\t\t\t\tchunkIndex: index,\n\t\t\t\tblob,\n\t\t\t\tcreatedAt: Date.now(),\n\t\t\t})\n\t\t}\n\t\tstore.pendingUploads -= 1\n\t})\n}\n\n// ---------------------------------------------------------------------------\n// Silent-microphone guard\n//\n// A dead mic, or a virtual audio input device that macOS hands Chrome (e.g.\n// \"Background Music\", a Zoom/Teams virtual mic), delivers digital silence.\n// getUserMedia succeeds, MediaRecorder records, and 15 minutes of nothing\n// reaches the researcher with no warning. We DETECT a silent input stream and\n// WARN the participant (non-blocking: recording always continues).\n//\n// Detection runs a Web Audio AnalyserNode over the live track and computes RMS\n// in dBFS over a short window. The decision is a pure function so it can be\n// unit-tested without a real AudioContext.\n\n// Threshold rationale (dBFS, full-scale = 0):\n// - True failure is essentially digital silence: every sample ~0, so RMS is\n// -Infinity (or, with analyser float error, well below -80 dB).\n// - Confirmed-real speech in our captured data sits around -36 dB RMS.\n// - Quiet-but-present speech (a soft talker) sits around -40 to -50 dB.\n// We set the bar at -60 dB: only treat the stream as silent when RMS is\n// effectively zero. A -50 dB quiet voice is a full 10 dB ABOVE the line and\n// will never trip it, so we never falsely stop a real (quiet) participant.\n// This is deliberately conservative per the product decision: warn, never\n// block, and never false-positive on a real voice.\nconst SILENCE_RMS_DB_THRESHOLD = -60\n\n// dBFS for a fully-silent (all-zero) window is -Infinity. Floor it to a finite\n// value so the pure decision function stays total and testable.\nconst SILENCE_FLOOR_DB = -100\n\n// How long the analyser must read continuous silence before we surface the\n// warning. ~1.8s at record start and as the sustained-silence window during\n// recording. Long enough that a natural pause between sentences (which dips\n// toward the floor for a fraction of a second) never trips it; short enough\n// that a dead device is flagged almost immediately.\nconst SILENCE_SUSTAINED_MS = 1800\n\n// How often the monitor samples the analyser.\nconst SILENCE_POLL_MS = 250\n\n// Compute RMS in dBFS from normalized float time-domain samples (each in\n// [-1, 1], as produced by AnalyserNode.getFloatTimeDomainData). Returns a\n// finite dB value floored at SILENCE_FLOOR_DB so an all-zero window doesn't\n// yield -Infinity. Pure, no Web Audio needed: unit-tested directly.\nexport function rmsDbFromSamples(samples: Float32Array | number[]): number {\n\tconst n = samples.length\n\tif (n === 0) return SILENCE_FLOOR_DB\n\tlet sumSquares = 0\n\tfor (let i = 0; i < n; i += 1) {\n\t\tconst s = samples[i] ?? 0\n\t\tsumSquares += s * s\n\t}\n\tconst rms = Math.sqrt(sumSquares / n)\n\tif (rms <= 0) return SILENCE_FLOOR_DB\n\tconst db = 20 * Math.log10(rms)\n\treturn db < SILENCE_FLOOR_DB ? SILENCE_FLOOR_DB : db\n}\n\n// Pure silence decision. Accepts EITHER an already-computed RMS dB value (a\n// number) OR a sample window (array). True only when the level is at/below the\n// conservative silence threshold. A real voice, even a quiet one (-40 to\n// -50 dB), is comfortably above the line and returns false.\nexport function isStreamSilent(input: number | Float32Array | number[]): boolean {\n\tconst rmsDb = typeof input === 'number' ? input : rmsDbFromSamples(input)\n\treturn rmsDb <= SILENCE_RMS_DB_THRESHOLD\n}\n\n// Live monitor: wires an AnalyserNode onto the stream and polls it. Calls\n// `onChange(silent)` only on transitions (silent <-> audible), debounced by\n// SILENCE_SUSTAINED_MS so a brief between-words dip never flips the pill.\n// Returns a teardown that closes the AudioContext and disconnects nodes.\ninterface SilenceMonitor {\n\tstop(): void\n}\n\nfunction startSilenceMonitor(stream: MediaStream, onChange: (silent: boolean) => void, logger: PluginContext['logger']): SilenceMonitor | null {\n\tconst Ctor: typeof AudioContext | undefined =\n\t\ttypeof window !== 'undefined'\n\t\t\t? (window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext)\n\t\t\t: undefined\n\tif (!Ctor) return null\n\n\tlet audioCtx: AudioContext\n\tlet source: MediaStreamAudioSourceNode\n\tlet analyser: AnalyserNode\n\ttry {\n\t\taudioCtx = new Ctor()\n\t\tsource = audioCtx.createMediaStreamSource(stream)\n\t\tanalyser = audioCtx.createAnalyser()\n\t\tanalyser.fftSize = 2048\n\t\t// We do not connect the analyser to audioCtx.destination: we only READ\n\t\t// the track, never play it back (that would echo the participant's own\n\t\t// mic into their speakers).\n\t\tsource.connect(analyser)\n\t} catch (err) {\n\t\tlogger.warn('silence monitor: failed to attach analyser', err)\n\t\treturn null\n\t}\n\n\tconst buffer = new Float32Array(analyser.fftSize)\n\t// Reported state (what the pill currently shows). Starts audible; we only\n\t// flip to silent after SILENCE_SUSTAINED_MS of continuous silence.\n\tlet reportedSilent = false\n\t// Timestamp the CURRENT run of same-classification readings began.\n\tlet runStartedAt = Date.now()\n\tlet lastRaw = false\n\tlet intervalId: ReturnType<typeof setInterval> | null = null\n\n\tconst tick = (): void => {\n\t\t// getFloatTimeDomainData is widely supported; guard for older engines.\n\t\ttry {\n\t\t\tanalyser.getFloatTimeDomainData(buffer)\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tconst rawSilent = isStreamSilent(buffer)\n\t\tconst now = Date.now()\n\t\tif (rawSilent !== lastRaw) {\n\t\t\tlastRaw = rawSilent\n\t\t\trunStartedAt = now\n\t\t}\n\t\t// Only commit a state change once the raw classification has held for\n\t\t// the sustained window. Going audible clears the warning immediately\n\t\t// once sustained, going silent raises it once sustained.\n\t\tif (rawSilent !== reportedSilent && now - runStartedAt >= SILENCE_SUSTAINED_MS) {\n\t\t\treportedSilent = rawSilent\n\t\t\tonChange(reportedSilent)\n\t\t}\n\t}\n\n\tintervalId = setInterval(tick, SILENCE_POLL_MS)\n\n\treturn {\n\t\tstop(): void {\n\t\t\tif (intervalId !== null) {\n\t\t\t\tclearInterval(intervalId)\n\t\t\t\tintervalId = null\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tsource.disconnect()\n\t\t\t\tanalyser.disconnect()\n\t\t\t} catch {\n\t\t\t\t// nodes may already be torn down\n\t\t\t}\n\t\t\t// close() returns a promise; failures here are harmless (context may\n\t\t\t// already be closing on page unload).\n\t\t\ttry {\n\t\t\t\tvoid audioCtx.close()\n\t\t\t} catch {\n\t\t\t\t// ignore\n\t\t\t}\n\t\t},\n\t}\n}\n\nasync function startRecording(store: RecorderStore, ctx: PluginContext): Promise<void> {\n\t// Re-entrant: the failed chip re-invokes this to retry. Reset to the\n\t// pending state so the chip shows \"connecting\" again during the attempt.\n\tstore.micAcquiring = true\n\tstore.micFailReason = null\n\t// A retry tears down a prior monitor and clears the silent flag so the\n\t// fresh attempt starts from a clean state.\n\tif (store.silenceMonitor) {\n\t\tstore.silenceMonitor.stop()\n\t\tstore.silenceMonitor = null\n\t}\n\tstore.micSilent = false\n\trenderIndicatorState(store)\n\tif (!isMediaRecorderSupported()) {\n\t\tctx.logger.warn('MediaRecorder not supported, continuing without audio')\n\t\tstore.micAcquiring = false\n\t\tstore.micFailReason = 'unsupported'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tlet stream: MediaStream\n\ttry {\n\t\tstream = await navigator.mediaDevices.getUserMedia({ audio: true })\n\t} catch (err) {\n\t\tctx.logger.warn('mic permission denied or unavailable', err)\n\t\tstore.micAcquiring = false\n\t\t// Distinguish denied (blocked) from no-device (not-found) for copy.\n\t\tconst name = err instanceof Error ? err.name : ''\n\t\tstore.micFailReason = name === 'NotFoundError' || name === 'DevicesNotFoundError' ? 'not-found' : 'blocked'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tstore.stream = stream\n\tstore.hasMicPermission = true\n\tstore.micAcquiring = false\n\tstore.micFailReason = null\n\tconst mimeType = pickMimeType()\n\tlet recorder: MediaRecorder\n\ttry {\n\t\trecorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream)\n\t} catch (err) {\n\t\tctx.logger.error('MediaRecorder construction failed', err)\n\t\tstream.getTracks().forEach(t => t.stop())\n\t\tstore.stream = null\n\t\tstore.hasMicPermission = false\n\t\tstore.micAcquiring = false\n\t\tstore.micFailReason = 'unsupported'\n\t\tstore.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tstore.recorder = recorder\n\trecorder.addEventListener('dataavailable', event => {\n\t\tif (event.data && event.data.size > 0) {\n\t\t\tenqueueChunk(store, ctx, event.data)\n\t\t}\n\t})\n\trecorder.addEventListener('error', event => {\n\t\tctx.logger.error('MediaRecorder error', event)\n\t})\n\t// `timeslice` makes the recorder emit a self-contained chunk every N ms.\n\trecorder.start(store.options.chunkSeconds * 1000)\n\t// On a successful (re)acquire, restore the live recording indicator. A\n\t// prior failed attempt left indicatorState at 'no-audio' (steady amber\n\t// dot); now that audio is live the dot should pulse red again.\n\tif (store.indicatorState === 'no-audio') {\n\t\tstore.indicatorState = 'recording'\n\t}\n\trenderIndicatorState(store)\n\n\t// Start the silent-mic guard over the live track. Detects a dead or virtual\n\t// silent input at record start and keeps checking for a mid-session mic\n\t// death. Warning only; recording is never gated on it. When the participant\n\t// has muted themselves the track is intentionally silent, so we suppress the\n\t// warning in that case (see the onChange guard).\n\tconst monitor = startSilenceMonitor(\n\t\tstream,\n\t\tsilent => {\n\t\t\t// Ignore the analyser while the participant has deliberately muted:\n\t\t\t// a muted track reads as silence by design, that's not a fault.\n\t\t\tconst effectiveSilent = silent && !store.muted\n\t\t\tif (store.micSilent === effectiveSilent) return\n\t\t\tstore.micSilent = effectiveSilent\n\t\t\trenderIndicatorState(store)\n\t\t},\n\t\tctx.logger,\n\t)\n\tstore.silenceMonitor = monitor\n}\n\nfunction toggleMute(store: RecorderStore): boolean {\n\tif (!store.stream || !store.hasMicPermission) return false\n\tconst tracks = store.stream.getAudioTracks()\n\tif (tracks.length === 0) return false\n\tconst nowMs = Date.now() - store.startedAt\n\tif (!store.muted) {\n\t\t// Going muted: disable each audio track. MediaRecorder keeps running;\n\t\t// the disabled track produces silence in the resulting WebM. We do NOT\n\t\t// pause the recorder so the single-stream lifecycle stays simple.\n\t\tfor (const t of tracks) t.enabled = false\n\t\tstore.muted = true\n\t\tstore.mutedSinceMs = nowMs\n\t} else {\n\t\t// Coming back: close the muted segment, re-enable.\n\t\tconst startMs = store.mutedSinceMs ?? nowMs\n\t\tif (nowMs > startMs) {\n\t\t\tstore.mutedSegments.push({ startMs, endMs: nowMs })\n\t\t}\n\t\tstore.mutedSinceMs = null\n\t\tstore.muted = false\n\t\tfor (const t of tracks) t.enabled = true\n\t}\n\treturn true\n}\n\nfunction flushMuteIfActive(store: RecorderStore): void {\n\tif (!store.muted || store.mutedSinceMs === null) return\n\tconst nowMs = Date.now() - store.startedAt\n\tif (nowMs > store.mutedSinceMs) {\n\t\tstore.mutedSegments.push({ startMs: store.mutedSinceMs, endMs: nowMs })\n\t}\n\tstore.mutedSinceMs = null\n}\n\nfunction stopRecording(store: RecorderStore): void {\n\tif (store.silenceMonitor) {\n\t\tstore.silenceMonitor.stop()\n\t\tstore.silenceMonitor = null\n\t}\n\tstore.micSilent = false\n\tconst recorder = store.recorder\n\tif (recorder && recorder.state !== 'inactive') {\n\t\ttry {\n\t\t\trecorder.requestData()\n\t\t} catch {\n\t\t\t// requestData throws if state is invalid; ignore.\n\t\t}\n\t\ttry {\n\t\t\trecorder.stop()\n\t\t} catch {\n\t\t\t// already stopped\n\t\t}\n\t}\n\tstore.recorder = null\n\tif (store.stream) {\n\t\tstore.stream.getTracks().forEach(t => t.stop())\n\t\tstore.stream = null\n\t}\n}\n\nasync function finishFlow(store: RecorderStore, ctx: PluginContext, opts: { showThanks: boolean }): Promise<void> {\n\tif (store.cancelled) return\n\t// Short-circuit re-entry. The pagehide handler and the manual Finish click\n\t// can race; server is also idempotent on a second finalise call, but doing\n\t// the local work twice (flushing mute, draining queues, etc.) is wasted.\n\tif (store.finishFlowRan) return\n\tif (store.indicatorState === 'finishing' || store.indicatorState === 'done') return\n\tstore.finishFlowRan = true\n\tstore.indicatorState = 'finishing'\n\tflushMuteIfActive(store)\n\trenderIndicatorState(store)\n\n\tstopRecording(store)\n\t// Wait for the queued uploads to drain. Each upload already has its own\n\t// retry/backoff; this just lets them finish before finalise fires.\n\tawait store.uploadQueue\n\tawait flushPendingFromIdb(store, ctx)\n\n\tconst durationSeconds = (Date.now() - store.startedAt) / 1000\n\t// Replay linkage, computed once and sent on every finalise call for this\n\t// session. sdkSessionId is the core-owned per-tab id (the primary key the\n\t// server uses to resolve the SessionReplay); replayOffsetMs is the offset\n\t// captured at session start, only set when replay was active. Both degrade\n\t// gracefully to absent. Sending it on the second (end-note) finalise too\n\t// is harmless: the server stores idempotently.\n\tconst replayLinkage: { sdkSessionId?: string; replayOffsetMs?: number } = {}\n\tconst linkageSdkSessionId = ctx.getSdkSessionId ? ctx.getSdkSessionId() : undefined\n\tif (linkageSdkSessionId) replayLinkage.sdkSessionId = linkageSdkSessionId\n\tif (store.replayOffsetAtStartMs !== null) {\n\t\treplayLinkage.replayOffsetMs = store.replayOffsetAtStartMs\n\t}\n\t// Payment summary from the first finalise response drives the finished screen\n\t// (complete vs ended-early, reward headline, one-tap payout default).\n\tlet payment: PaymentSummary | null = null\n\tif (store.sessionId) {\n\t\t// First finalise carries durationSeconds + mutedSegments + any un-acked\n\t\t// notes (recovery channel). End-of-test note is sent via a second\n\t\t// finalise call from the thanks screen.\n\t\tconst unackedNotes = store.notes.filter(n => !n.acked).map(n => ({ atMs: n.atMs, text: n.text }))\n\t\tconst result = await finaliseSession(store.options.apiUrl, store.sessionId, durationSeconds, {\n\t\t\tmutedSegments: store.mutedSegments,\n\t\t\tnotes: unackedNotes,\n\t\t\t...replayLinkage,\n\t\t})\n\t\tif (result.ok) {\n\t\t\tpayment = result.payment\n\t\t\t// Mark the un-acked notes we just shipped as acked so the second\n\t\t\t// finalise call doesn't resend them.\n\t\t\tfor (const n of store.notes) {\n\t\t\t\tif (!n.acked) n.acked = true\n\t\t\t}\n\t\t}\n\t\tstore.indicatorState = result.ok ? 'done' : 'error'\n\t} else {\n\t\tstore.indicatorState = 'error'\n\t}\n\trenderIndicatorState(store)\n\n\tif (opts.showThanks && store.indicatorRoot && store.indicatorState === 'done') {\n\t\tshowThanksScreen(store.indicatorRoot, {\n\t\t\tpayment,\n\t\t\tonPayout: async destination => {\n\t\t\t\tif (!store.sessionId) return false\n\t\t\t\treturn postPayout(store.options.apiUrl, store.sessionId, destination, ctx.logger)\n\t\t\t},\n\t\t\tonResume: () => {\n\t\t\t\t// Re-arm an ended-early session: the recording was already stopped +\n\t\t\t\t// finalised, so resuming starts a fresh recording leg under the same\n\t\t\t\t// sessionId. The server is idempotent on a later finalise; the new\n\t\t\t\t// audio chunks continue the same R2 prefix. Reset the finish guard\n\t\t\t\t// and timeline anchor so the next Finish re-evaluates completion.\n\t\t\t\tstore.finishFlowRan = false\n\t\t\t\tstore.indicatorState = 'recording'\n\t\t\t\tstore.startedAt = Date.now()\n\t\t\t\tstore.muted = false\n\t\t\t\tstore.mutedSinceMs = null\n\t\t\t\trenderIndicatorState(store)\n\t\t\t\tvoid startRecording(store, ctx)\n\t\t\t},\n\t\t\tonSubmitNote: async text => {\n\t\t\t\tif (!store.sessionId) return\n\t\t\t\tstore.endNote = text\n\t\t\t\t// Second finalise only carries the late-binding fields. mutedSegments\n\t\t\t\t// already landed on call 1, server stores idempotently, no need to\n\t\t\t\t// resend. Include any notes that arrived (or failed to ack) between\n\t\t\t\t// the two calls.\n\t\t\t\tconst stillUnacked = store.notes.filter(n => !n.acked).map(n => ({ atMs: n.atMs, text: n.text }))\n\t\t\t\tconst result = await finaliseSession(store.options.apiUrl, store.sessionId, durationSeconds, {\n\t\t\t\t\tendNote: text,\n\t\t\t\t\tnotes: stillUnacked,\n\t\t\t\t\t...replayLinkage,\n\t\t\t\t})\n\t\t\t\tif (!result.ok) throw new Error('finalise failed')\n\t\t\t\tfor (const n of store.notes) {\n\t\t\t\t\tif (!n.acked) n.acked = true\n\t\t\t\t}\n\t\t\t},\n\t\t\tonSkip: () => { /* nothing to send */ },\n\t\t})\n\t}\n}\n\nexport function userTest(options: UserTestOptions = {}): UseroPlugin {\n\tconst merged: Required<UserTestOptions> = {\n\t\tqueryParam: options.queryParam ?? DEFAULT_OPTIONS.queryParam,\n\t\tchunkSeconds: options.chunkSeconds ?? DEFAULT_OPTIONS.chunkSeconds,\n\t\tapiUrl: options.apiUrl ?? DEFAULT_OPTIONS.apiUrl,\n\t\ttesterName: options.testerName ?? DEFAULT_OPTIONS.testerName,\n\t\thideIndicator: options.hideIndicator ?? DEFAULT_OPTIONS.hideIndicator,\n\t}\n\n\treturn {\n\t\tname: 'user-test',\n\t\tonInit(ctx) {\n\t\t\tif (typeof window === 'undefined' || typeof document === 'undefined') return\n\t\t\tconst slug = getTestSlug(merged.queryParam)\n\t\t\tif (!slug) return\n\n\t\t\tconst apiUrl = merged.apiUrl || ctx.baseUrl || DEFAULT_API_URL\n\t\t\tconst store: RecorderStore = {\n\t\t\t\tcancelled: false,\n\t\t\t\tslug,\n\t\t\t\tsessionId: null,\n\t\t\t\tclientId: null,\n\t\t\t\trecorder: null,\n\t\t\t\tstream: null,\n\t\t\t\tchunkIndex: 0,\n\t\t\t\tuploadQueue: Promise.resolve(),\n\t\t\t\tpendingUploads: 0,\n\t\t\t\tstartedAt: Date.now(),\n\t\t\t\tindicator: null,\n\t\t\t\tindicatorRoot: null,\n\t\t\t\tindicatorState: 'recording',\n\t\t\t\tpageHideHandler: null,\n\t\t\t\tvisibilityHandler: null,\n\t\t\t\toptions: { ...merged, apiUrl },\n\t\t\t\ttasks: [],\n\t\t\t\ttasksPanelOpen: readTasksPanelOpen(),\n\t\t\t\toutsidePointerHandler: null,\n\t\t\t\tkeydownHandler: null,\n\t\t\t\thasMicPermission: false,\n\t\t\t\tmicAcquiring: true,\n\t\t\t\tmicFailReason: null,\n\t\t\t\tmuted: false,\n\t\t\t\tmutedSinceMs: null,\n\t\t\t\tmutedSegments: [],\n\t\t\t\tmicSilent: false,\n\t\t\t\tsilenceMonitor: null,\n\t\t\t\tmuteToastShown: false,\n\t\t\t\tmuteToastTimers: [],\n\t\t\t\tnotes: [],\n\t\t\t\tnotesPopoverOpen: false,\n\t\t\t\tnotePopoverAtMs: null,\n\t\t\t\tendNote: '',\n\t\t\t\tfinishFlowRan: false,\n\t\t\t\treplayOffsetAtStartMs: null,\n\t\t\t}\n\t\t\tctx.setStore(store)\n\n\t\t\tconst onFinish = (): void => {\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: true })\n\t\t\t}\n\n\t\t\tconst setPanelOpen = (open: boolean): void => {\n\t\t\t\tif (store.tasksPanelOpen === open) return\n\t\t\t\tstore.tasksPanelOpen = open\n\t\t\t\twriteTasksPanelOpen(open)\n\t\t\t\trenderTasksPanel(store)\n\t\t\t}\n\n\t\t\tconst onToggleTasks = (): void => setPanelOpen(!store.tasksPanelOpen)\n\n\t\t\tconst onToggleMute = (): void => {\n\t\t\t\tif (!store.hasMicPermission) {\n\t\t\t\t\t// In the failed terminal state the chip is a retry button:\n\t\t\t\t\t// re-attempt mic acquisition. Ignore taps while still\n\t\t\t\t\t// acquiring (connecting state is unfocusable anyway).\n\t\t\t\t\tif (!store.micAcquiring && store.indicatorState !== 'finishing' && store.indicatorState !== 'done' && store.indicatorState !== 'error') {\n\t\t\t\t\t\tvoid startRecording(store, ctx)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Silent-mic warning is also a retry affordance: the participant\n\t\t\t\t// has likely switched their input device, so re-acquire the mic\n\t\t\t\t// rather than toggling mute. startRecording tears down the old\n\t\t\t\t// stream + monitor and re-runs detection on the fresh track.\n\t\t\t\tif (store.micSilent && !store.micAcquiring && store.indicatorState !== 'finishing' && store.indicatorState !== 'done' && store.indicatorState !== 'error') {\n\t\t\t\t\tvoid startRecording(store, ctx)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst ok = toggleMute(store)\n\t\t\t\tif (!ok) return\n\t\t\t\tif (store.muted) {\n\t\t\t\t\t// Muting is intentional silence: drop any active silent-mic\n\t\t\t\t\t// warning so the two states don't fight. The monitor's\n\t\t\t\t\t// onChange suppresses re-raising it while muted.\n\t\t\t\t\tstore.micSilent = false\n\t\t\t\t\tshowMuteToast(store)\n\t\t\t\t}\n\t\t\t\trenderIndicatorState(store)\n\t\t\t}\n\n\t\t\tconst closeNote = (): void => closeNotePopover(store)\n\t\t\tconst onOpenNote = (): void => {\n\t\t\t\tif (store.notesPopoverOpen) { closeNote(); return }\n\t\t\t\topenNotePopover(\n\t\t\t\t\tstore,\n\t\t\t\t\ttext => {\n\t\t\t\t\t\tconst atMs = store.notePopoverAtMs ?? Math.max(0, Date.now() - store.startedAt)\n\t\t\t\t\t\tconst note: InFlightNote = { atMs, text, acked: false }\n\t\t\t\t\t\tstore.notes.push(note)\n\t\t\t\t\t\tcloseNote()\n\t\t\t\t\t\trenderNotesCount(store)\n\t\t\t\t\t\t// UI never blocks on the POST. On success we mark the note\n\t\t\t\t\t\t// acked; on failure (after one retry) it stays unacked and\n\t\t\t\t\t\t// gets included in the finalise notes batch as a recovery\n\t\t\t\t\t\t// channel. Server dedupes by (sessionId, atMs, text).\n\t\t\t\t\t\tif (store.sessionId) {\n\t\t\t\t\t\t\tconst sessionId = store.sessionId\n\t\t\t\t\t\t\tvoid (async (): Promise<void> => {\n\t\t\t\t\t\t\t\tconst result = await postNoteWithRetry(store.options.apiUrl, sessionId, atMs, text, ctx.logger)\n\t\t\t\t\t\t\t\tif (result.ok) {\n\t\t\t\t\t\t\t\t\tnote.acked = true\n\t\t\t\t\t\t\t\t\tif (result.id) note.serverId = result.id\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t() => closeNote(),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tif (!merged.hideIndicator) {\n\t\t\t\tconst host = document.createElement('div')\n\t\t\t\thost.setAttribute('data-usero-user-test', 'true')\n\t\t\t\tdocument.body.appendChild(host)\n\t\t\t\tstore.indicator = host\n\t\t\t\tstore.indicatorRoot = buildIndicator(host, store, {\n\t\t\t\t\tonFinish,\n\t\t\t\t\tonToggleTasks,\n\t\t\t\t\tonToggleMute,\n\t\t\t\t\tonOpenNote,\n\t\t\t\t})\n\t\t\t\trenderIndicatorState(store)\n\t\t\t\trenderNotesCount(store)\n\t\t\t}\n\n\t\t\t// Outside-click + Escape close the tasks panel. Listen on document\n\t\t\t// (composedPath checks shadow ancestry so taps on the panel/pill\n\t\t\t// itself don't dismiss).\n\t\t\tconst outsidePointer = (event: PointerEvent): void => {\n\t\t\t\tconst host = store.indicator\n\t\t\t\tif (!host) return\n\t\t\t\tconst path = event.composedPath()\n\t\t\t\tif (path.includes(host)) return\n\t\t\t\tif (store.tasksPanelOpen) setPanelOpen(false)\n\t\t\t\tif (store.notesPopoverOpen) closeNote()\n\t\t\t}\n\t\t\tconst onKeydown = (event: KeyboardEvent): void => {\n\t\t\t\tif (event.key !== 'Escape') return\n\t\t\t\tif (store.tasksPanelOpen) setPanelOpen(false)\n\t\t\t\tif (store.notesPopoverOpen) closeNote()\n\t\t\t}\n\t\t\tstore.outsidePointerHandler = outsidePointer\n\t\t\tstore.keydownHandler = onKeydown\n\t\t\tdocument.addEventListener('pointerdown', outsidePointer, true)\n\t\t\tdocument.addEventListener('keydown', onKeydown)\n\n\t\t\tconst pageHide = (): void => {\n\t\t\t\t// Best-effort flush + finalise. We don't await here; the browser\n\t\t\t\t// is shutting the page down. `keepalive: true` on finalise lets\n\t\t\t\t// the request race the unload.\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: false })\n\t\t\t}\n\t\t\tstore.pageHideHandler = pageHide\n\t\t\twindow.addEventListener('pagehide', pageHide)\n\n\t\t\t// visibilitychange -> hidden is the reliable mobile unload backstop:\n\t\t\t// iOS frequently kills a backgrounded tab WITHOUT ever firing\n\t\t\t// pagehide, leaving the session stuck un-finalised. visibilitychange\n\t\t\t// fires far more consistently when the tab is backgrounded. It runs\n\t\t\t// the SAME finishFlow path as pagehide; finishFlow is idempotent (the\n\t\t\t// `finishFlowRan` + indicatorState short-circuit at its top), so the\n\t\t\t// manual Finish click, pagehide, and this handler can fire in any\n\t\t\t// order or concurrently and only the first does the work. Like\n\t\t\t// pagehide we don't await; finalise rides on `keepalive: true`.\n\t\t\tconst onVisibilityChange = (): void => {\n\t\t\t\tif (document.visibilityState !== 'hidden') return\n\t\t\t\tvoid finishFlow(store, ctx, { showThanks: false })\n\t\t\t}\n\t\t\tstore.visibilityHandler = onVisibilityChange\n\t\t\tdocument.addEventListener('visibilitychange', onVisibilityChange)\n\n\t\t\tvoid (async (): Promise<void> => {\n\t\t\t\t// If the entry screen created the session and passed `uts`, ADOPT\n\t\t\t\t// it (the participant's email is already attached server-side).\n\t\t\t\t// Otherwise fall back to creating one (open tests / old links).\n\t\t\t\tconst adoptId = getAdoptSessionId()\n\t\t\t\tconst created = adoptId\n\t\t\t\t\t? await adoptSession(apiUrl, adoptId)\n\t\t\t\t\t: await createSession(apiUrl, slug, readTesterName(merged.testerName))\n\t\t\t\tif (store.cancelled) return\n\t\t\t\tif (!created) {\n\t\t\t\t\tctx.logger.error(adoptId ? 'failed to adopt user-test session' : 'failed to create user-test session')\n\t\t\t\t\tstore.indicatorState = 'error'\n\t\t\t\t\trenderIndicatorState(store)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tstore.sessionId = created.sessionId\n\t\t\t\tstore.clientId = created.clientId\n\t\t\t\t// Capture the replay offset HERE at session start (not at\n\t\t\t\t// finalise) so it reflects when the test began relative to the\n\t\t\t\t// recording. The replay plugin publishes its start epoch into\n\t\t\t\t// the core; we read it via the context. If replay is not active\n\t\t\t\t// (plugin not loaded, sampled out, or an older host without the\n\t\t\t\t// accessor) we leave it null and the finalise body omits\n\t\t\t\t// replayOffsetMs. Anchored to store.startedAt (test start),\n\t\t\t\t// clamped >= 0 in case the test starts a hair before the replay\n\t\t\t\t// epoch is published.\n\t\t\t\tconst replayStartMs = ctx.getReplayStartMs ? ctx.getReplayStartMs() : null\n\t\t\t\tstore.replayOffsetAtStartMs =\n\t\t\t\t\treplayStartMs === null ? null : Math.max(0, store.startedAt - replayStartMs)\n\t\t\t\tstore.tasks = created.tasks\n\t\t\t\tif (store.tasks.length > 0 && store.indicatorRoot && !merged.hideIndicator) {\n\t\t\t\t\tconst bar = store.indicatorRoot.querySelector('.bar')\n\t\t\t\t\tconst finishBtn = bar?.querySelector('.finish-btn')\n\t\t\t\t\tif (bar instanceof HTMLElement && finishBtn instanceof HTMLElement && !bar.querySelector('.tasks-btn')) {\n\t\t\t\t\t\tinstallTasksToggle(bar, finishBtn, store, onToggleTasks)\n\t\t\t\t\t}\n\t\t\t\t\trenderTasksPanel(store)\n\t\t\t\t}\n\t\t\t\tawait startRecording(store, ctx)\n\t\t\t\trenderIndicatorState(store)\n\t\t\t})()\n\t\t},\n\t\tonDestroy(ctx) {\n\t\t\tconst store = ctx.getStore<RecorderStore>()\n\t\t\tif (!store) return\n\t\t\tstore.cancelled = true\n\t\t\tif (store.pageHideHandler) {\n\t\t\t\twindow.removeEventListener('pagehide', store.pageHideHandler)\n\t\t\t\tstore.pageHideHandler = null\n\t\t\t}\n\t\t\tif (store.visibilityHandler) {\n\t\t\t\tdocument.removeEventListener('visibilitychange', store.visibilityHandler)\n\t\t\t\tstore.visibilityHandler = null\n\t\t\t}\n\t\t\tstopRecording(store)\n\t\t\tif (store.outsidePointerHandler) {\n\t\t\t\tdocument.removeEventListener('pointerdown', store.outsidePointerHandler, true)\n\t\t\t\tstore.outsidePointerHandler = null\n\t\t\t}\n\t\t\tif (store.keydownHandler) {\n\t\t\t\tdocument.removeEventListener('keydown', store.keydownHandler)\n\t\t\t\tstore.keydownHandler = null\n\t\t\t}\n\t\t\tfor (const id of store.muteToastTimers) {\n\t\t\t\ttry { window.clearTimeout(id) } catch { /* ignore */ }\n\t\t\t}\n\t\t\tstore.muteToastTimers = []\n\t\t\tif (store.indicator && store.indicator.parentNode) {\n\t\t\t\tstore.indicator.parentNode.removeChild(store.indicator)\n\t\t\t}\n\t\t\tstore.indicator = null\n\t\t\tstore.indicatorRoot = null\n\t\t},\n\t}\n}\n\n// Internal helpers exposed for tests only. Not part of the public API.\nexport const __test__ = {\n\tgetTestSlug,\n\tpickMimeType,\n\tisMediaRecorderSupported,\n\tmicChipState,\n\tisStreamSilent,\n\trmsDbFromSamples,\n\tSILENCE_RMS_DB_THRESHOLD,\n\tSILENCE_FLOOR_DB,\n}\n"]}