@merittdev/horus-lens 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../browser/src/index.ts","../../browser/src/gate.ts","../../browser/src/overlay/env.ts","../../browser/src/overlay/dom.ts","../../browser/src/overlay/geometry.ts","../../browser/src/overlay/icons.ts","../../browser/src/overlay/annotation-editor.ts","../../browser/src/overlay/panel.ts","../../browser/src/overlay/picker.ts","../../browser/src/overlay/styles.ts","../../browser/src/overlay/overlay.ts","../../browser/src/queue.ts","../../browser/src/snippet.ts"],"sourcesContent":["import { LensClient, type LensConfig } from '@horus-lens/core';\nimport { clearGate, DEFAULT_PARAM_NAME, evaluateGate, isGateActive } from './gate.js';\nimport { detectBrowser, detectOs, currentRoute, viewport } from './overlay/env.js';\nimport { mountOverlay, type OverlayHandle, type OverlayStats } from './overlay/index.js';\nimport { applyContext, installGlobal, processQueue, type QueuedCommands } from './queue.js';\n\nexport interface BootOptions extends Partial<Omit<LensConfig, 'accessId'>> {\n /** Falls back to a `<script data-lens-id>` attribute or a queued `init` call. */\n accessId?: string;\n /** Query param that gates activation. Default `'lens'` → `?lens=true`. */\n paramName?: string;\n /** Bypass the query-param gate (preview envs / the React provider). */\n force?: boolean;\n}\n\nexport interface LensBrowser {\n client: LensClient;\n /** Open the report panel. */\n open(): void;\n /** Close the report panel (overlay stays mounted). */\n close(): void;\n /** Remove the overlay, stop the client, and clear gate persistence. */\n destroy(): void;\n}\n\nexport { isGateActive } from './gate.js';\nexport { loaderSnippet, LOADER_SNIPPET, DEFAULT_CDN_URL } from './snippet.js';\nexport type { SnippetOptions } from './snippet.js';\nexport { processQueue, installGlobal } from './queue.js';\nexport type { QueuedCommands, LensCommand, LensGlobal } from './queue.js';\nexport type { OverlayStats } from './overlay/index.js';\n\nfunction hasDom(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nfunction scriptAccessId(): string | undefined {\n const tag = document.querySelector('script[data-lens-id]');\n return tag?.getAttribute('data-lens-id') ?? undefined;\n}\n\n/** Resolve access id + base config from options, script tag, and queued init. */\nfunction resolveConfig(\n options: BootOptions,\n commands: QueuedCommands,\n): { accessId: string; config: LensConfig } | null {\n const { accessId: optAccessId, paramName: _p, force: _f, ...rest } = options;\n\n let queuedConfig: Record<string, unknown> = {};\n let queuedAccessId: string | undefined;\n if (typeof commands.init === 'string') {\n queuedAccessId = commands.init;\n } else if (commands.init && typeof commands.init === 'object') {\n queuedConfig = commands.init;\n if (typeof commands.init.accessId === 'string') queuedAccessId = commands.init.accessId;\n }\n\n const accessId = optAccessId ?? scriptAccessId() ?? queuedAccessId;\n if (!accessId) return null;\n\n const config = { ...queuedConfig, ...rest, accessId } as unknown as LensConfig;\n return { accessId, config };\n}\n\n/**\n * Boot the overlay: gate check → resolve access id → start a LensClient →\n * mount the overlay → wire the global command dispatcher. Returns `null` on the\n * server, when the gate is inactive, or when no access id can be resolved.\n */\nexport function boot(options: BootOptions = {}): LensBrowser | null {\n if (!hasDom()) return null;\n\n const commands = processQueue();\n const paramName = options.paramName ?? DEFAULT_PARAM_NAME;\n\n const active = options.force === true || evaluateGate(paramName);\n if (!active) {\n installGlobal(null);\n return null;\n }\n\n const resolved = resolveConfig(options, commands);\n if (!resolved) {\n if (options.debug) console.warn('[lens] no accessId — overlay not booted');\n installGlobal(null);\n return null;\n }\n\n const client = new LensClient(resolved.config);\n client.start();\n\n const snapshotStats = (): OverlayStats => ({\n url: window.location.href,\n route: currentRoute(),\n browser: detectBrowser(),\n os: detectOs(),\n viewport: viewport(),\n replay: resolved.config.replay !== false,\n // Console / network / error counts are not exposed by the public core API.\n console: null,\n network: null,\n errors: null,\n });\n\n let overlay: OverlayHandle | null = null;\n const browser: LensBrowser = {\n client,\n open: () => overlay?.open(),\n close: () => overlay?.close(),\n destroy: () => {\n overlay?.destroy();\n overlay = null;\n client.stop();\n clearGate();\n installGlobal(null);\n },\n };\n\n overlay = mountOverlay({\n client,\n snapshotStats,\n onDismiss: () => {\n client.stop();\n clearGate();\n installGlobal(null);\n },\n });\n\n installGlobal(browser);\n applyContext(browser, commands);\n\n return browser;\n}\n\n/**\n * Auto-boot on bundle load when a queued `init` command or a\n * `<script data-lens-id>` attribute supplies an access id and the gate is\n * active. No-op during SSR. Exposed so the entry can self-initialize when\n * loaded via the CDN snippet, while ESM consumers call `boot()` directly.\n */\nexport function autoBoot(): LensBrowser | null {\n if (!hasDom()) return null;\n const hasQueuedInit = Array.from(window.Lens?.q ?? []).some(\n (entry) => (entry as ArrayLike<unknown>)[0] === 'init',\n );\n const hasScriptId = !!document.querySelector('script[data-lens-id]');\n if (!hasQueuedInit && !hasScriptId) return null;\n if (!isGateActive()) return null;\n return boot();\n}\n\n// Self-initialize when loaded via the CDN snippet: a queued `init` command or a\n// `<script data-lens-id>` attribute plus an active gate is enough to boot. This\n// is a no-op for bundler/ESM consumers (React provider, composition package),\n// which have neither and drive `boot({ force })` themselves.\nif (hasDom()) autoBoot();\n","/**\n * Activation gate — decides whether the overlay should mount on this page.\n *\n * The overlay is opt-in per session: it activates when the URL carries\n * `?lens=true` (param name configurable). Once seen we persist a flag in\n * sessionStorage so client-side navigations that drop the query param keep the\n * overlay alive for the rest of the tab session. Passing `?lens=false` (or\n * `off` / `0`) clears the flag and deactivates.\n */\n\nexport const DEFAULT_PARAM_NAME = 'lens';\nexport const GATE_STORAGE_KEY = 'lens:active';\n\n// Deprecated pre-rename (\"Lense\") identifiers, still honoured read-only so\n// existing links/sessions minted before the Lens rename keep working.\nconst LEGACY_PARAM_NAME = 'lense';\nconst LEGACY_STORAGE_KEY = 'lense:active';\n\nconst TRUTHY = new Set(['', 'true', '1', 'on', 'yes']);\nconst FALSY = new Set(['false', '0', 'off', 'no']);\n\nfunction hasWindow(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nfunction readParam(paramName: string): string | null {\n try {\n const params = new URLSearchParams(window.location.search);\n // Prefer the new param; fall back to the deprecated `?lense=` for back-compat.\n const value = params.get(paramName);\n if (value !== null) return value;\n if (paramName === DEFAULT_PARAM_NAME) return params.get(LEGACY_PARAM_NAME);\n return null;\n } catch {\n return null;\n }\n}\n\nfunction readStorage(): boolean {\n try {\n const s = window.sessionStorage;\n // Deprecated `lense:active` key is read-only back-compat for old sessions.\n return s.getItem(GATE_STORAGE_KEY) === '1' || s.getItem(LEGACY_STORAGE_KEY) === '1';\n } catch {\n return false;\n }\n}\n\nfunction writeStorage(active: boolean): void {\n try {\n if (active) window.sessionStorage.setItem(GATE_STORAGE_KEY, '1');\n else window.sessionStorage.removeItem(GATE_STORAGE_KEY);\n } catch {\n /* storage may be unavailable (private mode, sandbox) — degrade gracefully */\n }\n}\n\n/**\n * Evaluate the gate against the URL param and persisted session flag, applying\n * any side effects (persist on activate, clear on explicit deactivate).\n */\nexport function evaluateGate(paramName: string = DEFAULT_PARAM_NAME): boolean {\n if (!hasWindow()) return false;\n\n const raw = readParam(paramName);\n if (raw !== null) {\n const value = raw.trim().toLowerCase();\n if (FALSY.has(value)) {\n writeStorage(false);\n return false;\n }\n if (TRUTHY.has(value)) {\n writeStorage(true);\n return true;\n }\n // Unrecognised value — fall through to persisted state.\n }\n\n return readStorage();\n}\n\n/** Read-only gate check (param OR persisted flag). Never mutates storage. */\nexport function isGateActive(paramName: string = DEFAULT_PARAM_NAME): boolean {\n if (!hasWindow()) return false;\n\n const raw = readParam(paramName);\n if (raw !== null) {\n const value = raw.trim().toLowerCase();\n if (FALSY.has(value)) return false;\n if (TRUTHY.has(value)) return true;\n }\n return readStorage();\n}\n\n/** Clear the persisted session flag (used when the user closes the overlay). */\nexport function clearGate(): void {\n if (!hasWindow()) return;\n writeStorage(false);\n}\n","/**\n * Best-effort browser/OS detection from the user agent, plus viewport/route\n * readers. These feed the read-only context chips shown in the report panel;\n * the authoritative capture lives in @horus-lens/core.\n */\n\nexport function detectBrowser(ua: string = navigator.userAgent): string {\n if (/Edg\\//.test(ua)) return 'Edge';\n if (/OPR\\/|Opera/.test(ua)) return 'Opera';\n if (/Firefox\\//.test(ua)) return 'Firefox';\n if (/Chrome\\//.test(ua) && !/Chromium/.test(ua)) return 'Chrome';\n if (/Chromium\\//.test(ua)) return 'Chromium';\n if (/Safari\\//.test(ua) && /Version\\//.test(ua)) return 'Safari';\n return 'Browser';\n}\n\nexport function detectOs(ua: string = navigator.userAgent): string {\n if (/Windows NT/.test(ua)) return 'Windows';\n if (/Mac OS X|Macintosh/.test(ua)) return 'macOS';\n if (/Android/.test(ua)) return 'Android';\n if (/iPhone|iPad|iPod/.test(ua)) return 'iOS';\n if (/Linux/.test(ua)) return 'Linux';\n return 'Unknown';\n}\n\nexport function viewport(): { width: number; height: number } {\n return {\n width: window.innerWidth || document.documentElement.clientWidth || 0,\n height: window.innerHeight || document.documentElement.clientHeight || 0,\n };\n}\n\nexport function currentRoute(): string {\n return (window.location.pathname || '/') + (window.location.search || '');\n}\n","/** Tiny framework-free DOM helpers used to build the overlay tree. */\n\ntype Child = Node | string | null | undefined | false;\n\nexport interface ElProps {\n class?: string;\n text?: string;\n html?: string;\n title?: string;\n type?: string;\n placeholder?: string;\n ariaLabel?: string;\n attrs?: Record<string, string>;\n style?: Partial<CSSStyleDeclaration>;\n on?: Partial<Record<keyof HTMLElementEventMap, (e: Event) => void>>;\n}\n\nexport function el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n props: ElProps = {},\n children: Child[] = [],\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (props.class) node.className = props.class;\n if (props.text !== undefined) node.textContent = props.text;\n if (props.html !== undefined) node.innerHTML = props.html;\n if (props.title) node.title = props.title;\n if (props.ariaLabel) node.setAttribute('aria-label', props.ariaLabel);\n if (props.type && 'type' in node) (node as unknown as { type: string }).type = props.type;\n if (props.placeholder && 'placeholder' in node) {\n (node as unknown as { placeholder: string }).placeholder = props.placeholder;\n }\n if (props.attrs) {\n for (const [k, v] of Object.entries(props.attrs)) node.setAttribute(k, v);\n }\n if (props.style) Object.assign(node.style, props.style);\n if (props.on) {\n for (const [event, handler] of Object.entries(props.on)) {\n if (handler) node.addEventListener(event, handler as EventListener);\n }\n }\n for (const child of children) {\n if (child === null || child === undefined || child === false) continue;\n node.append(child);\n }\n return node;\n}\n\nexport function clear(node: Node): void {\n while (node.firstChild) node.removeChild(node.firstChild);\n}\n","/**\n * Pure geometry helpers for the SVG annotation editor. Kept free of DOM so the\n * math (point thinning / simplification, crop-bounds union, arrowhead polygon)\n * is unit-testable in isolation.\n *\n * ALL coordinates are DOCUMENT CSS pixels — the same space annotations are\n * emitted in.\n */\nimport type { Annotation } from '@horus-lens/shared';\n\nexport interface Point {\n x: number;\n y: number;\n}\n\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Minimum pointer travel (px) before a freehand point is kept. */\nexport const THIN_MIN_DIST = 3;\n/** Hard cap on points captured per freehand stroke. */\nexport const MAX_POINTS = 2000;\n/** Highlighter is always drawn at this stroke width (ignores S/M/L). */\nexport const HIGHLIGHTER_WIDTH = 14;\n/** Step badge circle radius. */\nexport const STEP_RADIUS = 12;\n\nexport function distance(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\n/**\n * True when `candidate` is far enough from `last` to be worth keeping while\n * capturing a freehand stroke (thins jitter at capture time).\n */\nexport function shouldKeepPoint(last: Point, candidate: Point, minDist = THIN_MIN_DIST): boolean {\n return distance(last, candidate) >= minDist;\n}\n\n/** Perpendicular distance from `p` to the segment `a`→`b`. */\nfunction perpendicularDistance(p: Point, a: Point, b: Point): number {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) return distance(p, a);\n let t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / len2;\n t = Math.max(0, Math.min(1, t));\n return distance(p, { x: a.x + t * dx, y: a.y + t * dy });\n}\n\n/**\n * Ramer–Douglas–Peucker simplification. Drops points that sit within\n * `tolerance` px of the line between their neighbours — a light pass applied on\n * pointerup so freehand strokes stay smooth but cheap.\n */\nexport function simplifyPoints(points: Point[], tolerance = 1): Point[] {\n if (points.length <= 2 || tolerance <= 0) return points.map((p) => ({ ...p }));\n const first = points[0]!;\n const last = points[points.length - 1]!;\n\n let maxDist = 0;\n let index = 0;\n for (let i = 1; i < points.length - 1; i++) {\n const d = perpendicularDistance(points[i]!, first, last);\n if (d > maxDist) {\n maxDist = d;\n index = i;\n }\n }\n\n if (maxDist > tolerance) {\n const left = simplifyPoints(points.slice(0, index + 1), tolerance);\n const right = simplifyPoints(points.slice(index), tolerance);\n return left.slice(0, -1).concat(right);\n }\n return [{ ...first }, { ...last }];\n}\n\n/**\n * Three points of the filled arrowhead triangle for the segment tail→head.\n * Returned as `[tip, base1, base2]` in document coords. Drawn as an explicit\n * `<polygon>` because SVG `<marker>` does not rasterize reliably from a\n * serialized data-URL SVG.\n */\nexport function arrowheadPolygon(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n size = 14,\n): Point[] {\n const angle = Math.atan2(y2 - y1, x2 - x1);\n const spread = Math.PI / 7; // ~25.7° half-angle\n return [\n { x: x2, y: y2 },\n { x: x2 - size * Math.cos(angle - spread), y: y2 - size * Math.sin(angle - spread) },\n { x: x2 - size * Math.cos(angle + spread), y: y2 - size * Math.sin(angle + spread) },\n ];\n}\n\n/** Bounding box of an annotation in document coords, or `null` if degenerate. */\nexport function boundsOfAnnotation(a: Annotation): Bounds | null {\n switch (a.kind) {\n case 'rect':\n case 'ellipse':\n case 'blur': {\n const x = Math.min(a.x, a.x + a.width);\n const y = Math.min(a.y, a.y + a.height);\n return { x, y, width: Math.abs(a.width), height: Math.abs(a.height) };\n }\n case 'arrow':\n case 'line': {\n const x = Math.min(a.x1, a.x2);\n const y = Math.min(a.y1, a.y2);\n return { x, y, width: Math.abs(a.x2 - a.x1), height: Math.abs(a.y2 - a.y1) };\n }\n case 'pencil':\n case 'highlighter': {\n if (a.points.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const p of a.points) {\n minX = Math.min(minX, p.x);\n minY = Math.min(minY, p.y);\n maxX = Math.max(maxX, p.x);\n maxY = Math.max(maxY, p.y);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n }\n case 'text': {\n const fontSize = a.fontSize ?? 16;\n // Rough estimate; the editor prefers a live getBBox() when available.\n const width = Math.max(1, a.text.length * fontSize * 0.6);\n return { x: a.x, y: a.y, width, height: fontSize * 1.2 };\n }\n case 'step': {\n return {\n x: a.x - STEP_RADIUS,\n y: a.y - STEP_RADIUS,\n width: STEP_RADIUS * 2,\n height: STEP_RADIUS * 2,\n };\n }\n }\n}\n\n/** Union of a list of bounds, or `null` when the list is empty. */\nexport function unionBounds(list: Bounds[]): Bounds | null {\n if (list.length === 0) return null;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const b of list) {\n minX = Math.min(minX, b.x);\n minY = Math.min(minY, b.y);\n maxX = Math.max(maxX, b.x + b.width);\n maxY = Math.max(maxY, b.y + b.height);\n }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Expand `b` by `padding` on every side, then clamp to the document box\n * `[0..maxWidth] × [0..maxHeight]`.\n */\nexport function padAndClampBounds(\n b: Bounds,\n padding: number,\n maxWidth: number,\n maxHeight: number,\n): Bounds {\n const x = Math.max(0, b.x - padding);\n const y = Math.max(0, b.y - padding);\n const right = Math.min(maxWidth, b.x + b.width + padding);\n const bottom = Math.min(maxHeight, b.y + b.height + padding);\n return { x, y, width: Math.max(0, right - x), height: Math.max(0, bottom - y) };\n}\n","/** Inline SVG icon strings (16px, currentColor). Used via ElProps.html. */\n\nconst svg = (inner: string): string =>\n `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${inner}</svg>`;\n\nexport const iconEye = svg(\n '<path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n);\n\nexport const iconCrosshair = svg(\n '<circle cx=\"12\" cy=\"12\" r=\"8\"/><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"6\"/><line x1=\"12\" y1=\"18\" x2=\"12\" y2=\"22\"/><line x1=\"2\" y1=\"12\" x2=\"6\" y2=\"12\"/><line x1=\"18\" y1=\"12\" x2=\"22\" y2=\"12\"/>',\n);\n\nexport const iconClose = svg('<line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>');\n\nexport const iconMark = svg(\n '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" stroke-dasharray=\"4 3\"/>',\n);\n\nexport const iconCopy = svg(\n '<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\"/><path d=\"M5 15V5a2 2 0 0 1 2-2h10\"/>',\n);\n\nexport const iconCheck = svg('<polyline points=\"20 6 9 17 4 12\"/>');\n\nexport const iconSend = svg('<line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/><polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>');\n\n/** Filled red dot — \"record steps\". Uses a fixed fill so it reads as a record cue. */\nexport const iconRecord = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"6\" fill=\"#ef4444\"/></svg>`;\n\n/** Square \"stop\" glyph. */\nexport const iconStop = `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\"/></svg>`;\n\n/* ---------------- Annotation tool glyphs ---------------- */\n\nexport const iconRectTool = svg('<rect x=\"4\" y=\"6\" width=\"16\" height=\"12\" rx=\"1\"/>');\n\nexport const iconEllipseTool = svg('<ellipse cx=\"12\" cy=\"12\" rx=\"8\" ry=\"6\"/>');\n\nexport const iconArrowTool = svg('<line x1=\"5\" y1=\"19\" x2=\"18\" y2=\"6\"/><polyline points=\"18 12 18 6 12 6\"/>');\n\nexport const iconLineTool = svg('<line x1=\"5\" y1=\"19\" x2=\"19\" y2=\"5\"/>');\n\nexport const iconPencil = svg('<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>');\n\nexport const iconHighlighter = svg(\n '<path d=\"m9 11-6 6v3h9l3-3\"/><path d=\"m22 12-4.6 4.6a1 1 0 0 1-1.4 0l-5.6-5.6a1 1 0 0 1 0-1.4L14 4\"/>',\n);\n\nexport const iconText = svg(\n '<polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"/>',\n);\n\nexport const iconStepTool = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M11.2 9 13 8v8\"/>');\n\nexport const iconBlur = svg('<path d=\"M12 3s6 6.4 6 10a6 6 0 0 1-12 0c0-3.6 6-10 6-10Z\"/>');\n\nexport const iconUndo = svg('<path d=\"M9 14 4 9l5-5\"/><path d=\"M4 9h11a5 5 0 0 1 0 10h-1\"/>');\n\nexport const iconTrash = svg(\n '<polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>',\n);\n\n/** Panel action glyph — replaces the old dashed-rect \"Mark area\" icon. */\nexport const iconAnnotate = iconPencil;\n","import type { Annotation } from '@horus-lens/shared';\nimport { el } from './dom.js';\nimport {\n arrowheadPolygon,\n boundsOfAnnotation,\n distance,\n HIGHLIGHTER_WIDTH,\n MAX_POINTS,\n padAndClampBounds,\n shouldKeepPoint,\n simplifyPoints,\n STEP_RADIUS,\n unionBounds,\n type Bounds,\n type Point,\n} from './geometry.js';\nimport {\n iconArrowTool,\n iconBlur,\n iconEllipseTool,\n iconHighlighter,\n iconLineTool,\n iconPencil,\n iconRectTool,\n iconStepTool,\n iconText,\n iconTrash,\n iconUndo,\n} from './icons.js';\n\nconst SVG_NS = 'http://www.w3.org/2000/svg';\nconst FONT = \"-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\";\n\n/** Minimum drag extent before a shape/segment is committed (vs. treated as a tap). */\nconst MIN_DRAG = 6;\n\ntype Tool =\n | 'rect'\n | 'ellipse'\n | 'arrow'\n | 'line'\n | 'pencil'\n | 'highlighter'\n | 'text'\n | 'step'\n | 'blur';\n\nconst TOOLS: ReadonlyArray<{ tool: Tool; icon: string; label: string }> = [\n { tool: 'rect', icon: iconRectTool, label: 'Rectangle' },\n { tool: 'ellipse', icon: iconEllipseTool, label: 'Ellipse' },\n { tool: 'arrow', icon: iconArrowTool, label: 'Arrow' },\n { tool: 'line', icon: iconLineTool, label: 'Line' },\n { tool: 'pencil', icon: iconPencil, label: 'Pencil' },\n { tool: 'highlighter', icon: iconHighlighter, label: 'Highlighter' },\n { tool: 'text', icon: iconText, label: 'Text' },\n { tool: 'step', icon: iconStepTool, label: 'Step number' },\n { tool: 'blur', icon: iconBlur, label: 'Blur / redact' },\n];\n\nconst COLORS = ['#ef4444', '#f59e0b', '#22c55e', '#3b82f6', '#8b5cf6', '#111827'] as const;\nconst WIDTHS: ReadonlyArray<{ label: string; value: number }> = [\n { label: 'S', value: 2 },\n { label: 'M', value: 3.5 },\n { label: 'L', value: 6 },\n];\n\n/** In-progress drag/draw state. */\ninterface DragState {\n tool: Tool;\n color: string;\n width: number;\n start: Point;\n node: SVGElement;\n points?: Point[];\n last?: Point;\n line?: SVGElement;\n head?: SVGElement;\n}\n\n/**\n * SVG annotation editor. Replaces the div-rect Annotator with a full-DOCUMENT\n * `<svg>` overlay whose marks anchor to page content (they survive scrolling)\n * and serialize to a standalone composite for server-side rasterization.\n *\n * Session semantics mirror the old Annotator: `start(onExit)` arms drawing,\n * \"Done\" (or Escape) keeps this session's marks, \"Cancel\" discards them.\n */\nexport class AnnotationEditor {\n private svg: SVGSVGElement | null = null;\n private bg: SVGRectElement | null = null;\n private toolbar: HTMLElement | null = null;\n private textInputEl: HTMLInputElement | null = null;\n private textAnchor: Point | null = null;\n private textColor: string = COLORS[0];\n\n private annotations: Annotation[] = [];\n private markNodes: SVGElement[] = [];\n private drag: DragState | null = null;\n\n private active = false;\n private sessionBase = 0;\n private stepCounter = 0;\n private idSeq = 0;\n private onExit: (() => void) | null = null;\n\n private tool: Tool = 'rect';\n private color: string = COLORS[0];\n private width = 3.5;\n\n private docW = 0;\n private docH = 0;\n private resizeObserver: ResizeObserver | null = null;\n\n private readonly toolBtns = new Map<Tool, HTMLButtonElement>();\n private readonly colorBtns = new Map<string, HTMLButtonElement>();\n private readonly widthBtns = new Map<number, HTMLButtonElement>();\n private undoBtn: HTMLButtonElement | null = null;\n private clearBtn: HTMLButtonElement | null = null;\n\n constructor(private readonly host: HTMLElement) {}\n\n get isActive(): boolean {\n return this.active;\n }\n\n get count(): number {\n return this.annotations.length;\n }\n\n /** Deep-copied document-coord annotations per the schema contract. */\n list(): Annotation[] {\n return this.annotations.map((a) => {\n const copy: Annotation = { ...a };\n if ('points' in copy && Array.isArray(copy.points)) {\n copy.points = copy.points.map((p) => ({ ...p }));\n }\n if (copy.kind === 'rect' && copy.viewport) copy.viewport = { ...copy.viewport };\n return copy;\n });\n }\n\n /** Remove every mark. Tears the layer down when not actively drawing. */\n clear(): void {\n for (const node of this.markNodes) node.remove();\n this.markNodes = [];\n this.annotations = [];\n this.stepCounter = 0;\n if (!this.active) this.teardownLayer();\n this.syncActionButtons();\n }\n\n start(onExit: () => void): void {\n if (this.active) return;\n this.ensureLayer();\n const svg = this.svg!;\n this.active = true;\n this.onExit = onExit;\n this.sessionBase = this.annotations.length;\n this.stepCounter = 0;\n this.sizeLayer();\n this.updateTransform();\n svg.style.pointerEvents = 'auto';\n svg.style.touchAction = 'none';\n svg.style.cursor = 'crosshair';\n svg.addEventListener('pointerdown', this.onPointerDown);\n this.buildToolbar();\n window.addEventListener('keydown', this.onKey, true);\n }\n\n /** Done — keep this session's marks, exit draw mode. */\n exit(): void {\n if (!this.active) return;\n this.active = false;\n this.commitTextInput(); // flush any in-progress text\n if (this.drag) {\n this.drag.node.remove();\n this.detachDragListeners();\n this.drag = null;\n }\n const svg = this.svg;\n if (svg) {\n svg.removeEventListener('pointerdown', this.onPointerDown);\n svg.style.pointerEvents = 'none';\n svg.style.touchAction = '';\n svg.style.cursor = '';\n }\n window.removeEventListener('keydown', this.onKey, true);\n this.removeToolbar();\n const cb = this.onExit;\n this.onExit = null;\n cb?.();\n }\n\n /** Cancel — discard marks drawn during this session, then exit. */\n private cancel(): void {\n // Discard any in-progress text FIRST so `exit()`'s flush can't re-commit it\n // after the splice (some browsers don't blur the input on the Cancel click).\n this.cancelTextInput();\n const removed = this.markNodes.splice(this.sessionBase);\n for (const node of removed) node.remove();\n this.annotations.splice(this.sessionBase);\n this.exit();\n }\n\n private undo(): void {\n const node = this.markNodes.pop();\n if (!node) return;\n node.remove();\n this.annotations.pop();\n this.syncActionButtons();\n }\n\n // --------------------------------------------------------------------------\n // Composite / crop\n // --------------------------------------------------------------------------\n\n /**\n * Complete standalone SVG of every NON-blur mark, plus blur regions returned\n * separately. `null` when there are no marks.\n */\n getComposite(): {\n svgMarkup: string;\n docWidth: number;\n docHeight: number;\n blurRegions: Bounds[];\n } | null {\n if (this.annotations.length === 0 || !this.svg) return null;\n this.sizeLayer();\n const docWidth = this.docW;\n const docHeight = this.docH;\n\n const clone = this.svg.cloneNode(true) as SVGSVGElement;\n clone.removeAttribute('style');\n clone.removeAttribute('class');\n // Strip editor chrome, in-progress drafts, and blur previews.\n clone\n .querySelectorAll('[data-lens-chrome],[data-lens-draft],[data-lens-blur]')\n .forEach((n) => n.remove());\n clone.querySelector('defs')?.remove();\n clone.setAttribute('xmlns', SVG_NS);\n clone.setAttribute('viewBox', `0 0 ${docWidth} ${docHeight}`);\n clone.setAttribute('width', String(docWidth));\n clone.setAttribute('height', String(docHeight));\n\n const svgMarkup = new XMLSerializer().serializeToString(clone);\n const blurRegions: Bounds[] = this.annotations\n .filter((a): a is Extract<Annotation, { kind: 'blur' }> => a.kind === 'blur')\n .map((a) => ({ x: a.x, y: a.y, width: a.width, height: a.height }));\n\n return { svgMarkup, docWidth, docHeight, blurRegions };\n }\n\n /** Union bbox of all marks + 24px padding, clamped to the document. */\n getCropBounds(): Bounds | undefined {\n if (this.annotations.length === 0) return undefined;\n const boxes: Bounds[] = [];\n for (let i = 0; i < this.annotations.length; i++) {\n const a = this.annotations[i]!;\n const b = a.kind === 'text' ? this.textBounds(i) : boundsOfAnnotation(a);\n if (b) boxes.push(b);\n }\n const u = unionBounds(boxes);\n if (!u) return undefined;\n this.sizeLayer();\n return padAndClampBounds(u, 24, this.docW, this.docH);\n }\n\n /** Prefer a live getBBox() for text; fall back to the geometric estimate. */\n private textBounds(index: number): Bounds | null {\n const node = this.markNodes[index];\n const annotation = this.annotations[index]!;\n if (node && typeof (node as SVGGraphicsElement).getBBox === 'function') {\n try {\n const box = (node as SVGGraphicsElement).getBBox();\n if (box.width > 0 && box.height > 0) {\n return { x: box.x, y: box.y, width: box.width, height: box.height };\n }\n } catch {\n /* getBBox throws for un-rendered nodes — fall through to the estimate */\n }\n }\n return boundsOfAnnotation(annotation);\n }\n\n // --------------------------------------------------------------------------\n // Layer lifecycle\n // --------------------------------------------------------------------------\n\n private ensureLayer(): void {\n if (this.svg) return;\n const svg = document.createElementNS(SVG_NS, 'svg') as SVGSVGElement;\n svg.setAttribute('class', 'lens-annotate-svg');\n svg.setAttribute('xmlns', SVG_NS);\n\n const defs = document.createElementNS(SVG_NS, 'defs');\n defs.setAttribute('data-lens-chrome', '1');\n // Diagonal hatch fill for blur/redaction previews (~35% opacity baked in).\n const pattern = document.createElementNS(SVG_NS, 'pattern');\n pattern.setAttribute('id', 'lens-blur-hatch');\n pattern.setAttribute('width', '8');\n pattern.setAttribute('height', '8');\n pattern.setAttribute('patternUnits', 'userSpaceOnUse');\n pattern.setAttribute('patternTransform', 'rotate(45)');\n const patternBase = document.createElementNS(SVG_NS, 'rect');\n patternBase.setAttribute('width', '8');\n patternBase.setAttribute('height', '8');\n patternBase.setAttribute('fill', 'rgba(17,24,39,0.12)');\n const patternLine = document.createElementNS(SVG_NS, 'line');\n patternLine.setAttribute('x1', '0');\n patternLine.setAttribute('y1', '0');\n patternLine.setAttribute('x2', '0');\n patternLine.setAttribute('y2', '8');\n patternLine.setAttribute('stroke', 'rgba(17,24,39,0.55)');\n patternLine.setAttribute('stroke-width', '4');\n pattern.append(patternBase, patternLine);\n defs.append(pattern);\n svg.append(defs);\n\n // Transparent capture surface so empty regions still start a draw.\n const bg = document.createElementNS(SVG_NS, 'rect') as SVGRectElement;\n bg.setAttribute('data-lens-chrome', '1');\n bg.setAttribute('x', '0');\n bg.setAttribute('y', '0');\n bg.setAttribute('fill', 'transparent');\n bg.style.pointerEvents = 'all';\n svg.append(bg);\n\n this.svg = svg;\n this.bg = bg;\n this.host.append(svg);\n\n // Re-anchor on scroll; resize the surface when the document grows.\n window.addEventListener('scroll', this.onScroll, { passive: true, capture: true });\n window.addEventListener('resize', this.onResize);\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(this.onResize);\n this.resizeObserver.observe(document.documentElement);\n }\n this.sizeLayer();\n this.updateTransform();\n }\n\n private teardownLayer(): void {\n window.removeEventListener('scroll', this.onScroll, true);\n window.removeEventListener('resize', this.onResize);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.svg?.remove();\n this.svg = null;\n this.bg = null;\n }\n\n private docSize(): { width: number; height: number } {\n const d = document.documentElement;\n const b = document.body;\n const width = Math.max(d.scrollWidth, b?.scrollWidth ?? 0, d.clientWidth);\n const height = Math.max(d.scrollHeight, b?.scrollHeight ?? 0, d.clientHeight);\n return { width, height };\n }\n\n private sizeLayer(): void {\n if (!this.svg) return;\n const { width, height } = this.docSize();\n this.docW = width;\n this.docH = height;\n this.svg.setAttribute('width', String(width));\n this.svg.setAttribute('height', String(height));\n this.svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n this.svg.style.width = `${width}px`;\n this.svg.style.height = `${height}px`;\n if (this.bg) {\n this.bg.setAttribute('width', String(width));\n this.bg.setAttribute('height', String(height));\n }\n }\n\n private updateTransform(): void {\n if (!this.svg) return;\n const scrollX = window.scrollX || window.pageXOffset || 0;\n const scrollY = window.scrollY || window.pageYOffset || 0;\n this.svg.style.left = `${-scrollX}px`;\n this.svg.style.top = `${-scrollY}px`;\n }\n\n private onScroll = (): void => this.updateTransform();\n private onResize = (): void => {\n this.sizeLayer();\n this.updateTransform();\n };\n\n // --------------------------------------------------------------------------\n // Toolbar\n // --------------------------------------------------------------------------\n\n private buildToolbar(): void {\n this.toolBtns.clear();\n this.colorBtns.clear();\n this.widthBtns.clear();\n\n const toolGroup = el('div', { class: 'lens-tool-group' });\n for (const { tool, icon, label } of TOOLS) {\n const btn = el('button', {\n class: 'lens-tool-btn',\n ariaLabel: label,\n title: label,\n html: icon,\n attrs: { type: 'button', 'aria-pressed': String(tool === this.tool) },\n on: { click: () => this.selectTool(tool) },\n });\n this.toolBtns.set(tool, btn);\n toolGroup.append(btn);\n }\n\n const colorGroup = el('div', { class: 'lens-tool-group lens-swatches' });\n for (const c of COLORS) {\n const btn = el('button', {\n class: 'lens-swatch',\n ariaLabel: `Color ${c}`,\n title: c,\n attrs: { type: 'button', 'aria-pressed': String(c === this.color) },\n style: { background: c },\n on: { click: () => this.selectColor(c) },\n });\n this.colorBtns.set(c, btn);\n colorGroup.append(btn);\n }\n\n const widthGroup = el('div', { class: 'lens-tool-group' });\n for (const { label, value } of WIDTHS) {\n const btn = el('button', {\n class: 'lens-width-btn',\n text: label,\n ariaLabel: `Stroke width ${label}`,\n title: `Stroke ${label} (${value}px)`,\n attrs: { type: 'button', 'aria-pressed': String(value === this.width) },\n on: { click: () => this.selectWidth(value) },\n });\n this.widthBtns.set(value, btn);\n widthGroup.append(btn);\n }\n\n this.undoBtn = el('button', {\n class: 'lens-tool-btn',\n ariaLabel: 'Undo',\n title: 'Undo',\n html: iconUndo,\n attrs: { type: 'button' },\n on: { click: () => this.undo() },\n });\n this.clearBtn = el('button', {\n class: 'lens-tool-btn',\n ariaLabel: 'Clear all',\n title: 'Clear all',\n html: iconTrash,\n attrs: { type: 'button' },\n on: { click: () => this.clear() },\n });\n const editGroup = el('div', { class: 'lens-tool-group' }, [this.undoBtn, this.clearBtn]);\n\n const doneGroup = el('div', { class: 'lens-tool-group' }, [\n el('button', {\n class: 'lens-pick-chip__btn',\n text: 'Cancel',\n attrs: { type: 'button' },\n on: { click: () => this.cancel() },\n }),\n el('button', {\n class: 'lens-pick-chip__btn lens-pick-chip__btn--primary',\n text: 'Done',\n attrs: { type: 'button' },\n on: { click: () => this.exit() },\n }),\n ]);\n\n this.toolbar = el(\n 'div',\n { class: 'lens-annotate-toolbar', attrs: { role: 'toolbar', 'aria-label': 'Annotation tools' } },\n [\n toolGroup,\n el('span', { class: 'lens-tool-sep' }),\n colorGroup,\n el('span', { class: 'lens-tool-sep' }),\n widthGroup,\n el('span', { class: 'lens-tool-sep' }),\n editGroup,\n el('span', { class: 'lens-tool-sep' }),\n doneGroup,\n ],\n );\n this.host.append(this.toolbar);\n this.syncActionButtons();\n }\n\n private removeToolbar(): void {\n this.toolbar?.remove();\n this.toolbar = null;\n this.toolBtns.clear();\n this.colorBtns.clear();\n this.widthBtns.clear();\n this.undoBtn = null;\n this.clearBtn = null;\n }\n\n private selectTool(tool: Tool): void {\n this.commitTextInput();\n this.tool = tool;\n for (const [t, btn] of this.toolBtns) {\n const on = t === tool;\n btn.classList.toggle('is-active', on);\n btn.setAttribute('aria-pressed', String(on));\n }\n if (this.svg) this.svg.style.cursor = tool === 'text' ? 'text' : 'crosshair';\n }\n\n private selectColor(color: string): void {\n this.color = color;\n for (const [c, btn] of this.colorBtns) {\n const on = c === color;\n btn.classList.toggle('is-active', on);\n btn.setAttribute('aria-pressed', String(on));\n }\n }\n\n private selectWidth(value: number): void {\n this.width = value;\n for (const [v, btn] of this.widthBtns) {\n const on = v === value;\n btn.classList.toggle('is-active', on);\n btn.setAttribute('aria-pressed', String(on));\n }\n }\n\n private syncActionButtons(): void {\n const empty = this.markNodes.length === 0;\n if (this.undoBtn) this.undoBtn.disabled = empty;\n if (this.clearBtn) this.clearBtn.disabled = empty;\n }\n\n // --------------------------------------------------------------------------\n // Pointer / drawing\n // --------------------------------------------------------------------------\n\n private toDoc(e: PointerEvent): Point {\n return {\n x: e.clientX + (window.scrollX || window.pageXOffset || 0),\n y: e.clientY + (window.scrollY || window.pageYOffset || 0),\n };\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this.active) return;\n if (e.button !== undefined && e.button !== 0) return; // primary button only\n e.preventDefault();\n const p = this.toDoc(e);\n const tool = this.tool;\n\n if (tool === 'text') {\n this.openTextInput(e.clientX, e.clientY, p);\n return;\n }\n if (tool === 'step') {\n this.placeStep(p);\n return;\n }\n\n const color = this.color;\n const width = this.width;\n let drag: DragState;\n\n if (tool === 'pencil' || tool === 'highlighter') {\n const poly = this.svgEl('polyline', {\n 'data-lens-draft': '1',\n fill: 'none',\n stroke: color,\n 'stroke-width': tool === 'highlighter' ? HIGHLIGHTER_WIDTH : width,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n ...(tool === 'highlighter' ? { 'stroke-opacity': '0.35' } : {}),\n points: `${p.x},${p.y}`,\n });\n this.svg!.append(poly);\n drag = { tool, color, width, start: p, node: poly, points: [p], last: p };\n } else if (tool === 'arrow') {\n const g = this.svgEl('g', { 'data-lens-draft': '1' });\n const line = this.svgEl('line', {\n stroke: color,\n 'stroke-width': width,\n 'stroke-linecap': 'round',\n });\n const head = this.svgEl('polygon', { fill: color });\n g.append(line, head);\n this.svg!.append(g);\n drag = { tool, color, width, start: p, node: g, line, head };\n this.updateArrow(drag, p);\n } else {\n const node = this.createShapeNode(tool, color, width);\n this.svg!.append(node);\n drag = { tool, color, width, start: p, node };\n this.updateShape(drag, p);\n }\n\n this.drag = drag;\n window.addEventListener('pointermove', this.onPointerMove, true);\n window.addEventListener('pointerup', this.onPointerUp, true);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n const d = this.drag;\n if (!d) return;\n const p = this.toDoc(e);\n if (d.tool === 'pencil' || d.tool === 'highlighter') {\n const pts = d.points!;\n if (d.last && shouldKeepPoint(d.last, p) && pts.length < MAX_POINTS) {\n pts.push(p);\n d.last = p;\n d.node.setAttribute('points', this.pointsAttr(pts));\n }\n } else if (d.tool === 'arrow') {\n this.updateArrow(d, p);\n } else {\n this.updateShape(d, p);\n }\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n const d = this.drag;\n this.detachDragListeners();\n this.drag = null;\n if (!d) return;\n const p = this.toDoc(e);\n let annotation: Annotation | null = null;\n\n if (d.tool === 'pencil' || d.tool === 'highlighter') {\n let pts = d.points!;\n if (pts.length >= 2) pts = simplifyPoints(pts, 1);\n if (pts.length < 2) {\n d.node.remove();\n return;\n }\n d.node.setAttribute('points', this.pointsAttr(pts));\n annotation =\n d.tool === 'pencil'\n ? { kind: 'pencil', points: pts, color: d.color, strokeWidth: d.width, id: this.nextId() }\n : {\n kind: 'highlighter',\n points: pts,\n color: d.color,\n strokeWidth: HIGHLIGHTER_WIDTH,\n id: this.nextId(),\n };\n } else if (d.tool === 'arrow' || d.tool === 'line') {\n if (distance(d.start, p) < MIN_DRAG) {\n d.node.remove();\n return;\n }\n if (d.tool === 'arrow') {\n this.updateArrow(d, p);\n annotation = {\n kind: 'arrow',\n x1: d.start.x,\n y1: d.start.y,\n x2: p.x,\n y2: p.y,\n color: d.color,\n strokeWidth: d.width,\n id: this.nextId(),\n };\n } else {\n this.updateShape(d, p);\n annotation = {\n kind: 'line',\n x1: d.start.x,\n y1: d.start.y,\n x2: p.x,\n y2: p.y,\n color: d.color,\n strokeWidth: d.width,\n id: this.nextId(),\n };\n }\n } else {\n const x = Math.min(d.start.x, p.x);\n const y = Math.min(d.start.y, p.y);\n const width = Math.abs(p.x - d.start.x);\n const height = Math.abs(p.y - d.start.y);\n if (width < MIN_DRAG || height < MIN_DRAG) {\n d.node.remove();\n return;\n }\n this.updateShape(d, p);\n if (d.tool === 'rect') {\n annotation = {\n kind: 'rect',\n x,\n y,\n width,\n height,\n color: d.color,\n strokeWidth: d.width,\n id: this.nextId(),\n };\n } else if (d.tool === 'ellipse') {\n annotation = {\n kind: 'ellipse',\n x,\n y,\n width,\n height,\n color: d.color,\n strokeWidth: d.width,\n id: this.nextId(),\n };\n } else {\n // blur ignores color/width\n annotation = { kind: 'blur', x, y, width, height, id: this.nextId() };\n }\n }\n\n d.node.removeAttribute('data-lens-draft');\n this.commitMark(annotation, d.node);\n };\n\n private detachDragListeners(): void {\n window.removeEventListener('pointermove', this.onPointerMove, true);\n window.removeEventListener('pointerup', this.onPointerUp, true);\n }\n\n private commitMark(annotation: Annotation, node: SVGElement): void {\n this.annotations.push(annotation);\n this.markNodes.push(node);\n this.syncActionButtons();\n }\n\n private createShapeNode(tool: Tool, color: string, width: number): SVGElement {\n if (tool === 'ellipse') {\n return this.svgEl('ellipse', {\n 'data-lens-draft': '1',\n fill: 'none',\n stroke: color,\n 'stroke-width': width,\n });\n }\n if (tool === 'line') {\n return this.svgEl('line', {\n 'data-lens-draft': '1',\n stroke: color,\n 'stroke-width': width,\n 'stroke-linecap': 'round',\n });\n }\n if (tool === 'blur') {\n return this.svgEl('rect', {\n 'data-lens-draft': '1',\n 'data-lens-blur': '1',\n fill: 'url(#lens-blur-hatch)',\n stroke: '#111827',\n 'stroke-width': 1,\n 'stroke-dasharray': '4 3',\n });\n }\n // rect\n return this.svgEl('rect', {\n 'data-lens-draft': '1',\n fill: 'none',\n stroke: color,\n 'stroke-width': width,\n rx: 2,\n });\n }\n\n private updateShape(d: DragState, cur: Point): void {\n const x = Math.min(d.start.x, cur.x);\n const y = Math.min(d.start.y, cur.y);\n const w = Math.abs(cur.x - d.start.x);\n const h = Math.abs(cur.y - d.start.y);\n const node = d.node;\n if (d.tool === 'ellipse') {\n node.setAttribute('cx', String(x + w / 2));\n node.setAttribute('cy', String(y + h / 2));\n node.setAttribute('rx', String(w / 2));\n node.setAttribute('ry', String(h / 2));\n } else if (d.tool === 'line') {\n node.setAttribute('x1', String(d.start.x));\n node.setAttribute('y1', String(d.start.y));\n node.setAttribute('x2', String(cur.x));\n node.setAttribute('y2', String(cur.y));\n } else {\n // rect / blur\n node.setAttribute('x', String(x));\n node.setAttribute('y', String(y));\n node.setAttribute('width', String(w));\n node.setAttribute('height', String(h));\n }\n }\n\n private updateArrow(d: DragState, cur: Point): void {\n if (!d.line || !d.head) return;\n d.line.setAttribute('x1', String(d.start.x));\n d.line.setAttribute('y1', String(d.start.y));\n d.line.setAttribute('x2', String(cur.x));\n d.line.setAttribute('y2', String(cur.y));\n const size = Math.max(12, d.width * 3);\n const poly = arrowheadPolygon(d.start.x, d.start.y, cur.x, cur.y, size);\n d.head.setAttribute('points', this.pointsAttr(poly));\n }\n\n // --------------------------------------------------------------------------\n // Text tool\n // --------------------------------------------------------------------------\n\n private openTextInput(clientX: number, clientY: number, docPoint: Point): void {\n this.commitTextInput();\n const input = el('input', {\n class: 'lens-text-input',\n attrs: { type: 'text', 'aria-label': 'Annotation text' },\n style: { left: `${clientX}px`, top: `${clientY}px`, color: this.color },\n });\n input.addEventListener('blur', () => this.commitTextInput());\n this.host.append(input);\n this.textInputEl = input;\n this.textAnchor = docPoint;\n this.textColor = this.color;\n input.focus();\n }\n\n private commitTextInput(): void {\n const input = this.textInputEl;\n const anchor = this.textAnchor;\n if (!input || !anchor) return;\n const value = input.value.trim();\n this.textInputEl = null;\n this.textAnchor = null;\n input.remove();\n if (!value) return;\n const node = this.svgEl('text', {\n x: anchor.x,\n y: anchor.y,\n fill: this.textColor,\n 'font-size': 16,\n 'font-family': FONT,\n 'dominant-baseline': 'hanging',\n });\n node.textContent = value;\n this.svg!.append(node);\n this.commitMark(\n {\n kind: 'text',\n x: anchor.x,\n y: anchor.y,\n text: value,\n fontSize: 16,\n color: this.textColor,\n id: this.nextId(),\n },\n node,\n );\n }\n\n private cancelTextInput(): void {\n if (!this.textInputEl) return;\n this.textInputEl.remove();\n this.textInputEl = null;\n this.textAnchor = null;\n }\n\n // --------------------------------------------------------------------------\n // Step tool\n // --------------------------------------------------------------------------\n\n private placeStep(p: Point): void {\n const n = ++this.stepCounter;\n const g = this.svgEl('g', {});\n const circle = this.svgEl('circle', {\n cx: p.x,\n cy: p.y,\n r: STEP_RADIUS,\n fill: this.color,\n });\n const text = this.svgEl('text', {\n x: p.x,\n y: p.y,\n fill: '#ffffff',\n 'font-size': 13,\n 'font-weight': 700,\n 'font-family': FONT,\n 'text-anchor': 'middle',\n 'dominant-baseline': 'central',\n });\n text.textContent = String(n);\n g.append(circle, text);\n this.svg!.append(g);\n this.commitMark({ kind: 'step', x: p.x, y: p.y, n, color: this.color, id: this.nextId() }, g);\n }\n\n // --------------------------------------------------------------------------\n // Keyboard\n // --------------------------------------------------------------------------\n\n private onKey = (e: KeyboardEvent): void => {\n if (this.textInputEl) {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n this.cancelTextInput();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n this.commitTextInput();\n }\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n this.exit();\n }\n };\n\n // --------------------------------------------------------------------------\n // Small helpers\n // --------------------------------------------------------------------------\n\n private svgEl(tag: string, attrs: Record<string, string | number>): SVGElement {\n const node = document.createElementNS(SVG_NS, tag) as SVGElement;\n for (const [k, v] of Object.entries(attrs)) node.setAttribute(k, String(v));\n return node;\n }\n\n private pointsAttr(points: Point[]): string {\n return points.map((p) => `${p.x},${p.y}`).join(' ');\n }\n\n private nextId(): string {\n return `lens-${++this.idSeq}`;\n }\n}\n","import type { TargetElement } from '@horus-lens/shared';\nimport { clear, el } from './dom.js';\nimport { iconAnnotate, iconCheck, iconClose, iconCopy, iconRecord, iconSend } from './icons.js';\nimport type { IncludeKey, IncludeState, OverlayStats, SubmitReportIncludes } from './types.js';\n\nexport interface PanelCallbacks {\n getStats: () => OverlayStats;\n getTarget: () => TargetElement | null;\n getAnnotationCount: () => number;\n /** Duration of a retained \"record steps\" recording, or `null` if none. */\n getRecording: () => { durationMs: number } | null;\n onRemoveTarget: () => void;\n onMarkArea: () => void;\n onRecordSteps: () => void;\n onDiscardRecording: () => void;\n onClose: () => void;\n onSubmit: (comment: string, include: SubmitReportIncludes) => Promise<{ reportId: string }>;\n}\n\n/** Include toggles rendered (in order) in the \"Include:\" row. All default ON. */\nconst INCLUDE_ITEMS: ReadonlyArray<{ key: IncludeKey; label: string }> = [\n { key: 'replay', label: 'Replay' },\n { key: 'console', label: 'Console' },\n { key: 'network', label: 'Network' },\n { key: 'errors', label: 'Errors' },\n { key: 'screenshot', label: 'Screenshot' },\n];\n\n/** The bottom-right report card: compose, submit, success / error states. */\nexport class Panel {\n readonly root: HTMLElement;\n private body: HTMLElement;\n private textarea!: HTMLTextAreaElement;\n private submitBtn!: HTMLButtonElement;\n private autoCloseTimer: ReturnType<typeof setTimeout> | null = null;\n private submitting = false;\n /** Selected capture toggles; every flag starts ON. Persists across refresh. */\n private readonly include: IncludeState = {\n replay: true,\n console: true,\n network: true,\n errors: true,\n screenshot: true,\n };\n\n constructor(private readonly cb: PanelCallbacks) {\n this.body = el('div', { class: 'lens-panel__body' });\n this.root = el('div', { class: 'lens-panel', attrs: { role: 'dialog', 'aria-label': 'Report an issue' } }, [\n el('div', { class: 'lens-panel__head' }, [\n el('div', { class: 'lens-panel__title', text: 'Report an issue' }),\n el('button', {\n class: 'lens-panel__x',\n ariaLabel: 'Close',\n html: iconClose,\n on: { click: () => this.cb.onClose() },\n }),\n ]),\n this.body,\n ]);\n this.renderForm();\n }\n\n /** Re-render the compose view (chips reflect latest target / annotations). */\n refresh(): void {\n if (!this.submitting) this.renderForm();\n }\n\n focus(): void {\n this.textarea?.focus();\n }\n\n destroy(): void {\n if (this.autoCloseTimer) clearTimeout(this.autoCloseTimer);\n this.root.remove();\n }\n\n private renderForm(): void {\n const prior = this.textarea?.value ?? '';\n clear(this.body);\n\n this.textarea = el('textarea', {\n class: 'lens-textarea',\n placeholder: \"What's wrong? Describe the issue…\",\n ariaLabel: 'Issue description',\n });\n this.textarea.value = prior;\n\n this.body.append(\n this.textarea,\n this.buildContext(),\n this.buildIncludes(),\n this.buildChips(),\n this.buildActions(),\n );\n }\n\n /** Static, non-interactive page context: route · browser · os · viewport. */\n private buildContext(): HTMLElement {\n const s = this.cb.getStats();\n const parts = [\n truncate(s.route || s.url, 40),\n `${s.browser} · ${s.os}`,\n `${s.viewport.width}×${s.viewport.height}`,\n ];\n const nodes: (HTMLElement | string)[] = [];\n parts.forEach((part, i) => {\n if (i > 0) nodes.push(el('span', { class: 'lens-context__dot', text: '·' }));\n nodes.push(el('span', { class: 'lens-context__item', text: part }));\n });\n return el('div', { class: 'lens-context', title: s.url }, nodes);\n }\n\n /** Real toggles (\"switch\"): which captured data to attach. All ON by default. */\n private buildIncludes(): HTMLElement {\n const s = this.cb.getStats();\n const counts: Partial<Record<IncludeKey, number | null>> = {\n console: s.console,\n network: s.network,\n errors: s.errors,\n };\n const toggles = INCLUDE_ITEMS.map((item) => this.buildToggle(item.key, item.label, counts[item.key]));\n return el('div', { class: 'lens-includes' }, [\n el('span', { class: 'lens-includes__label', text: 'Include:' }),\n ...toggles,\n ]);\n }\n\n private buildToggle(key: IncludeKey, label: string, count?: number | null): HTMLButtonElement {\n const on = this.include[key];\n const btn = el('button', {\n class: `lens-tgl${on ? ' is-on' : ''}`,\n attrs: { type: 'button', role: 'switch', 'aria-checked': String(on) },\n html: `<span class=\"lens-tgl__check\" aria-hidden=\"true\">${iconCheck}</span>`,\n });\n btn.append(el('span', { class: 'lens-tgl__label', text: label }));\n if (typeof count === 'number' && count > 0) {\n btn.append(el('span', { class: 'lens-tgl__count', text: String(count) }));\n }\n btn.addEventListener('click', () => {\n const next = !this.include[key];\n this.include[key] = next;\n btn.classList.toggle('is-on', next);\n btn.setAttribute('aria-checked', String(next));\n });\n return btn;\n }\n\n /** Removable context chips: annotations, retained recording, picked element. */\n private buildChips(): HTMLElement {\n const row = el('div', { class: 'lens-chips' });\n\n const annCount = this.cb.getAnnotationCount();\n if (annCount > 0) {\n row.append(chip(`${annCount} annotation${annCount === 1 ? '' : 's'}`));\n }\n\n const recording = this.cb.getRecording();\n if (recording) {\n const recChip = el('span', { class: 'lens-chip lens-chip--ok lens-chip--rec' }, [\n el('span', { text: `recording ✓ ${formatDuration(recording.durationMs)}` }),\n el('button', {\n class: 'lens-chip__x',\n ariaLabel: 'Discard recording',\n text: '×',\n on: { click: () => this.cb.onDiscardRecording() },\n }),\n ]);\n row.append(recChip);\n }\n\n const target = this.cb.getTarget();\n if (target) {\n const label = target.domPath || target.tagName || 'element';\n const targetChip = el('span', { class: 'lens-chip lens-chip--target', title: label }, [\n el('span', { class: 'lens-chip__code', text: truncate(label, 40) }),\n el('button', {\n class: 'lens-chip__x',\n ariaLabel: 'Remove element',\n text: '×',\n on: { click: () => this.cb.onRemoveTarget() },\n }),\n ]);\n row.append(targetChip);\n }\n\n // Collapse to nothing when empty so the section gap doesn't leave a void.\n row.style.display = row.childElementCount > 0 ? '' : 'none';\n return row;\n }\n\n private buildActions(): HTMLElement {\n const mark = el('button', {\n class: 'lens-abtn lens-abtn--ghost lens-abtn--compact',\n html: iconAnnotate + '<span>Annotate</span>',\n on: { click: () => this.cb.onMarkArea() },\n });\n const record = el('button', {\n class: 'lens-abtn lens-abtn--ghost lens-abtn--compact',\n html: iconRecord + '<span>Record steps</span>',\n on: { click: () => this.cb.onRecordSteps() },\n });\n const cancel = el('button', {\n class: 'lens-abtn lens-abtn--ghost',\n text: 'Cancel',\n on: { click: () => this.cb.onClose() },\n });\n this.submitBtn = el('button', {\n class: 'lens-abtn lens-abtn--primary lens-abtn--submit',\n html: iconSend + '<span>Submit</span>',\n on: { click: () => void this.submit() },\n });\n return el('div', { class: 'lens-actions' }, [\n el('div', { class: 'lens-actions__row lens-actions__secondary' }, [mark, record]),\n el('div', { class: 'lens-actions__row lens-actions__primary' }, [cancel, this.submitBtn]),\n ]);\n }\n\n private async submit(): Promise<void> {\n if (this.submitting) return;\n const comment = this.textarea.value.trim();\n this.submitting = true;\n this.submitBtn.disabled = true;\n this.submitBtn.innerHTML = '<span>Submitting…</span>';\n try {\n const { reportId } = await this.cb.onSubmit(comment, { ...this.include });\n this.renderSuccess(reportId);\n } catch (err) {\n this.renderError(err instanceof Error ? err.message : 'Something went wrong');\n } finally {\n this.submitting = false;\n }\n }\n\n private renderSuccess(reportId: string): void {\n clear(this.body);\n const idPill = el('div', { class: 'lens-idpill' }, [\n el('span', { text: reportId }),\n el('button', {\n ariaLabel: 'Copy report id',\n html: iconCopy,\n on: {\n click: (e) => {\n const btn = e.currentTarget as HTMLButtonElement;\n void copy(reportId).then(() => {\n btn.innerHTML = iconCheck;\n setTimeout(() => (btn.innerHTML = iconCopy), 1200);\n });\n },\n },\n }),\n ]);\n this.body.append(\n el('div', { class: 'lens-state' }, [\n el('div', { class: 'lens-state__badge lens-state__badge--ok', html: iconCheck }),\n el('div', { class: 'lens-state__title', text: 'Report submitted' }),\n el('div', { class: 'lens-state__msg', text: 'Thanks — the team can see the full context.' }),\n idPill,\n ]),\n );\n this.autoCloseTimer = setTimeout(() => this.cb.onClose(), 2500);\n }\n\n private renderError(message: string): void {\n clear(this.body);\n this.body.append(\n el('div', { class: 'lens-state' }, [\n el('div', { class: 'lens-state__badge lens-state__badge--err', html: iconClose }),\n el('div', { class: 'lens-state__title', text: 'Submission failed' }),\n el('div', { class: 'lens-state__msg', text: truncate(message, 120) }),\n el('div', { class: 'lens-actions' }, [\n el('button', {\n class: 'lens-abtn lens-abtn--ghost',\n text: 'Cancel',\n on: { click: () => this.cb.onClose() },\n }),\n el('button', {\n class: 'lens-abtn lens-abtn--primary',\n text: 'Retry',\n on: { click: () => this.renderForm() },\n }),\n ]),\n ]),\n );\n }\n}\n\nfunction chip(text: string, title?: string, extra?: string): HTMLElement {\n return el('span', { class: `lens-chip${extra ? ' ' + extra : ''}`, text, title: title ?? text });\n}\n\nfunction truncate(value: string, max: number): string {\n return value.length > max ? value.slice(0, max - 1) + '…' : value;\n}\n\n/** Format milliseconds as `m:ss` (e.g. 42000 → \"0:42\"). */\nexport function formatDuration(ms: number): string {\n const total = Math.max(0, Math.round(ms / 1000));\n const m = Math.floor(total / 60);\n const s = total % 60;\n return `${m}:${s.toString().padStart(2, '0')}`;\n}\n\nasync function copy(text: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n /* clipboard blocked — silently ignore */\n }\n}\n","import { el } from './dom.js';\n\n/**\n * Element picker. Highlights an element with a fixed overlay box (never mutates\n * host element styles) and resolves the chosen element. Events originating\n * inside the overlay's own shadow tree are ignored so the pill / panel stay\n * interactive.\n *\n * Pointer-based so it works with mouse, pen and touch:\n * - Fine pointers (mouse/pen): hover highlights; a click confirms.\n * - Coarse pointers (touch): no hover, so the first tap highlights the element\n * under the finger, a second tap on the *same* element confirms, and a tap\n * elsewhere moves the highlight. A floating \"Tap an element — Cancel\" chip is\n * shown since mobile has no Escape key. Escape still cancels on desktop.\n */\nexport class ElementPicker {\n private highlight: HTMLElement;\n private tag: HTMLElement;\n private hint: HTMLElement;\n private current: Element | null = null;\n private active = false;\n private onPick: ((elem: Element) => void) | null = null;\n private onCancel: (() => void) | null = null;\n\n constructor(\n private readonly layer: HTMLElement,\n private readonly rootHost: HTMLElement,\n ) {\n this.tag = el('div', { class: 'lens-highlight__tag' });\n this.highlight = el('div', { class: 'lens-highlight' }, [this.tag]);\n this.hint = el('div', { class: 'lens-pick-chip' }, [\n el('span', { class: 'lens-pick-chip__label', text: 'Tap an element' }),\n el('button', {\n class: 'lens-pick-chip__btn',\n text: 'Cancel',\n on: { click: () => this.cancel() },\n }),\n ]);\n this.layer.append(this.highlight, this.hint);\n this.hide();\n }\n\n get isActive(): boolean {\n return this.active;\n }\n\n start(onPick: (elem: Element) => void, onCancel: () => void): void {\n if (this.active) return;\n this.active = true;\n this.onPick = onPick;\n this.onCancel = onCancel;\n this.current = null;\n this.hint.style.display = '';\n window.addEventListener('pointermove', this.onMove, true);\n window.addEventListener('pointerdown', this.onDown, true);\n window.addEventListener('pointerup', this.onUp, true);\n window.addEventListener('click', this.onClick, true);\n window.addEventListener('keydown', this.onKey, true);\n }\n\n stop(): void {\n if (!this.active) return;\n this.active = false;\n this.current = null;\n this.onPick = null;\n this.onCancel = null;\n this.hide();\n window.removeEventListener('pointermove', this.onMove, true);\n window.removeEventListener('pointerdown', this.onDown, true);\n window.removeEventListener('pointerup', this.onUp, true);\n window.removeEventListener('click', this.onClick, true);\n window.removeEventListener('keydown', this.onKey, true);\n }\n\n private cancel(): void {\n const cancel = this.onCancel;\n this.stop();\n cancel?.();\n }\n\n private hide(): void {\n this.highlight.style.display = 'none';\n this.hint.style.display = 'none';\n }\n\n private isOverlayEvent(e: Event): boolean {\n return e.composedPath().includes(this.rootHost);\n }\n\n private isCoarse(): boolean {\n return typeof window.matchMedia === 'function' && window.matchMedia('(pointer: coarse)').matches;\n }\n\n private elementAt(x: number, y: number): Element | null {\n const found = document.elementFromPoint(x, y);\n if (!found || found === this.rootHost) return null;\n return found;\n }\n\n private highlightElement(target: Element): void {\n this.current = target;\n const rect = target.getBoundingClientRect();\n Object.assign(this.highlight.style, {\n display: 'block',\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n this.tag.textContent = describe(target);\n }\n\n private confirm(target: Element): void {\n const pick = this.onPick;\n // The browser dispatches `click` AFTER pointerup — by then stop() has\n // removed our click suppressor, so a picked link/button would fire its own\n // action. Swallow exactly one trailing click before handing over.\n this.suppressNextClick();\n this.stop();\n pick?.(target);\n }\n\n private suppressNextClick(): void {\n const swallow = (e: MouseEvent): void => {\n e.preventDefault();\n e.stopImmediatePropagation();\n cleanup();\n };\n const cleanup = (): void => {\n window.removeEventListener('click', swallow, true);\n clearTimeout(timer);\n };\n window.addEventListener('click', swallow, { capture: true });\n // Safety: if no click arrives (e.g. keyboard-driven pick), don't leak the\n // suppressor into the next real interaction.\n const timer = setTimeout(cleanup, 500);\n }\n\n private onMove = (e: PointerEvent): void => {\n if (this.isOverlayEvent(e)) return;\n // On coarse pointers there is no hover; highlight is driven by taps instead.\n if (this.isCoarse()) return;\n const target = this.elementAt(e.clientX, e.clientY);\n if (!target || target === this.current) return;\n this.highlightElement(target);\n };\n\n private onDown = (e: PointerEvent): void => {\n if (this.isOverlayEvent(e)) return;\n // Block the underlying page from reacting to the press.\n e.preventDefault();\n e.stopImmediatePropagation();\n };\n\n private onUp = (e: PointerEvent): void => {\n if (this.isOverlayEvent(e)) return;\n e.preventDefault();\n e.stopImmediatePropagation();\n const target = this.elementAt(e.clientX, e.clientY);\n if (this.isCoarse()) {\n // Two-tap: first tap (or a tap on a different element) highlights; a\n // second tap on the same element confirms.\n if (target && target === this.current) {\n this.confirm(target);\n } else if (target) {\n this.highlightElement(target);\n }\n return;\n }\n const chosen = target ?? this.current;\n if (chosen) this.confirm(chosen);\n };\n\n private onClick = (e: MouseEvent): void => {\n if (this.isOverlayEvent(e)) return;\n // Swallow the synthetic click so links / buttons don't navigate.\n e.preventDefault();\n e.stopImmediatePropagation();\n };\n\n private onKey = (e: KeyboardEvent): void => {\n if (e.key !== 'Escape') return;\n e.preventDefault();\n e.stopPropagation();\n this.cancel();\n };\n}\n\nfunction describe(elem: Element): string {\n const tag = elem.tagName.toLowerCase();\n const id = elem.id ? `#${elem.id}` : '';\n const cls =\n typeof elem.className === 'string' && elem.className.trim()\n ? '.' + elem.className.trim().split(/\\s+/).slice(0, 2).join('.')\n : '';\n return `${tag}${id}${cls}`;\n}\n","/**\n * Overlay stylesheet, injected once into the shadow root. Scoped by `:host`\n * with `all: initial` so no host-page CSS can leak in and nothing here leaks\n * out. Dark, glassy pill; a light-aware panel that respects prefers-color-scheme;\n * an 8px radius/spacing grid and 150ms transitions throughout.\n */\nexport const OVERLAY_CSS = /* css */ `\n:host {\n all: initial;\n --lens-accent: #6366f1;\n --lens-accent-strong: #4f46e5;\n --lens-radius: 8px;\n --lens-font: system-ui, -apple-system, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n --lens-z: 2147483000;\n font-family: var(--lens-font);\n line-height: 1.4;\n}\n\n*, *::before, *::after { box-sizing: border-box; }\n\n.lens-layer {\n position: fixed;\n inset: 0;\n z-index: var(--lens-z);\n pointer-events: none;\n font-family: var(--lens-font);\n}\n.lens-layer > * { pointer-events: auto; }\n\n/* ---------------- Pill ---------------- */\n.lens-pill {\n position: fixed;\n bottom: calc(12px + env(safe-area-inset-bottom));\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100vw - 16px);\n flex-wrap: wrap;\n justify-content: center;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px;\n border-radius: 999px;\n background: rgba(20, 20, 23, 0.82);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n backdrop-filter: blur(12px) saturate(180%);\n border: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.06);\n color: #f4f4f5;\n user-select: none;\n transition: opacity 150ms ease, transform 150ms ease;\n}\n.lens-pill__dot {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n margin-left: 4px;\n border-radius: 999px;\n color: #a5b4fc;\n}\n.lens-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 30px;\n padding: 0 12px;\n border: 0;\n border-radius: 999px;\n background: transparent;\n color: #e4e4e7;\n font-family: var(--lens-font);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: background 150ms ease, color 150ms ease;\n}\n.lens-btn:hover { background: rgba(255, 255, 255, 0.1); }\n.lens-btn:focus-visible { outline: 2px solid var(--lens-accent); outline-offset: 1px; }\n.lens-btn--primary { background: var(--lens-accent); color: #fff; }\n.lens-btn--primary:hover { background: var(--lens-accent-strong); }\n.lens-btn--icon { width: 30px; padding: 0; justify-content: center; }\n.lens-btn--icon.is-active { background: var(--lens-accent); color: #fff; }\n.lens-pill__sep {\n width: 1px;\n height: 18px;\n background: rgba(255, 255, 255, 0.14);\n margin: 0 2px;\n}\n\n/* ---------------- Picker highlight ---------------- */\n.lens-highlight {\n position: fixed;\n z-index: calc(var(--lens-z) - 2);\n pointer-events: none;\n border: 2px solid var(--lens-accent);\n background: rgba(99, 102, 241, 0.14);\n border-radius: 3px;\n transition: all 60ms linear;\n display: none;\n}\n.lens-highlight__tag {\n position: absolute;\n top: -22px;\n left: -2px;\n padding: 1px 6px;\n border-radius: 4px;\n background: var(--lens-accent);\n color: #fff;\n font: 500 11px/1.5 var(--lens-font);\n white-space: nowrap;\n}\n.lens-hint {\n position: fixed;\n bottom: 64px;\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 12px;\n border-radius: 999px;\n background: rgba(20, 20, 23, 0.9);\n color: #e4e4e7;\n font-size: 12px;\n font-weight: 500;\n border: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);\n pointer-events: none;\n}\n\n/* ---------------- Annotation SVG layer ---------------- */\n/* One full-DOCUMENT SVG anchored to page content (translated by -scroll so\n marks survive scrolling). pointer-events flip to auto only while drawing. */\n.lens-annotate-svg {\n position: absolute;\n left: 0;\n top: 0;\n z-index: calc(var(--lens-z) - 1);\n pointer-events: none;\n overflow: visible;\n}\n\n/* Floating text-entry input for the Text tool (viewport-positioned). */\n.lens-text-input {\n position: fixed;\n z-index: var(--lens-z);\n min-width: 120px;\n padding: 2px 6px;\n border: 1px solid var(--lens-accent);\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.96);\n color: #111827;\n font-family: var(--lens-font);\n font-size: 15px;\n line-height: 1.3;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n outline: none;\n}\n\n/* ---------------- Panel ---------------- */\n.lens-panel {\n position: fixed;\n right: 20px;\n bottom: 64px;\n width: min(520px, calc(100vw - 40px));\n max-width: 520px;\n max-height: calc(100vh - 96px);\n display: flex;\n flex-direction: column;\n border-radius: 14px;\n background: #ffffff;\n color: #18181b;\n border: 1px solid rgba(0, 0, 0, 0.08);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22), 0 2px 8px rgba(0, 0, 0, 0.08);\n overflow: hidden;\n transform-origin: bottom right;\n animation: lens-in 150ms ease;\n}\n@keyframes lens-in {\n from { opacity: 0; transform: translateY(6px) scale(0.98); }\n to { opacity: 1; transform: none; }\n}\n.lens-panel__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid rgba(0, 0, 0, 0.07);\n}\n.lens-panel__title { font-size: 14px; font-weight: 600; }\n.lens-panel__x {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: #52525b;\n cursor: pointer;\n transition: background 150ms ease;\n}\n.lens-panel__x:hover { background: rgba(0, 0, 0, 0.06); }\n.lens-panel__body {\n padding: 14px 16px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.lens-textarea {\n width: 100%;\n min-height: 120px;\n resize: vertical;\n padding: 10px 12px;\n border-radius: var(--lens-radius);\n border: 1px solid rgba(0, 0, 0, 0.14);\n background: #fafafa;\n color: inherit;\n font-family: var(--lens-font);\n font-size: 13px;\n transition: border-color 150ms ease, box-shadow 150ms ease;\n}\n.lens-textarea:focus {\n outline: none;\n border-color: var(--lens-accent);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.18);\n}\n/* ---- Context row: static, non-interactive page facts (muted, dot-joined) ---- */\n.lens-context {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-size: 11.5px;\n line-height: 1.4;\n color: #71717a;\n}\n.lens-context__item { white-space: nowrap; }\n.lens-context__dot { opacity: 0.55; }\n\n/* ---- Include row: real toggles (role=switch) for which data to attach ---- */\n.lens-includes {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n}\n.lens-includes__label {\n font-size: 11.5px;\n font-weight: 600;\n color: #71717a;\n margin-right: 2px;\n}\n.lens-tgl {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border-radius: 999px;\n border: 1px solid rgba(0, 0, 0, 0.14);\n background: #fafafa;\n color: #a1a1aa;\n font-family: var(--lens-font);\n font-size: 11.5px;\n font-weight: 600;\n white-space: nowrap;\n cursor: pointer;\n opacity: 0.75;\n transition: background 150ms ease, border-color 150ms ease, color 150ms ease, opacity 150ms ease;\n}\n.lens-tgl:hover { opacity: 1; }\n.lens-tgl:focus-visible { outline: 2px solid var(--lens-accent); outline-offset: 1px; }\n.lens-tgl__check { display: none; align-items: center; }\n.lens-tgl__check svg { width: 13px; height: 13px; }\n.lens-tgl__count { font-weight: 500; opacity: 0.75; font-variant-numeric: tabular-nums; }\n.lens-tgl.is-on {\n opacity: 1;\n color: var(--lens-accent-strong);\n border-color: rgba(99, 102, 241, 0.5);\n background: #eef2ff;\n}\n.lens-tgl.is-on .lens-tgl__check { display: inline-flex; }\n\n.lens-chips { display: flex; flex-wrap: wrap; gap: 6px; }\n.lens-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n max-width: 100%;\n padding: 3px 9px;\n border-radius: 999px;\n background: #f4f4f5;\n border: 1px solid rgba(0, 0, 0, 0.06);\n color: #3f3f46;\n font-size: 11.5px;\n font-weight: 500;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.lens-chip--ok { color: #15803d; background: #f0fdf4; border-color: rgba(21, 128, 61, 0.18); }\n.lens-chip--target {\n max-width: 100%;\n background: #eef2ff;\n border-color: rgba(99, 102, 241, 0.25);\n color: var(--lens-accent-strong);\n}\n.lens-chip__code {\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.lens-chip__x {\n display: inline-flex;\n border: 0;\n background: transparent;\n color: inherit;\n cursor: pointer;\n padding: 0;\n opacity: 0.7;\n font-size: 13px;\n line-height: 1;\n}\n.lens-chip__x:hover { opacity: 1; }\n/* ---- Actions: secondary row (mark / record) then primary row (cancel / submit) ---- */\n.lens-actions { display: flex; flex-direction: column; gap: 8px; }\n.lens-actions__row { display: flex; align-items: center; gap: 8px; }\n/* Mark area / Record steps split the row evenly, one line, never wrap. */\n.lens-actions__secondary .lens-abtn { flex: 1; min-width: 0; justify-content: center; }\n/* Submit always fills remaining width; Cancel stays intrinsic. */\n.lens-actions__primary .lens-abtn--submit { flex: 1; }\n.lens-abtn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 34px;\n padding: 0 14px;\n border-radius: var(--lens-radius);\n border: 1px solid transparent;\n font-family: var(--lens-font);\n font-size: 13px;\n font-weight: 600;\n white-space: nowrap;\n cursor: pointer;\n transition: background 150ms ease, border-color 150ms ease, opacity 150ms ease;\n}\n.lens-abtn span { white-space: nowrap; }\n.lens-abtn--compact { padding: 0 10px; font-size: 12px; }\n.lens-abtn svg { flex: none; }\n.lens-abtn--ghost { background: transparent; border-color: rgba(0, 0, 0, 0.14); color: #3f3f46; }\n.lens-abtn--ghost:hover { background: rgba(0, 0, 0, 0.04); }\n.lens-abtn--primary { background: var(--lens-accent); color: #fff; }\n.lens-abtn--primary:hover { background: var(--lens-accent-strong); }\n.lens-abtn:disabled { opacity: 0.55; cursor: default; }\n.lens-abtn:focus-visible { outline: 2px solid var(--lens-accent); outline-offset: 1px; }\n\n.lens-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 10px;\n padding: 26px 18px;\n text-align: center;\n}\n.lens-state__badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n border-radius: 999px;\n}\n.lens-state__badge--ok { background: #dcfce7; color: #16a34a; }\n.lens-state__badge--err { background: #fee2e2; color: #dc2626; }\n.lens-state__title { font-size: 14px; font-weight: 600; }\n.lens-state__msg { font-size: 12.5px; color: #52525b; }\n.lens-idpill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border-radius: 8px;\n background: #f4f4f5;\n border: 1px solid rgba(0, 0, 0, 0.08);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n}\n.lens-idpill button {\n border: 0;\n background: transparent;\n color: #52525b;\n cursor: pointer;\n display: inline-flex;\n padding: 2px;\n border-radius: 4px;\n}\n.lens-idpill button:hover { background: rgba(0, 0, 0, 0.06); color: #18181b; }\n\n@media (prefers-color-scheme: dark) {\n .lens-panel { background: #1c1c1f; color: #f4f4f5; border-color: rgba(255, 255, 255, 0.1); }\n .lens-panel__head { border-bottom-color: rgba(255, 255, 255, 0.08); }\n .lens-panel__x { color: #a1a1aa; }\n .lens-panel__x:hover { background: rgba(255, 255, 255, 0.08); }\n .lens-textarea { background: #26262a; border-color: rgba(255, 255, 255, 0.14); color: #f4f4f5; }\n .lens-context { color: #a1a1aa; }\n .lens-includes__label { color: #a1a1aa; }\n .lens-tgl { background: #26262a; border-color: rgba(255, 255, 255, 0.12); color: #a1a1aa; }\n .lens-tgl.is-on { background: rgba(99, 102, 241, 0.18); border-color: rgba(99, 102, 241, 0.55); color: #c7d2fe; }\n .lens-chip { background: #26262a; border-color: rgba(255, 255, 255, 0.08); color: #d4d4d8; }\n .lens-chip--ok { color: #4ade80; background: rgba(34, 197, 94, 0.12); border-color: rgba(74, 222, 128, 0.22); }\n .lens-chip--target { background: rgba(99, 102, 241, 0.16); color: #c7d2fe; }\n .lens-abtn--ghost { border-color: rgba(255, 255, 255, 0.16); color: #d4d4d8; }\n .lens-abtn--ghost:hover { background: rgba(255, 255, 255, 0.06); }\n .lens-state__msg { color: #a1a1aa; }\n .lens-idpill { background: #26262a; border-color: rgba(255, 255, 255, 0.1); }\n .lens-idpill button { color: #a1a1aa; }\n .lens-idpill button:hover { background: rgba(255, 255, 255, 0.08); color: #f4f4f5; }\n}\n\n/* ---------------- Floating action chips (picker / annotator) ---------------- */\n.lens-pick-chip, .lens-annotate-chips {\n position: fixed;\n top: calc(16px + env(safe-area-inset-top));\n left: 50%;\n transform: translateX(-50%);\n z-index: var(--lens-z);\n display: inline-flex;\n align-items: center;\n gap: 10px;\n max-width: calc(100vw - 24px);\n padding: 6px 6px 6px 14px;\n border-radius: 999px;\n background: rgba(20, 20, 23, 0.92);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n backdrop-filter: blur(12px) saturate(180%);\n border: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);\n color: #f4f4f5;\n font-size: 13px;\n font-weight: 500;\n}\n.lens-annotate-chips { z-index: var(--lens-z); }\n\n/* ---------------- Annotation toolbar ---------------- */\n/* Same floating top-center anchor as the chips row; wraps on narrow screens. */\n.lens-annotate-toolbar {\n position: fixed;\n top: calc(16px + env(safe-area-inset-top));\n left: 50%;\n transform: translateX(-50%);\n z-index: var(--lens-z);\n display: inline-flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: center;\n gap: 6px;\n max-width: calc(100vw - 24px);\n padding: 6px 8px;\n border-radius: 14px;\n background: rgba(20, 20, 23, 0.92);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n backdrop-filter: blur(12px) saturate(180%);\n border: 1px solid rgba(255, 255, 255, 0.12);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);\n color: #f4f4f5;\n}\n.lens-tool-group {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n}\n.lens-tool-sep {\n width: 1px;\n align-self: stretch;\n min-height: 22px;\n background: rgba(255, 255, 255, 0.16);\n margin: 0 2px;\n}\n.lens-tool-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: #d4d4d8;\n cursor: pointer;\n transition: background 150ms ease, color 150ms ease, border-color 150ms ease;\n}\n.lens-tool-btn:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }\n.lens-tool-btn:focus-visible { outline: 2px solid var(--lens-accent); outline-offset: 1px; }\n.lens-tool-btn.is-active {\n background: var(--lens-accent);\n border-color: var(--lens-accent);\n color: #fff;\n}\n.lens-tool-btn:disabled { opacity: 0.4; cursor: default; }\n.lens-tool-btn:disabled:hover { background: transparent; color: #d4d4d8; }\n\n.lens-swatch {\n width: 22px;\n height: 22px;\n padding: 0;\n border-radius: 999px;\n border: 2px solid transparent;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.25) inset;\n cursor: pointer;\n transition: transform 120ms ease, border-color 120ms ease;\n}\n.lens-swatch:hover { transform: scale(1.1); }\n.lens-swatch:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }\n.lens-swatch.is-active {\n border-color: #fff;\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);\n}\n\n.lens-width-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 26px;\n height: 30px;\n padding: 0 6px;\n border: 1px solid transparent;\n border-radius: 8px;\n background: transparent;\n color: #d4d4d8;\n font-family: var(--lens-font);\n font-size: 12px;\n font-weight: 700;\n cursor: pointer;\n transition: background 150ms ease, color 150ms ease, border-color 150ms ease;\n}\n.lens-width-btn:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }\n.lens-width-btn:focus-visible { outline: 2px solid var(--lens-accent); outline-offset: 1px; }\n.lens-width-btn.is-active {\n background: var(--lens-accent);\n border-color: var(--lens-accent);\n color: #fff;\n}\n\n/* Coarse pointers: bump the tool targets toward 40px. */\n@media (pointer: coarse) {\n .lens-tool-btn, .lens-width-btn { width: 38px; height: 38px; }\n .lens-swatch { width: 30px; height: 30px; }\n}\n\n/* Stacking inside the shadow layer: the panel, pill and floating chips always\n sit above the annotation layer/rects and picker highlight, so marked areas\n never paint over interactive UI. */\n.lens-panel, .lens-pill, .lens-recchip { z-index: var(--lens-z); }\n.lens-pick-chip__label, .lens-annotate-chips__label { white-space: nowrap; }\n.lens-pick-chip__btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 30px;\n padding: 0 14px;\n border: 0;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.12);\n color: #f4f4f5;\n font-family: var(--lens-font);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background 150ms ease;\n}\n.lens-pick-chip__btn:hover { background: rgba(255, 255, 255, 0.2); }\n.lens-pick-chip__btn--primary { background: var(--lens-accent); }\n.lens-pick-chip__btn--primary:hover { background: var(--lens-accent-strong); }\n\n/* ---------------- Recording chip ---------------- */\n.lens-rec-chip {\n position: fixed;\n top: calc(16px + env(safe-area-inset-top));\n left: 50%;\n transform: translateX(-50%);\n z-index: var(--lens-z);\n display: inline-flex;\n align-items: center;\n gap: 10px;\n max-width: calc(100vw - 24px);\n padding: 6px 6px 6px 14px;\n border-radius: 999px;\n background: rgba(20, 20, 23, 0.92);\n -webkit-backdrop-filter: blur(12px) saturate(180%);\n backdrop-filter: blur(12px) saturate(180%);\n border: 1px solid rgba(239, 68, 68, 0.4);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.35);\n color: #f4f4f5;\n font-size: 13px;\n font-weight: 600;\n}\n.lens-rec-chip__dot {\n width: 10px;\n height: 10px;\n border-radius: 999px;\n background: #ef4444;\n animation: lens-pulse 1.2s ease-in-out infinite;\n}\n@keyframes lens-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.4; transform: scale(0.7); }\n}\n.lens-rec-chip__time { font-variant-numeric: tabular-nums; min-width: 34px; }\n.lens-rec-chip__stop {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n height: 30px;\n padding: 0 14px;\n border: 0;\n border-radius: 999px;\n background: #ef4444;\n color: #fff;\n font-family: var(--lens-font);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: background 150ms ease;\n}\n.lens-rec-chip__stop:hover { background: #dc2626; }\n.lens-chip--rec { gap: 6px; }\n\n/* ---------------- Coarse pointers (touch): ≥44px targets ---------------- */\n@media (pointer: coarse) {\n .lens-btn { height: 44px; padding: 0 16px; }\n .lens-btn--icon { width: 44px; }\n .lens-pill__dot { width: 40px; height: 40px; }\n .lens-abtn { height: 44px; }\n .lens-tgl { min-height: 40px; padding: 4px 14px; }\n .lens-panel__x { width: 44px; height: 44px; }\n .lens-chip__x { min-width: 32px; min-height: 32px; align-items: center; justify-content: center; }\n .lens-pick-chip__btn, .lens-rec-chip__stop { height: 40px; padding: 0 18px; }\n}\n\n/* ---------------- Bottom sheet under 640px ---------------- */\n@media (max-width: 640px) {\n .lens-panel {\n left: 0;\n right: 0;\n bottom: 0;\n width: 100%;\n max-width: 100%;\n max-height: 85dvh;\n border-radius: 16px 16px 0 0;\n overflow-y: auto;\n padding-bottom: env(safe-area-inset-bottom);\n animation: lens-sheet-in 180ms ease;\n }\n @keyframes lens-sheet-in {\n from { opacity: 0; transform: translateY(16px); }\n to { opacity: 1; transform: none; }\n }\n .lens-textarea { font-size: 16px; }\n}\n`;\n","import type { Annotation, TargetElement } from '@horus-lens/shared';\nimport { AnnotationEditor } from './annotation-editor.js';\nimport { el } from './dom.js';\nimport { iconClose, iconCrosshair, iconEye, iconStop } from './icons.js';\nimport { formatDuration, Panel } from './panel.js';\nimport { ElementPicker } from './picker.js';\nimport { OVERLAY_CSS } from './styles.js';\nimport type { OverlayDeps, SubmitReportIncludes } from './types.js';\n\nimport { LENS_OVERLAY_HOST_ID } from '@horus-lens/core';\n\n/** Canonical host id — the core recorder/screenshot exclusions key off it. */\nexport const ROOT_ID = LENS_OVERLAY_HOST_ID;\n\n/** Auto-stop a manual recording at this ceiling (mirrors the core hard cap). */\nconst RECORDING_MAX_MS = 120000;\n\nexport interface OverlayHandle {\n open(): void;\n close(): void;\n destroy(): void;\n}\n\n/**\n * Root overlay controller. Owns the Shadow DOM host, the floating pill, and the\n * three interaction surfaces (element picker, annotator, report panel). Pure\n * DOM — no framework — so it can be dropped into any page.\n */\nclass Overlay implements OverlayHandle {\n private host: HTMLElement;\n private shadow: ShadowRoot;\n private layer: HTMLElement;\n private pickBtn!: HTMLButtonElement;\n private picker: ElementPicker;\n private annotator: AnnotationEditor;\n private panel: Panel | null = null;\n private target: TargetElement | null = null;\n private destroyed = false;\n\n private recordingChip: HTMLElement | null = null;\n private recordingTimerEl: HTMLElement | null = null;\n private recordingInterval: ReturnType<typeof setInterval> | null = null;\n private recordingStartTs = 0;\n /** Duration of a retained (stopped, not yet submitted/discarded) recording. */\n private recordedDurationMs: number | null = null;\n\n constructor(private readonly deps: OverlayDeps) {\n this.host = el('div', { attrs: { id: ROOT_ID } });\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n const style = document.createElement('style');\n style.textContent = OVERLAY_CSS;\n this.shadow.append(style);\n\n this.layer = el('div', { class: 'lens-layer' });\n this.shadow.append(this.layer);\n\n this.picker = new ElementPicker(this.layer, this.host);\n this.annotator = new AnnotationEditor(this.layer);\n\n this.layer.append(this.buildPill());\n document.documentElement.append(this.host);\n\n window.addEventListener('keydown', this.onGlobalKey, true);\n }\n\n private buildPill(): HTMLElement {\n this.pickBtn = el('button', {\n class: 'lens-btn lens-btn--icon',\n ariaLabel: 'Pick an element',\n title: 'Pick an element',\n html: iconCrosshair,\n on: { click: () => this.togglePicker() },\n });\n return el('div', { class: 'lens-pill', attrs: { role: 'toolbar', 'aria-label': 'Lens' } }, [\n el('span', { class: 'lens-pill__dot', html: iconEye }),\n el('button', {\n class: 'lens-btn',\n text: 'Report issue',\n on: { click: () => this.open() },\n }),\n this.pickBtn,\n el('span', { class: 'lens-pill__sep' }),\n el('button', {\n class: 'lens-btn lens-btn--icon',\n ariaLabel: 'Close Lens',\n title: 'Close Lens',\n html: iconClose,\n on: { click: () => this.dismiss() },\n }),\n ]);\n }\n\n open(): void {\n if (this.destroyed) return;\n this.stopPicker();\n if (!this.panel) {\n this.panel = new Panel({\n getStats: () => this.deps.snapshotStats(),\n getTarget: () => this.target,\n getAnnotationCount: () => this.annotator.count,\n getRecording: () =>\n this.recordedDurationMs !== null ? { durationMs: this.recordedDurationMs } : null,\n onRemoveTarget: () => {\n this.target = null;\n this.panel?.refresh();\n },\n onMarkArea: () => this.startAnnotating(),\n onRecordSteps: () => this.startRecording(),\n onDiscardRecording: () => this.discardRecording(),\n onClose: () => this.close(),\n onSubmit: (comment, include) => this.submit(comment, include),\n });\n this.layer.append(this.panel.root);\n }\n this.panel.root.style.display = '';\n this.panel.refresh();\n this.panel.focus();\n }\n\n close(): void {\n if (this.panel) {\n this.panel.destroy();\n this.panel = null;\n }\n }\n\n private toggle(): void {\n if (this.panel && this.panel.root.style.display !== 'none') this.close();\n else this.open();\n }\n\n private togglePicker(): void {\n if (this.picker.isActive) {\n this.stopPicker();\n return;\n }\n this.close();\n this.pickBtn.classList.add('is-active');\n this.picker.start(\n (elem) => {\n this.pickBtn.classList.remove('is-active');\n this.target = this.deps.client.captureTarget(elem);\n this.open();\n },\n () => this.pickBtn.classList.remove('is-active'),\n );\n }\n\n private stopPicker(): void {\n if (this.picker.isActive) this.picker.stop();\n this.pickBtn.classList.remove('is-active');\n }\n\n private startAnnotating(): void {\n if (this.panel) this.panel.root.style.display = 'none';\n this.annotator.start(() => {\n if (this.panel) {\n this.panel.root.style.display = '';\n this.panel.refresh();\n }\n });\n }\n\n private startRecording(): void {\n if (this.deps.client.isRecording()) return;\n // A fresh recording supersedes any retained one.\n this.recordedDurationMs = null;\n this.deps.client.startRecording();\n this.recordingStartTs = Date.now();\n if (this.panel) this.panel.root.style.display = 'none';\n this.showRecordingChip();\n }\n\n private stopRecording(): void {\n const result = this.deps.client.stopRecording();\n this.recordedDurationMs = result?.durationMs ?? Date.now() - this.recordingStartTs;\n this.hideRecordingChip();\n // Reopen the panel; the retained recording surfaces as a context chip.\n if (this.panel) {\n this.panel.root.style.display = '';\n this.panel.refresh();\n } else {\n this.open();\n }\n }\n\n private discardRecording(): void {\n this.deps.client.discardRecording();\n this.recordedDurationMs = null;\n this.panel?.refresh();\n }\n\n private showRecordingChip(): void {\n this.recordingTimerEl = el('span', { class: 'lens-rec-chip__time', text: '0:00' });\n this.recordingChip = el('div', { class: 'lens-rec-chip' }, [\n el('span', { class: 'lens-rec-chip__dot' }),\n el('span', { class: 'lens-rec-chip__label', text: 'Recording' }),\n this.recordingTimerEl,\n el('button', {\n class: 'lens-rec-chip__stop',\n html: iconStop + '<span>Stop</span>',\n on: { click: () => this.stopRecording() },\n }),\n ]);\n this.layer.append(this.recordingChip);\n this.recordingInterval = setInterval(() => this.tickRecording(), 250);\n }\n\n private tickRecording(): void {\n const elapsed = Date.now() - this.recordingStartTs;\n if (this.recordingTimerEl) this.recordingTimerEl.textContent = formatDuration(elapsed);\n if (elapsed >= RECORDING_MAX_MS) this.stopRecording();\n }\n\n private hideRecordingChip(): void {\n if (this.recordingInterval) {\n clearInterval(this.recordingInterval);\n this.recordingInterval = null;\n }\n if (this.recordingChip) {\n this.recordingChip.remove();\n this.recordingChip = null;\n }\n this.recordingTimerEl = null;\n }\n\n private async submit(\n comment: string,\n include: SubmitReportIncludes,\n ): Promise<{ reportId: string }> {\n const annotations: Annotation[] = this.annotator.list();\n // The SVG editor owns all annotation geometry (document coords). It bakes\n // the marks into the screenshot (blur redaction + rasterized overlay) via\n // the composite, and derives the crop bbox from the same mark data — no\n // DOM math here. Both are `undefined`/`null` when nothing is marked.\n const composite = this.annotator.getComposite() ?? undefined;\n const screenshotCrop = this.annotator.getCropBounds();\n const result = await this.deps.client.submitReport({\n comment: comment || undefined,\n annotations,\n target: this.target ?? undefined,\n excludeFromScreenshot: this.host,\n screenshotCrop,\n annotationComposite: composite,\n include,\n });\n // Reset transient capture state after a successful submission.\n this.target = null;\n this.annotator.clear();\n this.recordedDurationMs = null;\n this.deps.client.discardRecording();\n return result;\n }\n\n private dismiss(): void {\n this.deps.onDismiss();\n this.destroy();\n }\n\n private onGlobalKey = (e: KeyboardEvent): void => {\n // Cmd/Ctrl+Shift+L toggles the panel.\n if ((e.metaKey || e.ctrlKey) && e.shiftKey && (e.key === 'l' || e.key === 'L')) {\n e.preventDefault();\n this.toggle();\n }\n };\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n window.removeEventListener('keydown', this.onGlobalKey, true);\n this.stopPicker();\n if (this.deps.client.isRecording()) this.deps.client.stopRecording();\n this.hideRecordingChip();\n if (this.annotator.isActive) this.annotator.exit();\n this.annotator.clear();\n this.close();\n this.host.remove();\n }\n}\n\nexport function mountOverlay(deps: OverlayDeps): OverlayHandle {\n return new Overlay(deps);\n}\n","import type { AppContext } from '@horus-lens/shared';\nimport type { LensBrowser } from './index.js';\n\n/**\n * GTM-style command stub. The loader snippet defines:\n * window.Lens = function(){(window.Lens.q = window.Lens.q||[]).push(arguments)}\n * so pages can call `Lens('init', ...)`, `Lens('identify', user)` etc. before\n * the bundle downloads. On load we drain that queue, then replace the global\n * with a live dispatcher that forwards subsequent calls to the running client.\n */\n\nexport type LensCommand = 'init' | 'identify' | 'app' | 'open';\n\nexport interface LensGlobal {\n (...args: unknown[]): void;\n q?: Array<ArrayLike<unknown>>;\n}\n\ndeclare global {\n interface Window {\n Lens?: LensGlobal;\n }\n}\n\n/** Structured result of replaying the pre-boot command queue. */\nexport interface QueuedCommands {\n /** `init` argument: an access id string or a partial config object. */\n init?: string | Record<string, unknown>;\n identify?: NonNullable<AppContext['user']>;\n app?: Partial<AppContext>;\n open: boolean;\n}\n\n/** Drain `window.Lens.q` into a structured shape consumed by boot(). */\nexport function processQueue(): QueuedCommands {\n const result: QueuedCommands = { open: false };\n if (typeof window === 'undefined') return result;\n\n const queue = window.Lens?.q;\n if (!queue) return result;\n\n for (const entry of queue) {\n const args = Array.from(entry as ArrayLike<unknown>);\n const command = args[0] as LensCommand | undefined;\n const payload = args[1];\n switch (command) {\n case 'init':\n if (typeof payload === 'string' || (payload && typeof payload === 'object')) {\n result.init = payload as string | Record<string, unknown>;\n }\n break;\n case 'identify':\n if (payload && typeof payload === 'object') {\n result.identify = payload as NonNullable<AppContext['user']>;\n }\n break;\n case 'app':\n if (payload && typeof payload === 'object') {\n result.app = payload as Partial<AppContext>;\n }\n break;\n case 'open':\n result.open = true;\n break;\n }\n }\n\n // Clear so a freshly installed live dispatcher never re-processes them.\n if (window.Lens) window.Lens.q = [];\n return result;\n}\n\n/**\n * Replace `window.Lens` with a live function that forwards commands to the\n * mounted overlay. Safe to call with `null` (gate inactive) — it installs a\n * no-op-ish dispatcher that only handles future `init`-less commands.\n */\nexport function installGlobal(browser: LensBrowser | null): void {\n if (typeof window === 'undefined') return;\n\n const dispatch: LensGlobal = (...args: unknown[]): void => {\n if (!browser) return;\n const command = args[0] as LensCommand | undefined;\n const payload = args[1];\n switch (command) {\n case 'identify':\n if (payload && typeof payload === 'object') {\n browser.client.setApp({ user: payload as NonNullable<AppContext['user']> });\n }\n break;\n case 'app':\n if (payload && typeof payload === 'object') {\n browser.client.setApp(payload as Partial<AppContext>);\n }\n break;\n case 'open':\n browser.open();\n break;\n case 'init':\n // Already booted — ignore duplicate init calls.\n break;\n }\n };\n\n window.Lens = dispatch;\n}\n\n/** Apply queued identify / app context to a started client. */\nexport function applyContext(browser: LensBrowser, commands: QueuedCommands): void {\n if (commands.identify) browser.client.setApp({ user: commands.identify });\n if (commands.app) browser.client.setApp(commands.app);\n if (commands.open) browser.open();\n}\n","/**\n * The documented loader snippet — a GTM-style inline stub that queues commands\n * until the async bundle loads and replays them. Ship this in docs / install\n * flows so a page can call `Lens('init', ...)` before the SDK is downloaded.\n */\n\nexport interface SnippetOptions {\n accessId: string;\n /** URL of the browser bundle (defaults to the public CDN latest build). */\n cdnUrl?: string;\n}\n\nexport const DEFAULT_CDN_URL = 'https://cdn.lens.dev/browser.js';\n\nexport function loaderSnippet(options: SnippetOptions): string {\n const cdn = options.cdnUrl ?? DEFAULT_CDN_URL;\n return `<script>\n(function(w,d,s,u,i){\n w.Lens=w.Lens||function(){(w.Lens.q=w.Lens.q||[]).push(arguments)};\n w.Lens('init', i);\n var g=d.createElement(s); g.async=1; g.src=u;\n var f=d.getElementsByTagName(s)[0]; f.parentNode.insertBefore(g,f);\n})(window,document,'script','${cdn}','${options.accessId}');\n</script>`;\n}\n\n/** Example snippet string for documentation (placeholder access id + CDN). */\nexport const LOADER_SNIPPET = loaderSnippet({ accessId: 'lai_YOUR_ACCESS_ID' });\n"],"mappings":"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","names":["copy","svg"]}