@usero/sdk 1.1.6 → 1.1.7

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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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;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.cjs","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`), flushes any buffered chunks and calls\n// 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 30.\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\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\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\tchunkSeconds: 30,\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.mic[data-mic-state=\"none\"] {\n\t\t\tbackground: rgba(255,255,255,0.04);\n\t\t\tcolor: rgba(255,255,255,0.55);\n\t\t\tcursor: default;\n\t\t}\n\t\t.mic[data-mic-state=\"none\"]:hover { background: rgba(255,255,255,0.04); }\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' | 'inactive' {\n\tif (store.indicatorState === 'finishing' || store.indicatorState === 'done' || store.indicatorState === 'error') {\n\t\treturn 'inactive'\n\t}\n\tif (!store.hasMicPermission) return 'none'\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\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 'none':\n\t\t\tmicIcon.innerHTML = MIC_MUTED_ICON_SVG\n\t\t\tmicLabel.textContent = 'No mic, replay only'\n\t\t\tmic.setAttribute('aria-label', 'Microphone not granted, replay only')\n\t\t\tmic.setAttribute('aria-pressed', 'false')\n\t\t\tmic.setAttribute('tabindex', '-1')\n\t\t\tbreak\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\tif (!isMediaRecorderSupported()) {\n\t\tctx.logger.warn('MediaRecorder not supported, continuing without audio')\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.indicatorState = 'no-audio'\n\t\trenderIndicatorState(store)\n\t\treturn\n\t}\n\tstore.stream = stream\n\tstore.hasMicPermission = true\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.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}\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\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\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) return\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\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\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 }\n"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/plugins/user-test.ts"],"names":[],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAA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","file":"user-test.cjs","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`), flushes any buffered chunks and calls\n// 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 30.\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\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\tchunkSeconds: 30,\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\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\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\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"]}