agent-ui-annotation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +219 -0
- package/dist/agent-ui-annotation.js +3263 -0
- package/dist/agent-ui-annotation.js.map +1 -0
- package/dist/agent-ui-annotation.umd.cjs +1007 -0
- package/dist/agent-ui-annotation.umd.cjs.map +1 -0
- package/dist/index.d.ts +682 -0
- package/package.json +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-ui-annotation.js","sources":["../src/core/store.ts","../src/core/event-bus.ts","../src/core/state.ts","../src/core/element/identifier.ts","../src/core/utils/css-cleaner.ts","../src/core/element/path-generator.ts","../src/core/element/accessibility.ts","../src/core/element/styles.ts","../src/core/utils/fixed-detection.ts","../src/core/element/index.ts","../src/core/scopes/scope.ts","../src/core/scopes/persistence.ts","../src/core/scopes/output.ts","../src/core/dom/events.ts","../src/core/utils/throttle.ts","../src/core/dom/hover-detection.ts","../src/core/dom/multi-select.ts","../src/core/dom/freeze.ts","../src/core/dom/cursor.ts","../src/core/controller.ts","../src/themes/variables.ts","../src/element/styles.ts","../src/element/templates/toolbar.ts","../src/element/templates/marker.ts","../src/element/templates/popup.ts","../src/element/templates/tooltip.ts","../src/core/types.ts","../src/element/templates/settings.ts","../src/element/annotation-element.ts","../src/adapters/vanilla/index.ts","../src/index.ts"],"sourcesContent":["/**\n * Observable store with subscribe/batch functionality\n */\n\nexport type Listener<T> = (state: T) => void;\nexport type Selector<T, R> = (state: T) => R;\nexport type Unsubscribe = () => void;\n\nexport interface Store<T> {\n /** Get current state */\n getState(): T;\n /** Merge partial state update */\n setState(partial: Partial<T> | ((state: T) => Partial<T>)): void;\n /** Subscribe to state changes, optionally filtered by selector */\n subscribe(listener: Listener<T>, selector?: Selector<T, unknown>): Unsubscribe;\n /** Batch multiple state updates into a single notification */\n batch(fn: () => void): void;\n /** Reset state to initial value */\n reset(initialState: T): void;\n /** Destroy store and clean up */\n destroy(): void;\n}\n\n/**\n * Create a new observable store\n */\nexport function createStore<T extends object>(initialState: T): Store<T> {\n let state: T = { ...initialState };\n const listeners: Set<{ listener: Listener<T>; selector?: Selector<T, unknown>; prevSelected?: unknown }> = new Set();\n let isBatching = false;\n let hasChanges = false;\n let isDestroyed = false;\n\n const notify = () => {\n if (isDestroyed) return;\n\n listeners.forEach((entry) => {\n try {\n if (entry.selector) {\n const selected = entry.selector(state);\n if (!Object.is(selected, entry.prevSelected)) {\n entry.prevSelected = selected;\n entry.listener(state);\n }\n } else {\n entry.listener(state);\n }\n } catch (error) {\n console.error('[Annotation Store] Listener error:', error);\n }\n });\n };\n\n const getState = (): T => {\n return state;\n };\n\n const setState = (partial: Partial<T> | ((state: T) => Partial<T>)): void => {\n if (isDestroyed) return;\n\n const nextPartial = typeof partial === 'function' ? partial(state) : partial;\n const nextState = { ...state, ...nextPartial };\n\n // Check if state actually changed\n const hasActualChanges = Object.keys(nextPartial).some(\n (key) => !Object.is(state[key as keyof T], nextState[key as keyof T])\n );\n\n if (!hasActualChanges) return;\n\n state = nextState;\n\n if (isBatching) {\n hasChanges = true;\n } else {\n notify();\n }\n };\n\n const subscribe = (listener: Listener<T>, selector?: Selector<T, unknown>): Unsubscribe => {\n if (isDestroyed) return () => {};\n\n const entry = {\n listener,\n selector,\n prevSelected: selector ? selector(state) : undefined,\n };\n\n listeners.add(entry);\n\n return () => {\n listeners.delete(entry);\n };\n };\n\n const batch = (fn: () => void): void => {\n if (isDestroyed) return;\n\n isBatching = true;\n hasChanges = false;\n\n try {\n fn();\n } finally {\n isBatching = false;\n if (hasChanges) {\n notify();\n }\n }\n };\n\n const reset = (newInitialState: T): void => {\n if (isDestroyed) return;\n state = { ...newInitialState };\n notify();\n };\n\n const destroy = (): void => {\n isDestroyed = true;\n listeners.clear();\n };\n\n return {\n getState,\n setState,\n subscribe,\n batch,\n reset,\n destroy,\n };\n}\n\n/**\n * Create a derived store that computes values from another store\n */\nexport function createDerivedStore<T extends object, R>(\n sourceStore: Store<T>,\n selector: Selector<T, R>\n): { getValue: () => R; subscribe: (listener: (value: R) => void) => Unsubscribe } {\n let currentValue = selector(sourceStore.getState());\n\n return {\n getValue: () => currentValue,\n subscribe: (listener: (value: R) => void) => {\n return sourceStore.subscribe((state) => {\n const newValue = selector(state);\n if (!Object.is(newValue, currentValue)) {\n currentValue = newValue;\n listener(newValue);\n }\n });\n },\n };\n}\n","/**\n * Typed event emitter for cross-component communication\n */\n\nimport type { EventMap } from './types';\n\nexport type EventHandler<T> = (payload: T) => void;\nexport type Unsubscribe = () => void;\n\nexport interface EventBus<Events extends Record<string, unknown>> {\n /** Emit an event with payload */\n emit<K extends keyof Events>(event: K, payload: Events[K]): void;\n /** Subscribe to an event */\n on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Unsubscribe;\n /** Subscribe to an event, automatically unsubscribe after first emission */\n once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Unsubscribe;\n /** Remove all listeners for an event, or all listeners if no event specified */\n off<K extends keyof Events>(event?: K): void;\n /** Destroy the event bus */\n destroy(): void;\n}\n\n/**\n * Create a typed event bus\n */\nexport function createEventBus<Events extends Record<string, unknown> = EventMap>(): EventBus<Events> {\n type HandlerMap = Map<keyof Events, Set<EventHandler<unknown>>>;\n\n const handlers: HandlerMap = new Map();\n let isDestroyed = false;\n\n const emit = <K extends keyof Events>(event: K, payload: Events[K]): void => {\n if (isDestroyed) return;\n\n const eventHandlers = handlers.get(event);\n if (!eventHandlers) return;\n\n // Create a copy to avoid issues with handlers that unsubscribe themselves\n const handlersCopy = Array.from(eventHandlers);\n\n handlersCopy.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n console.error(`[Annotation EventBus] Error in handler for \"${String(event)}\":`, error);\n }\n });\n };\n\n const on = <K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Unsubscribe => {\n if (isDestroyed) return () => {};\n\n if (!handlers.has(event)) {\n handlers.set(event, new Set());\n }\n\n const eventHandlers = handlers.get(event)!;\n eventHandlers.add(handler as EventHandler<unknown>);\n\n return () => {\n eventHandlers.delete(handler as EventHandler<unknown>);\n if (eventHandlers.size === 0) {\n handlers.delete(event);\n }\n };\n };\n\n const once = <K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): Unsubscribe => {\n const unsubscribe = on(event, (payload) => {\n unsubscribe();\n handler(payload);\n });\n return unsubscribe;\n };\n\n const off = <K extends keyof Events>(event?: K): void => {\n if (isDestroyed) return;\n\n if (event !== undefined) {\n handlers.delete(event);\n } else {\n handlers.clear();\n }\n };\n\n const destroy = (): void => {\n isDestroyed = true;\n handlers.clear();\n };\n\n return {\n emit,\n on,\n once,\n off,\n destroy,\n };\n}\n\n/**\n * Create a namespaced event bus that prefixes all events\n */\nexport function createNamespacedEventBus<Events extends Record<string, unknown>>(\n parentBus: EventBus<Record<string, unknown>>,\n namespace: string\n): EventBus<Events> {\n const prefixEvent = (event: string | number | symbol) => `${namespace}:${String(event)}`;\n\n return {\n emit: (event, payload) => {\n parentBus.emit(prefixEvent(event), payload);\n },\n on: (event, handler) => {\n return parentBus.on(prefixEvent(event), handler as EventHandler<unknown>);\n },\n once: (event, handler) => {\n return parentBus.once(prefixEvent(event), handler as EventHandler<unknown>);\n },\n off: (event) => {\n if (event !== undefined) {\n parentBus.off(prefixEvent(event));\n }\n },\n destroy: () => {\n // Namespaced bus doesn't destroy parent\n },\n };\n}\n","/**\n * State shape and initial state factory\n */\n\nimport type { AppState, Settings, ToolMode, Position, AnnotationId } from './types';\n\n/** Default settings */\nexport const DEFAULT_SETTINGS: Settings = {\n theme: 'auto',\n outputLevel: 'standard',\n toolbarPosition: 'bottom-right',\n showTooltips: true,\n showMarkerNumbers: true,\n freezeOnScope: false,\n persistScopes: true,\n scopeColor: '#AF52DE', // purple\n blockInteractions: true,\n autoClearAfterCopy: false,\n};\n\n/** Default toolbar position */\nexport const DEFAULT_TOOLBAR_POSITION: Position = {\n x: 20,\n y: 20,\n};\n\n/** Create initial state */\nexport function createInitialState(overrides?: Partial<AppState>): AppState {\n return {\n scopes: new Map(),\n selectedAnnotationId: null,\n hoveredElement: null,\n hoveredElementInfo: null,\n mode: 'disabled' as ToolMode,\n toolbarExpanded: false,\n toolbarPosition: { ...DEFAULT_TOOLBAR_POSITION },\n settings: { ...DEFAULT_SETTINGS },\n isSelecting: false,\n selectionRect: null,\n selectionPreviewElements: [],\n isFrozen: false,\n popupVisible: false,\n popupAnnotationId: null,\n popupElementInfo: null,\n popupClickX: 0,\n popupClickY: 0,\n pendingMarkerX: 0,\n pendingMarkerY: 0,\n pendingMarkerIsFixed: false,\n multiSelectElements: [],\n multiSelectInfos: [],\n markersVisible: true,\n animatingMarkers: new Set(),\n exitingMarkers: new Set(),\n deletingMarkerId: null,\n renumberFrom: null,\n showCopiedFeedback: false,\n showClearedFeedback: false,\n scrollY: 0,\n showEntranceAnimation: true,\n isDraggingToolbar: false,\n settingsPanelVisible: false,\n ...overrides,\n };\n}\n\n/** State selectors */\nexport const selectors = {\n getScopes: (state: AppState) => state.scopes,\n getScopeById: (state: AppState, id: AnnotationId) => state.scopes.get(id),\n getScopeCount: (state: AppState) => state.scopes.size,\n getScopesArray: (state: AppState) =>\n Array.from(state.scopes.values()).sort((a, b) => a.number - b.number),\n getSelectedScope: (state: AppState) =>\n state.selectedAnnotationId ? state.scopes.get(state.selectedAnnotationId) : null,\n isActive: (state: AppState) => state.mode !== 'disabled',\n isMultiSelectMode: (state: AppState) => state.mode === 'multi-select',\n getSettings: (state: AppState) => state.settings,\n getTheme: (state: AppState) => state.settings.theme,\n getOutputLevel: (state: AppState) => state.settings.outputLevel,\n areMarkersVisible: (state: AppState) => state.markersVisible && state.toolbarExpanded,\n};\n","/**\n * Element identifier - generates human-readable element descriptions\n */\n\nconst MAX_TEXT_LENGTH = 40;\n\n/**\n * Truncate text to a maximum length with ellipsis\n */\nfunction truncate(text: string, maxLength: number = MAX_TEXT_LENGTH): string {\n const cleaned = text.trim().replace(/\\s+/g, ' ');\n if (cleaned.length <= maxLength) return cleaned;\n return cleaned.slice(0, maxLength - 3) + '...';\n}\n\n/**\n * Get visible text content from an element, excluding hidden elements\n */\nfunction getVisibleText(element: Element): string {\n // For input elements, use value or placeholder\n if (element instanceof HTMLInputElement) {\n return element.value || element.placeholder || '';\n }\n\n if (element instanceof HTMLTextAreaElement) {\n return element.value || element.placeholder || '';\n }\n\n // For select elements, use selected option text\n if (element instanceof HTMLSelectElement) {\n return element.options[element.selectedIndex]?.text || '';\n }\n\n // Get text content, excluding script and style\n const clone = element.cloneNode(true) as Element;\n clone.querySelectorAll('script, style, [aria-hidden=\"true\"]').forEach((el) => el.remove());\n\n return clone.textContent || '';\n}\n\n/**\n * Get ARIA label from element\n */\nfunction getAriaLabel(element: Element): string | null {\n const label = element.getAttribute('aria-label');\n if (label) return label;\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labelElement = document.getElementById(labelledBy);\n if (labelElement) {\n return getVisibleText(labelElement);\n }\n }\n\n return null;\n}\n\n/**\n * Get label for form element\n */\nfunction getFormLabel(element: Element): string | null {\n // Check for associated label via 'for' attribute\n const id = element.id;\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label) {\n return getVisibleText(label);\n }\n }\n\n // Check for wrapping label\n const parentLabel = element.closest('label');\n if (parentLabel) {\n // Get label text excluding the input itself\n const clone = parentLabel.cloneNode(true) as Element;\n clone.querySelectorAll('input, select, textarea').forEach((el) => el.remove());\n const text = clone.textContent?.trim();\n if (text) return text;\n }\n\n return null;\n}\n\n/**\n * Check if element contains only an SVG/icon\n */\nfunction containsOnlyIcon(element: Element): boolean {\n const children = Array.from(element.children);\n if (children.length === 0) return false;\n\n const hasOnlySvg = children.every(\n (child) =>\n child.tagName === 'SVG' ||\n child.tagName === 'svg' ||\n child.classList.contains('icon') ||\n child.tagName === 'I'\n );\n\n const textContent = getVisibleText(element).trim();\n return hasOnlySvg && !textContent;\n}\n\n/**\n * Identify a button element\n */\nfunction identifyButton(element: Element): string {\n const text = truncate(getVisibleText(element));\n if (text) {\n return `button \"${text}\"`;\n }\n\n const ariaLabel = getAriaLabel(element);\n if (ariaLabel) {\n return `button [${truncate(ariaLabel)}]`;\n }\n\n const title = element.getAttribute('title');\n if (title) {\n return `button [${truncate(title)}]`;\n }\n\n if (containsOnlyIcon(element)) {\n return 'icon button';\n }\n\n const type = element.getAttribute('type');\n if (type && type !== 'button') {\n return `${type} button`;\n }\n\n return 'button';\n}\n\n/**\n * Identify a link element\n */\nfunction identifyLink(element: HTMLAnchorElement): string {\n const text = truncate(getVisibleText(element));\n if (text) {\n return `link \"${text}\"`;\n }\n\n const ariaLabel = getAriaLabel(element);\n if (ariaLabel) {\n return `link [${truncate(ariaLabel)}]`;\n }\n\n const href = element.getAttribute('href');\n if (href && href !== '#') {\n // Extract meaningful part of URL\n try {\n const url = new URL(href, window.location.origin);\n if (url.origin === window.location.origin) {\n return `link to ${url.pathname}`;\n }\n return `link to ${url.hostname}`;\n } catch {\n return `link to ${truncate(href, 30)}`;\n }\n }\n\n if (containsOnlyIcon(element)) {\n return 'icon link';\n }\n\n return 'link';\n}\n\n/**\n * Identify an input element\n */\nfunction identifyInput(element: HTMLInputElement): string {\n const type = element.type || 'text';\n const label = getFormLabel(element);\n const placeholder = element.placeholder;\n const name = element.name;\n const ariaLabel = getAriaLabel(element);\n\n // Build description\n let desc = '';\n\n if (label) {\n desc = `\"${truncate(label)}\"`;\n } else if (ariaLabel) {\n desc = `[${truncate(ariaLabel)}]`;\n } else if (placeholder) {\n desc = `\"${truncate(placeholder)}\"`;\n } else if (name) {\n desc = `[${name}]`;\n }\n\n // Special input types\n switch (type) {\n case 'submit':\n return `submit button${desc ? ' ' + desc : ''}`;\n case 'checkbox':\n return `checkbox${desc ? ' ' + desc : ''}`;\n case 'radio':\n return `radio${desc ? ' ' + desc : ''}`;\n case 'file':\n return `file input${desc ? ' ' + desc : ''}`;\n case 'search':\n return `search input${desc ? ' ' + desc : ''}`;\n case 'email':\n return `email input${desc ? ' ' + desc : ''}`;\n case 'password':\n return `password input${desc ? ' ' + desc : ''}`;\n case 'number':\n return `number input${desc ? ' ' + desc : ''}`;\n case 'tel':\n return `phone input${desc ? ' ' + desc : ''}`;\n case 'url':\n return `URL input${desc ? ' ' + desc : ''}`;\n case 'date':\n case 'datetime-local':\n case 'time':\n return `${type} input${desc ? ' ' + desc : ''}`;\n case 'range':\n return `slider${desc ? ' ' + desc : ''}`;\n case 'color':\n return `color picker${desc ? ' ' + desc : ''}`;\n default:\n return `text input${desc ? ' ' + desc : ''}`;\n }\n}\n\n/**\n * Identify a select element\n */\nfunction identifySelect(element: HTMLSelectElement): string {\n const label = getFormLabel(element);\n const ariaLabel = getAriaLabel(element);\n const name = element.name;\n\n let desc = '';\n if (label) {\n desc = ` \"${truncate(label)}\"`;\n } else if (ariaLabel) {\n desc = ` [${truncate(ariaLabel)}]`;\n } else if (name) {\n desc = ` [${name}]`;\n }\n\n return `dropdown${desc}`;\n}\n\n/**\n * Identify a textarea element\n */\nfunction identifyTextarea(element: HTMLTextAreaElement): string {\n const label = getFormLabel(element);\n const ariaLabel = getAriaLabel(element);\n const placeholder = element.placeholder;\n const name = element.name;\n\n let desc = '';\n if (label) {\n desc = ` \"${truncate(label)}\"`;\n } else if (ariaLabel) {\n desc = ` [${truncate(ariaLabel)}]`;\n } else if (placeholder) {\n desc = ` \"${truncate(placeholder)}\"`;\n } else if (name) {\n desc = ` [${name}]`;\n }\n\n return `text area${desc}`;\n}\n\n/**\n * Identify a heading element\n */\nfunction identifyHeading(element: Element): string {\n const level = element.tagName.toLowerCase();\n const text = truncate(getVisibleText(element));\n return text ? `${level} \"${text}\"` : level;\n}\n\n/**\n * Identify a paragraph or text block\n */\nfunction identifyTextBlock(element: Element, type: string): string {\n const text = truncate(getVisibleText(element), 50);\n return text ? `${type}: \"${text}\"` : type;\n}\n\n/**\n * Identify an image element\n */\nfunction identifyImage(element: HTMLImageElement): string {\n const alt = element.alt;\n if (alt) {\n return `image \"${truncate(alt)}\"`;\n }\n\n const ariaLabel = getAriaLabel(element);\n if (ariaLabel) {\n return `image [${truncate(ariaLabel)}]`;\n }\n\n // Try to get meaningful part of src\n const src = element.src;\n if (src) {\n try {\n const url = new URL(src);\n const filename = url.pathname.split('/').pop();\n if (filename && !filename.includes('?')) {\n return `image \"${truncate(filename, 30)}\"`;\n }\n } catch {\n // Ignore URL parsing errors\n }\n }\n\n return 'image';\n}\n\n/**\n * Identify an SVG element\n */\nfunction identifySvg(element: SVGElement): string {\n // Check if SVG is inside a button or link\n const interactiveParent = element.closest('button, a, [role=\"button\"]');\n if (interactiveParent) {\n return 'icon';\n }\n\n const ariaLabel = getAriaLabel(element);\n if (ariaLabel) {\n return `graphic [${truncate(ariaLabel)}]`;\n }\n\n const title = element.querySelector('title');\n if (title?.textContent) {\n return `graphic \"${truncate(title.textContent)}\"`;\n }\n\n return 'icon';\n}\n\n/**\n * Identify a video element\n */\nfunction identifyVideo(element: HTMLVideoElement): string {\n const ariaLabel = getAriaLabel(element);\n if (ariaLabel) {\n return `video [${truncate(ariaLabel)}]`;\n }\n\n return 'video';\n}\n\n/**\n * Identify a table cell\n */\nfunction identifyTableCell(element: Element): string {\n const isHeader = element.tagName === 'TH';\n const text = truncate(getVisibleText(element), 30);\n const type = isHeader ? 'table header' : 'table cell';\n return text ? `${type}: \"${text}\"` : type;\n}\n\n/**\n * Identify a list item\n */\nfunction identifyListItem(element: Element): string {\n const text = truncate(getVisibleText(element), 50);\n return text ? `list item: \"${text}\"` : 'list item';\n}\n\n/**\n * Identify a label element\n */\nfunction identifyLabel(element: HTMLLabelElement): string {\n const text = truncate(getVisibleText(element));\n return text ? `label \"${text}\"` : 'label';\n}\n\n/**\n * Identify a generic container element\n */\nfunction identifyContainer(element: Element): string {\n // Check for ARIA role\n const role = element.getAttribute('role');\n if (role) {\n return role;\n }\n\n // Check for common semantic meanings via class names\n const classList = Array.from(element.classList);\n const semanticClasses = ['header', 'footer', 'nav', 'sidebar', 'main', 'content', 'article', 'section', 'card', 'modal', 'dialog', 'menu', 'dropdown', 'panel', 'container', 'wrapper'];\n\n for (const cls of classList) {\n const lowerCls = cls.toLowerCase();\n for (const semantic of semanticClasses) {\n if (lowerCls.includes(semantic)) {\n return semantic;\n }\n }\n }\n\n // Check for data attributes that might indicate purpose\n const dataTestId = element.getAttribute('data-testid') || element.getAttribute('data-test-id');\n if (dataTestId) {\n return dataTestId.replace(/[-_]/g, ' ');\n }\n\n // Fall back to tag name\n return element.tagName.toLowerCase();\n}\n\n/**\n * Generate a human-readable identifier for any DOM element\n */\nexport function identifyElement(element: Element): string {\n const tagName = element.tagName.toLowerCase();\n\n // Buttons\n if (\n tagName === 'button' ||\n element.getAttribute('role') === 'button' ||\n (element instanceof HTMLInputElement &&\n (element.type === 'button' || element.type === 'submit' || element.type === 'reset'))\n ) {\n return identifyButton(element);\n }\n\n // Links\n if (tagName === 'a') {\n return identifyLink(element as HTMLAnchorElement);\n }\n\n // Form inputs\n if (tagName === 'input') {\n return identifyInput(element as HTMLInputElement);\n }\n\n if (tagName === 'select') {\n return identifySelect(element as HTMLSelectElement);\n }\n\n if (tagName === 'textarea') {\n return identifyTextarea(element as HTMLTextAreaElement);\n }\n\n // Headings\n if (/^h[1-6]$/.test(tagName)) {\n return identifyHeading(element);\n }\n\n // Text elements\n if (tagName === 'p') {\n return identifyTextBlock(element, 'paragraph');\n }\n\n if (tagName === 'span') {\n const text = truncate(getVisibleText(element));\n return text ? `text: \"${text}\"` : 'text';\n }\n\n if (tagName === 'code') {\n const text = truncate(getVisibleText(element), 30);\n return text ? `code: \\`${text}\\`` : 'code';\n }\n\n if (tagName === 'pre') {\n return 'code block';\n }\n\n if (tagName === 'blockquote') {\n return 'blockquote';\n }\n\n // Media\n if (tagName === 'img') {\n return identifyImage(element as HTMLImageElement);\n }\n\n if (tagName === 'svg') {\n return identifySvg(element as SVGElement);\n }\n\n if (tagName === 'video') {\n return identifyVideo(element as HTMLVideoElement);\n }\n\n if (tagName === 'audio') {\n return 'audio';\n }\n\n if (tagName === 'canvas') {\n return 'canvas';\n }\n\n if (tagName === 'iframe') {\n return 'iframe';\n }\n\n // Table elements\n if (tagName === 'th' || tagName === 'td') {\n return identifyTableCell(element);\n }\n\n if (tagName === 'tr') {\n return 'table row';\n }\n\n if (tagName === 'table') {\n return 'table';\n }\n\n // List elements\n if (tagName === 'li') {\n return identifyListItem(element);\n }\n\n if (tagName === 'ul') {\n return 'unordered list';\n }\n\n if (tagName === 'ol') {\n return 'ordered list';\n }\n\n // Label\n if (tagName === 'label') {\n return identifyLabel(element as HTMLLabelElement);\n }\n\n // Semantic elements\n if (tagName === 'nav') {\n return 'navigation';\n }\n\n if (tagName === 'header') {\n return 'header';\n }\n\n if (tagName === 'footer') {\n return 'footer';\n }\n\n if (tagName === 'main') {\n return 'main content';\n }\n\n if (tagName === 'aside') {\n return 'sidebar';\n }\n\n if (tagName === 'article') {\n return 'article';\n }\n\n if (tagName === 'section') {\n return 'section';\n }\n\n if (tagName === 'form') {\n return 'form';\n }\n\n if (tagName === 'figure') {\n return 'figure';\n }\n\n if (tagName === 'figcaption') {\n return 'caption';\n }\n\n // Generic container\n return identifyContainer(element);\n}\n","/**\n * CSS class name cleaner - removes CSS module hashes and normalizes class names\n */\n\n/** Pattern to match CSS module hash suffixes like _a1b2c3 or -a1b2c3 */\nconst CSS_MODULE_HASH_PATTERN = /[-_][a-zA-Z0-9]{5,}$/;\n\n/** Pattern to match common hash patterns in class names */\nconst HASH_PATTERNS = [\n // Webpack/CSS Modules: component_abc123 or component-abc123\n /^(.+?)[-_][a-zA-Z0-9]{5,}$/,\n // Styled-components: sc-abc123\n /^sc-[a-zA-Z0-9]+$/,\n // Emotion: css-abc123\n /^css-[a-zA-Z0-9]+$/,\n // Tailwind JIT: arbitrary values like [color:red]\n /^\\[.+\\]$/,\n];\n\n/** Common utility class prefixes that should be kept as-is */\nconst UTILITY_PREFIXES = [\n 'text-',\n 'bg-',\n 'flex',\n 'grid',\n 'p-',\n 'px-',\n 'py-',\n 'm-',\n 'mx-',\n 'my-',\n 'w-',\n 'h-',\n 'min-',\n 'max-',\n 'border',\n 'rounded',\n 'shadow',\n 'opacity',\n 'font-',\n 'leading-',\n 'tracking-',\n 'space-',\n 'gap-',\n 'items-',\n 'justify-',\n 'self-',\n 'overflow-',\n 'z-',\n 'cursor-',\n 'transition',\n 'transform',\n 'scale-',\n 'rotate-',\n 'translate-',\n 'animate-',\n 'duration-',\n 'ease-',\n 'delay-',\n 'hidden',\n 'block',\n 'inline',\n 'relative',\n 'absolute',\n 'fixed',\n 'sticky',\n 'static',\n 'top-',\n 'right-',\n 'bottom-',\n 'left-',\n 'inset-',\n];\n\n/**\n * Clean a single CSS class name by removing module hashes\n */\nexport function cleanClassName(className: string): string | null {\n const trimmed = className.trim();\n\n if (!trimmed) return null;\n\n // Skip utility classes (Tailwind, etc.)\n if (UTILITY_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {\n return trimmed;\n }\n\n // Check for hash-only classes that should be removed entirely\n for (const pattern of HASH_PATTERNS.slice(1)) {\n if (pattern.test(trimmed)) {\n return null;\n }\n }\n\n // Try to extract the meaningful part before the hash\n const match = trimmed.match(HASH_PATTERNS[0]);\n if (match) {\n return match[1];\n }\n\n // Check for simple hash suffix pattern\n if (CSS_MODULE_HASH_PATTERN.test(trimmed)) {\n return trimmed.replace(CSS_MODULE_HASH_PATTERN, '');\n }\n\n return trimmed;\n}\n\n/**\n * Clean a list of class names, removing hashes and duplicates\n */\nexport function cleanClassList(classList: DOMTokenList | string[]): string[] {\n const classes = Array.isArray(classList) ? classList : Array.from(classList);\n const cleaned = new Set<string>();\n\n for (const className of classes) {\n const cleanedName = cleanClassName(className);\n if (cleanedName) {\n cleaned.add(cleanedName);\n }\n }\n\n return Array.from(cleaned);\n}\n\n/**\n * Get meaningful classes from an element (excludes hashes and common utilities)\n */\nexport function getMeaningfulClasses(element: Element): string[] {\n const cleaned = cleanClassList(element.classList);\n\n // Filter out single-character classes and very short ones\n return cleaned.filter((cls) => cls.length > 2);\n}\n\n/**\n * Get the first meaningful class from an element, suitable for CSS selectors\n */\nexport function getFirstMeaningfulClass(element: Element): string | null {\n const meaningful = getMeaningfulClasses(element);\n\n // Prefer classes that look like semantic names (not utilities)\n const semantic = meaningful.find(\n (cls) => !UTILITY_PREFIXES.some((prefix) => cls.startsWith(prefix))\n );\n\n return semantic || meaningful[0] || null;\n}\n\n/**\n * Format classes as a CSS class selector string\n */\nexport function formatClassSelector(classes: string[]): string {\n if (classes.length === 0) return '';\n return '.' + classes.join('.');\n}\n","/**\n * CSS selector path generator\n */\n\nimport { getFirstMeaningfulClass, cleanClassName } from '../utils/css-cleaner';\n\nconst MAX_PATH_DEPTH = 4;\n\n/** Elements that don't contribute meaningfully to paths */\nconst SKIP_TAGS = new Set(['html', 'body', 'main', 'div', 'span']);\n\n/** Elements that are good path anchors */\nconst ANCHOR_TAGS = new Set([\n 'header',\n 'footer',\n 'nav',\n 'aside',\n 'article',\n 'section',\n 'form',\n 'table',\n 'ul',\n 'ol',\n 'dialog',\n]);\n\n/**\n * Get a selector segment for a single element\n */\nfunction getElementSelector(element: Element): string {\n const tagName = element.tagName.toLowerCase();\n\n // ID is the strongest selector\n if (element.id) {\n // Clean potential hash from ID\n const cleanId = cleanClassName(element.id);\n if (cleanId && cleanId === element.id) {\n return `#${element.id}`;\n }\n }\n\n // Get meaningful class\n const meaningfulClass = getFirstMeaningfulClass(element);\n\n // For semantic elements, prefer tag name\n if (ANCHOR_TAGS.has(tagName)) {\n return meaningfulClass ? `${tagName}.${meaningfulClass}` : tagName;\n }\n\n // For generic elements, prefer class\n if (meaningfulClass) {\n // If it's a div/span, just use the class\n if (SKIP_TAGS.has(tagName)) {\n return `.${meaningfulClass}`;\n }\n return `${tagName}.${meaningfulClass}`;\n }\n\n // Check for role attribute\n const role = element.getAttribute('role');\n if (role) {\n return `[role=\"${role}\"]`;\n }\n\n // Check for data-testid\n const testId = element.getAttribute('data-testid') || element.getAttribute('data-test-id');\n if (testId) {\n return `[data-testid=\"${testId}\"]`;\n }\n\n // Check for name attribute on form elements\n if (element instanceof HTMLInputElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement) {\n if (element.name) {\n return `${tagName}[name=\"${element.name}\"]`;\n }\n }\n\n // Check for type on buttons/inputs\n if (element instanceof HTMLInputElement || element instanceof HTMLButtonElement) {\n const type = element.type;\n if (type && type !== 'text' && type !== 'submit') {\n return `${tagName}[type=\"${type}\"]`;\n }\n }\n\n // Check for href on links\n if (element instanceof HTMLAnchorElement && element.href) {\n try {\n const url = new URL(element.href);\n if (url.origin === window.location.origin && url.pathname !== '/') {\n // Use path for internal links\n return `a[href=\"${url.pathname}\"]`;\n }\n } catch {\n // Ignore URL parsing errors\n }\n }\n\n // Fall back to tag name\n return tagName;\n}\n\n/**\n * Check if a selector uniquely identifies the element\n */\nfunction isUniqueSelector(selector: string, element: Element): boolean {\n try {\n const matches = document.querySelectorAll(selector);\n return matches.length === 1 && matches[0] === element;\n } catch {\n return false;\n }\n}\n\n/**\n * Get nth-child suffix if needed for uniqueness\n */\nfunction getNthChildSuffix(element: Element): string {\n const parent = element.parentElement;\n if (!parent) return '';\n\n const siblings = Array.from(parent.children).filter(\n (child) => child.tagName === element.tagName\n );\n\n if (siblings.length <= 1) return '';\n\n const index = siblings.indexOf(element) + 1;\n return `:nth-of-type(${index})`;\n}\n\n/**\n * Build path segments from element to a good ancestor\n */\nfunction buildPathSegments(element: Element): string[] {\n const segments: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < MAX_PATH_DEPTH) {\n const tagName = current.tagName.toLowerCase();\n\n // Stop at body/html\n if (tagName === 'body' || tagName === 'html') {\n break;\n }\n\n const selector = getElementSelector(current);\n\n // If we find an ID, we can stop\n if (selector.startsWith('#')) {\n segments.unshift(selector);\n break;\n }\n\n // Skip meaningless containers unless they have useful selectors\n if (SKIP_TAGS.has(tagName) && selector === tagName) {\n current = current.parentElement;\n continue;\n }\n\n segments.unshift(selector);\n depth++;\n\n // If we reach an anchor tag, we might be able to stop\n if (ANCHOR_TAGS.has(tagName) && depth >= 2) {\n break;\n }\n\n current = current.parentElement;\n }\n\n return segments;\n}\n\n/**\n * Generate a CSS selector path for an element\n *\n * Goals:\n * - Maximum 4 levels deep\n * - Prefer IDs > meaningful classes > tag names\n * - Clean CSS module hashes\n */\nexport function generateSelectorPath(element: Element): string {\n // First, try direct unique selectors\n const directSelector = getElementSelector(element);\n if (directSelector.startsWith('#') || isUniqueSelector(directSelector, element)) {\n return directSelector;\n }\n\n // Build path segments\n const segments = buildPathSegments(element);\n\n if (segments.length === 0) {\n return element.tagName.toLowerCase();\n }\n\n // Try the path as-is\n let path = segments.join(' > ');\n if (isUniqueSelector(path, element)) {\n return path;\n }\n\n // Add nth-child to the last segment if needed\n const lastSegment = segments[segments.length - 1];\n const nthSuffix = getNthChildSuffix(element);\n if (nthSuffix) {\n segments[segments.length - 1] = lastSegment + nthSuffix;\n path = segments.join(' > ');\n if (isUniqueSelector(path, element)) {\n return path;\n }\n }\n\n // If still not unique, just return the path (best effort)\n return path;\n}\n\n/**\n * Generate a full DOM path (for forensic output)\n * Returns complete ancestry from html to element\n */\nexport function generateFullDomPath(element: Element): string {\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current) {\n const tagName = current.tagName.toLowerCase();\n\n if (tagName === 'html') {\n segments.unshift('html');\n break;\n }\n\n let segment = tagName;\n\n // Add ID if present\n if (current.id) {\n segment += `#${current.id}`;\n }\n\n // Add classes\n const classes = Array.from(current.classList).slice(0, 3);\n if (classes.length > 0) {\n segment += '.' + classes.join('.');\n }\n\n // Add nth-child for non-unique elements\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children);\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n segment += `:nth-child(${index})`;\n }\n }\n\n segments.unshift(segment);\n current = current.parentElement;\n }\n\n return segments.join(' > ');\n}\n\n/**\n * Generate a simple path for display purposes\n * More readable than selector path, shows hierarchy\n */\nexport function generateDisplayPath(element: Element): string {\n const segments: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < 4) {\n const tagName = current.tagName.toLowerCase();\n\n if (tagName === 'body' || tagName === 'html') {\n break;\n }\n\n let segment = tagName;\n\n // Add ID if present\n if (current.id) {\n segment = `#${current.id}`;\n } else {\n // Add first meaningful class\n const cls = getFirstMeaningfulClass(current);\n if (cls) {\n segment = SKIP_TAGS.has(tagName) ? `.${cls}` : `${tagName}.${cls}`;\n }\n }\n\n segments.unshift(segment);\n\n // Stop at ID\n if (current.id) break;\n\n current = current.parentElement;\n depth++;\n }\n\n return segments.join(' > ');\n}\n","/**\n * Accessibility information collection\n */\n\nimport type { AccessibilityInfo } from '../types';\n\n/** Selectors for interactive elements */\nconst INTERACTIVE_SELECTORS = [\n 'a[href]',\n 'button',\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"menuitem\"]',\n '[role=\"tab\"]',\n '[role=\"option\"]',\n '[role=\"switch\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"combobox\"]',\n '[contenteditable=\"true\"]',\n];\n\n/**\n * Check if an element is interactive (focusable and activatable)\n */\nexport function isInteractive(element: Element): boolean {\n // Check if matches any interactive selector\n for (const selector of INTERACTIVE_SELECTORS) {\n try {\n if (element.matches(selector)) {\n return true;\n }\n } catch {\n // Ignore invalid selectors\n }\n }\n\n // Check for click handlers (heuristic)\n if (element.hasAttribute('onclick') || element.hasAttribute('data-onclick')) {\n return true;\n }\n\n // Check cursor style (heuristic)\n const style = window.getComputedStyle(element);\n if (style.cursor === 'pointer') {\n return true;\n }\n\n return false;\n}\n\n/**\n * Get the ARIA role of an element\n */\nfunction getRole(element: Element): string | null {\n // Explicit role\n const explicitRole = element.getAttribute('role');\n if (explicitRole) {\n return explicitRole;\n }\n\n // Implicit roles based on tag name\n const tagName = element.tagName.toLowerCase();\n const implicitRoles: Record<string, string | null> = {\n a: element.hasAttribute('href') ? 'link' : null,\n article: 'article',\n aside: 'complementary',\n button: 'button',\n dialog: 'dialog',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n input: getInputRole(element as HTMLInputElement),\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') || element.hasAttribute('aria-labelledby') ? 'region' : null,\n select: 'combobox',\n table: 'table',\n tbody: 'rowgroup',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n thead: 'rowgroup',\n tr: 'row',\n ul: 'list',\n } as Record<string, string | null>;\n\n return implicitRoles[tagName] || null;\n}\n\n/**\n * Get implicit role for input element based on type\n */\nfunction getInputRole(element: HTMLInputElement): string | null {\n const type = element.type;\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n image: 'button',\n number: 'spinbutton',\n radio: 'radio',\n range: 'slider',\n reset: 'button',\n search: 'searchbox',\n submit: 'button',\n tel: 'textbox',\n text: 'textbox',\n url: 'textbox',\n };\n\n return inputRoles[type] || 'textbox';\n}\n\n/**\n * Get tab index, returning null if not set\n */\nfunction getTabIndex(element: Element): number | null {\n if (element.hasAttribute('tabindex')) {\n return (element as HTMLElement).tabIndex;\n }\n\n // Return implied tabindex for natively focusable elements\n if (element.matches('a[href], button, input, select, textarea, [contenteditable=\"true\"]')) {\n return 0;\n }\n\n return null;\n}\n\n/**\n * Get referenced element text by ID\n */\nfunction getReferencedText(attrValue: string | null): string | null {\n if (!attrValue) return null;\n\n const ids = attrValue.split(/\\s+/);\n const texts: string[] = [];\n\n for (const id of ids) {\n const element = document.getElementById(id);\n if (element) {\n const text = element.textContent?.trim();\n if (text) {\n texts.push(text);\n }\n }\n }\n\n return texts.length > 0 ? texts.join(' ') : null;\n}\n\n/**\n * Collect accessibility information for an element\n */\nexport function getAccessibilityInfo(element: Element): AccessibilityInfo {\n return {\n role: getRole(element),\n ariaLabel: element.getAttribute('aria-label'),\n ariaDescribedBy: getReferencedText(element.getAttribute('aria-describedby')),\n ariaLabelledBy: getReferencedText(element.getAttribute('aria-labelledby')),\n tabIndex: getTabIndex(element),\n isInteractive: isInteractive(element),\n };\n}\n\n/**\n * Format accessibility info as a string for output\n */\nexport function formatAccessibilityInfo(info: AccessibilityInfo): string {\n const parts: string[] = [];\n\n if (info.role) {\n parts.push(`Role: ${info.role}`);\n }\n\n if (info.ariaLabel) {\n parts.push(`Label: \"${info.ariaLabel}\"`);\n }\n\n if (info.ariaLabelledBy) {\n parts.push(`Labelled by: \"${info.ariaLabelledBy}\"`);\n }\n\n if (info.ariaDescribedBy) {\n parts.push(`Described by: \"${info.ariaDescribedBy}\"`);\n }\n\n if (info.tabIndex !== null) {\n parts.push(`Tab index: ${info.tabIndex}`);\n }\n\n if (info.isInteractive) {\n parts.push('Interactive: yes');\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Get the containing landmark element, if any\n */\nexport function getContainingLandmark(element: Element): Element | null {\n const landmarkRoles = ['banner', 'complementary', 'contentinfo', 'form', 'main', 'navigation', 'region', 'search'];\n const landmarkTags = ['header', 'footer', 'nav', 'main', 'aside', 'form', 'section'];\n\n let current = element.parentElement;\n\n while (current && current !== document.body) {\n const role = current.getAttribute('role');\n if (role && landmarkRoles.includes(role)) {\n return current;\n }\n\n const tagName = current.tagName.toLowerCase();\n if (landmarkTags.includes(tagName)) {\n // Section needs aria-label to be a landmark\n if (tagName === 'section') {\n if (current.hasAttribute('aria-label') || current.hasAttribute('aria-labelledby')) {\n return current;\n }\n } else {\n return current;\n }\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\n/**\n * Describe a landmark element\n */\nexport function describeLandmark(element: Element | null): string | null {\n if (!element) return null;\n\n const role = element.getAttribute('role') || element.tagName.toLowerCase();\n const label = element.getAttribute('aria-label');\n\n if (label) {\n return `${role} \"${label}\"`;\n }\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labelText = getReferencedText(labelledBy);\n if (labelText) {\n return `${role} \"${labelText}\"`;\n }\n }\n\n return role;\n}\n","/**\n * Computed style collection for elements\n */\n\nimport type { ComputedStylesSubset } from '../types';\n\n/** Default/browser values that should be excluded from output */\nconst DEFAULT_VALUES = new Set([\n 'none',\n 'normal',\n 'auto',\n '0px',\n '0',\n 'transparent',\n 'static',\n 'visible',\n 'start',\n 'baseline',\n 'stretch',\n 'currentcolor',\n 'rgba(0, 0, 0, 0)',\n 'rgb(0, 0, 0)',\n 'initial',\n 'inherit',\n 'unset',\n]);\n\n/** Style properties relevant for text elements */\nconst TEXT_PROPERTIES = [\n 'color',\n 'fontSize',\n 'fontWeight',\n 'fontFamily',\n 'lineHeight',\n 'textAlign',\n 'textDecoration',\n 'letterSpacing',\n 'textTransform',\n];\n\n/** Style properties relevant for buttons/links */\nconst BUTTON_PROPERTIES = [\n 'backgroundColor',\n 'color',\n 'padding',\n 'borderRadius',\n 'fontSize',\n 'fontWeight',\n 'border',\n 'boxShadow',\n 'cursor',\n];\n\n/** Style properties relevant for form inputs */\nconst INPUT_PROPERTIES = [\n 'backgroundColor',\n 'color',\n 'padding',\n 'borderRadius',\n 'fontSize',\n 'border',\n 'outline',\n 'boxShadow',\n];\n\n/** Style properties relevant for media elements */\nconst MEDIA_PROPERTIES = [\n 'width',\n 'height',\n 'objectFit',\n 'borderRadius',\n 'boxShadow',\n 'border',\n];\n\n/** Style properties relevant for containers */\nconst CONTAINER_PROPERTIES = [\n 'display',\n 'flexDirection',\n 'justifyContent',\n 'alignItems',\n 'gap',\n 'padding',\n 'margin',\n 'backgroundColor',\n 'borderRadius',\n 'boxShadow',\n];\n\n/** Full list of properties for forensic output */\nconst FORENSIC_PROPERTIES = [\n // Colors\n 'color',\n 'backgroundColor',\n 'borderColor',\n 'outlineColor',\n // Typography\n 'fontFamily',\n 'fontSize',\n 'fontWeight',\n 'fontStyle',\n 'lineHeight',\n 'letterSpacing',\n 'textAlign',\n 'textDecoration',\n 'textTransform',\n 'whiteSpace',\n 'wordBreak',\n 'wordSpacing',\n // Box Model\n 'width',\n 'height',\n 'minWidth',\n 'minHeight',\n 'maxWidth',\n 'maxHeight',\n 'padding',\n 'paddingTop',\n 'paddingRight',\n 'paddingBottom',\n 'paddingLeft',\n 'margin',\n 'marginTop',\n 'marginRight',\n 'marginBottom',\n 'marginLeft',\n 'border',\n 'borderWidth',\n 'borderStyle',\n 'borderRadius',\n 'boxSizing',\n // Layout\n 'display',\n 'position',\n 'top',\n 'right',\n 'bottom',\n 'left',\n 'float',\n 'clear',\n 'flexDirection',\n 'flexWrap',\n 'justifyContent',\n 'alignItems',\n 'alignContent',\n 'alignSelf',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'flexBasis',\n 'order',\n 'gap',\n 'gridTemplateColumns',\n 'gridTemplateRows',\n 'gridColumn',\n 'gridRow',\n // Visual Effects\n 'opacity',\n 'visibility',\n 'overflow',\n 'overflowX',\n 'overflowY',\n 'boxShadow',\n 'textShadow',\n 'filter',\n 'backdropFilter',\n // Transform\n 'transform',\n 'transformOrigin',\n 'transition',\n 'animation',\n // Other\n 'zIndex',\n 'cursor',\n 'pointerEvents',\n 'userSelect',\n 'objectFit',\n 'objectPosition',\n];\n\n/**\n * Determine element category for style selection\n */\nfunction getElementCategory(element: Element): 'text' | 'button' | 'input' | 'media' | 'container' {\n const tagName = element.tagName.toLowerCase();\n\n // Buttons\n if (\n tagName === 'button' ||\n element.getAttribute('role') === 'button' ||\n (element instanceof HTMLInputElement &&\n ['button', 'submit', 'reset'].includes(element.type))\n ) {\n return 'button';\n }\n\n // Links\n if (tagName === 'a') {\n return 'button';\n }\n\n // Form inputs\n if (tagName === 'input' || tagName === 'select' || tagName === 'textarea') {\n return 'input';\n }\n\n // Media\n if (tagName === 'img' || tagName === 'video' || tagName === 'canvas' || tagName === 'svg') {\n return 'media';\n }\n\n // Text elements\n if (\n /^h[1-6]$/.test(tagName) ||\n tagName === 'p' ||\n tagName === 'span' ||\n tagName === 'label' ||\n tagName === 'code' ||\n tagName === 'pre' ||\n tagName === 'blockquote' ||\n tagName === 'li'\n ) {\n return 'text';\n }\n\n // Default to container\n return 'container';\n}\n\n/**\n * Get relevant style properties for an element category\n */\nfunction getRelevantProperties(category: 'text' | 'button' | 'input' | 'media' | 'container'): string[] {\n switch (category) {\n case 'text':\n return TEXT_PROPERTIES;\n case 'button':\n return BUTTON_PROPERTIES;\n case 'input':\n return INPUT_PROPERTIES;\n case 'media':\n return MEDIA_PROPERTIES;\n case 'container':\n return CONTAINER_PROPERTIES;\n }\n}\n\n/**\n * Check if a style value is a default/meaningless value\n */\nfunction isDefaultValue(value: string): boolean {\n if (!value) return true;\n const normalized = value.toLowerCase().trim();\n return DEFAULT_VALUES.has(normalized);\n}\n\n/**\n * Format a CSS property name for output\n */\nfunction formatPropertyName(camelCase: string): string {\n return camelCase.replace(/([A-Z])/g, '-$1').toLowerCase();\n}\n\n/**\n * Collect contextual styles (relevant to element type)\n */\nexport function getContextualStyles(element: Element): Record<string, string> {\n const category = getElementCategory(element);\n const properties = getRelevantProperties(category);\n const computed = window.getComputedStyle(element);\n const result: Record<string, string> = {};\n\n for (const prop of properties) {\n const value = computed.getPropertyValue(formatPropertyName(prop)) ||\n (computed as unknown as Record<string, string>)[prop];\n\n if (value && !isDefaultValue(value)) {\n result[prop] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Collect full computed styles for forensic output\n */\nexport function getForensicStyles(element: Element): ComputedStylesSubset {\n const computed = window.getComputedStyle(element);\n\n return {\n display: computed.display,\n position: computed.position,\n visibility: computed.visibility,\n opacity: computed.opacity,\n zIndex: computed.zIndex,\n overflow: computed.overflow,\n pointerEvents: computed.pointerEvents,\n cursor: computed.cursor,\n backgroundColor: computed.backgroundColor,\n color: computed.color,\n fontSize: computed.fontSize,\n fontFamily: computed.fontFamily,\n fontWeight: computed.fontWeight,\n lineHeight: computed.lineHeight,\n padding: computed.padding,\n margin: computed.margin,\n border: computed.border,\n borderRadius: computed.borderRadius,\n boxShadow: computed.boxShadow,\n transform: computed.transform,\n transition: computed.transition,\n };\n}\n\n/**\n * Collect all non-default forensic styles\n */\nexport function getAllForensicStyles(element: Element): Record<string, string> {\n const computed = window.getComputedStyle(element);\n const result: Record<string, string> = {};\n\n for (const prop of FORENSIC_PROPERTIES) {\n const kebabProp = formatPropertyName(prop);\n const value = computed.getPropertyValue(kebabProp);\n\n if (value && !isDefaultValue(value)) {\n result[kebabProp] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Format styles as a string for output\n */\nexport function formatStyles(styles: Record<string, string>): string {\n return Object.entries(styles)\n .map(([prop, value]) => `${formatPropertyName(prop)}: ${value}`)\n .join('\\n');\n}\n\n/**\n * Format styles as inline CSS\n */\nexport function formatInlineStyles(styles: Record<string, string>): string {\n return Object.entries(styles)\n .map(([prop, value]) => `${formatPropertyName(prop)}: ${value};`)\n .join(' ');\n}\n","/**\n * Fixed/sticky element detection utilities\n */\n\n/**\n * Check if an element or any of its ancestors has fixed or sticky positioning\n */\nexport function isFixedOrSticky(element: Element | null): boolean {\n let current = element;\n\n while (current && current !== document.body && current !== document.documentElement) {\n const style = window.getComputedStyle(current);\n const position = style.position;\n\n if (position === 'fixed' || position === 'sticky') {\n return true;\n }\n\n current = current.parentElement;\n }\n\n return false;\n}\n\n/**\n * Get the fixed/sticky ancestor if one exists\n */\nexport function getFixedAncestor(element: Element | null): Element | null {\n let current = element;\n\n while (current && current !== document.body && current !== document.documentElement) {\n const style = window.getComputedStyle(current);\n const position = style.position;\n\n if (position === 'fixed' || position === 'sticky') {\n return current;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\n/**\n * Get the position of an element relative to either viewport (if fixed) or document\n */\nexport function getElementPosition(element: Element): {\n x: number;\n y: number;\n isFixed: boolean;\n} {\n const rect = element.getBoundingClientRect();\n const isFixed = isFixedOrSticky(element);\n\n if (isFixed) {\n // For fixed elements, use viewport-relative position\n return {\n x: rect.left,\n y: rect.top,\n isFixed: true,\n };\n }\n\n // For non-fixed elements, use document-relative position\n return {\n x: rect.left + window.scrollX,\n y: rect.top + window.scrollY,\n isFixed: false,\n };\n}\n\n/**\n * Convert percentage position to pixels for a given viewport dimension\n */\nexport function percentToPixels(percent: number, viewportDimension: number): number {\n return (percent / 100) * viewportDimension;\n}\n\n/**\n * Convert pixel position to percentage of viewport\n */\nexport function pixelsToPercent(pixels: number, viewportDimension: number): number {\n return (pixels / viewportDimension) * 100;\n}\n","/**\n * Element analysis module - re-exports\n */\n\nexport { identifyElement } from './identifier';\nexport {\n generateSelectorPath,\n generateFullDomPath,\n generateDisplayPath,\n} from './path-generator';\nexport {\n getAccessibilityInfo,\n formatAccessibilityInfo,\n isInteractive,\n getContainingLandmark,\n describeLandmark,\n} from './accessibility';\nexport {\n getContextualStyles,\n getForensicStyles,\n getAllForensicStyles,\n formatStyles,\n formatInlineStyles,\n} from './styles';\n\nimport type { ElementInfo, ElementRect, NearbyContext } from '../types';\nimport { identifyElement } from './identifier';\nimport { generateSelectorPath, generateFullDomPath } from './path-generator';\nimport { getAccessibilityInfo, getContainingLandmark, describeLandmark } from './accessibility';\nimport { getForensicStyles } from './styles';\nimport { isFixedOrSticky } from '../utils/fixed-detection';\nimport { getMeaningfulClasses } from '../utils/css-cleaner';\n\nconst MAX_TEXT_LENGTH = 200;\n\n/**\n * Get the bounding rectangle of an element\n */\nexport function getElementRect(element: Element): ElementRect {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n bottom: rect.bottom,\n right: rect.right,\n };\n}\n\n/**\n * Get nearby context (parent, siblings)\n */\nexport function getNearbyContext(element: Element): NearbyContext {\n const parent = element.parentElement;\n const prevSibling = element.previousElementSibling;\n const nextSibling = element.nextElementSibling;\n const landmark = getContainingLandmark(element);\n\n return {\n parent: parent ? identifyElement(parent) : null,\n previousSibling: prevSibling ? identifyElement(prevSibling) : null,\n nextSibling: nextSibling ? identifyElement(nextSibling) : null,\n containingLandmark: describeLandmark(landmark),\n };\n}\n\n/**\n * Get element attributes as a record\n */\nexport function getElementAttributes(element: Element): Record<string, string> {\n const result: Record<string, string> = {};\n const skipAttrs = new Set(['class', 'style', 'id']); // Already captured elsewhere\n\n for (const attr of Array.from(element.attributes)) {\n if (!skipAttrs.has(attr.name)) {\n result[attr.name] = attr.value;\n }\n }\n\n return result;\n}\n\n/**\n * Get truncated inner text\n */\nexport function getInnerText(element: Element): string {\n const text = element.textContent || '';\n const cleaned = text.trim().replace(/\\s+/g, ' ');\n\n if (cleaned.length <= MAX_TEXT_LENGTH) {\n return cleaned;\n }\n\n return cleaned.slice(0, MAX_TEXT_LENGTH - 3) + '...';\n}\n\n/**\n * Collect complete element information\n *\n * @param element - The DOM element to analyze\n * @param includeForensic - Whether to include forensic details (computed styles)\n */\nexport function collectElementInfo(element: Element, includeForensic: boolean = false): ElementInfo {\n return {\n humanReadable: identifyElement(element),\n selectorPath: generateSelectorPath(element),\n fullDomPath: generateFullDomPath(element),\n tagName: element.tagName.toLowerCase(),\n id: element.id || null,\n classes: getMeaningfulClasses(element),\n rect: getElementRect(element),\n accessibility: getAccessibilityInfo(element),\n computedStyles: includeForensic ? getForensicStyles(element) : null,\n nearbyContext: getNearbyContext(element),\n innerText: getInnerText(element),\n attributes: getElementAttributes(element),\n isFixed: isFixedOrSticky(element),\n };\n}\n","/**\n * Scope CRUD operations\n */\n\nimport type { Scope, AnnotationId, AppState } from '../types';\nimport type { Store } from '../store';\nimport type { EventBus } from '../event-bus';\nimport type { EventMap } from '../types';\nimport { collectElementInfo } from '../element';\n\n/**\n * Generate a unique scope ID\n */\nexport function generateAnnotationId(): AnnotationId {\n return `scope-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\n/**\n * Get the next scope number\n */\nexport function getNextScopeNumber(scopes: Map<AnnotationId, Scope>): number {\n if (scopes.size === 0) return 1;\n\n const maxNumber = Math.max(...Array.from(scopes.values()).map((s) => s.number));\n return maxNumber + 1;\n}\n\n/**\n * Create a new scope\n */\nexport function createScope(\n element: Element,\n comment: string,\n existingScopes: Map<AnnotationId, Scope>,\n options: {\n selectedText?: string | null;\n isMultiSelect?: boolean;\n includeForensic?: boolean;\n clickX?: number;\n clickY?: number;\n } = {}\n): Scope {\n const {\n selectedText = null,\n isMultiSelect = false,\n includeForensic = false,\n clickX = 0,\n clickY = 0,\n } = options;\n\n const now = Date.now();\n const elementInfo = collectElementInfo(element, includeForensic);\n\n return {\n id: generateAnnotationId(),\n number: getNextScopeNumber(existingScopes),\n comment,\n elementInfo,\n element,\n createdAt: now,\n updatedAt: now,\n selectedText,\n isMultiSelect,\n clickX,\n clickY,\n };\n}\n\n/**\n * Update an existing scope's comment\n */\nexport function updateScopeComment(scope: Scope, comment: string): Scope {\n return {\n ...scope,\n comment,\n updatedAt: Date.now(),\n };\n}\n\n/**\n * Update an existing scope's element info (e.g., after element moved)\n */\nexport function updateScopeElementInfo(scope: Scope, element: Element, includeForensic: boolean = false): Scope {\n return {\n ...scope,\n element,\n elementInfo: collectElementInfo(element, includeForensic),\n updatedAt: Date.now(),\n };\n}\n\n/**\n * Renumber scopes after deletion\n */\nexport function renumberScopes(scopes: Map<AnnotationId, Scope>, deletedNumber: number): Map<AnnotationId, Scope> {\n const newScopes = new Map<AnnotationId, Scope>();\n\n for (const [id, scope] of scopes) {\n if (scope.number > deletedNumber) {\n newScopes.set(id, {\n ...scope,\n number: scope.number - 1,\n });\n } else {\n newScopes.set(id, scope);\n }\n }\n\n return newScopes;\n}\n\n/**\n * Create scope manager bound to store and event bus\n */\nexport function createAnnotationManager(\n store: Store<AppState>,\n eventBus: EventBus<EventMap>\n) {\n /**\n * Add a new scope\n */\n const addScope = (\n element: Element,\n comment: string,\n options?: {\n selectedText?: string | null;\n isMultiSelect?: boolean;\n clickX?: number;\n clickY?: number;\n }\n ): Scope => {\n const state = store.getState();\n const includeForensic = state.settings.outputLevel === 'forensic';\n\n const scope = createScope(element, comment, state.scopes, {\n ...options,\n includeForensic,\n });\n\n const newScopes = new Map(state.scopes);\n newScopes.set(scope.id, scope);\n\n store.setState({ scopes: newScopes });\n eventBus.emit('scope:create', { scope });\n\n return scope;\n };\n\n /**\n * Update an existing scope\n */\n const updateScope = (id: AnnotationId, updates: { comment?: string }): Scope | null => {\n const state = store.getState();\n const scope = state.scopes.get(id);\n\n if (!scope) return null;\n\n const updatedScope = updates.comment !== undefined\n ? updateScopeComment(scope, updates.comment)\n : scope;\n\n const newScopes = new Map(state.scopes);\n newScopes.set(id, updatedScope);\n\n store.setState({ scopes: newScopes });\n eventBus.emit('scope:update', { scope: updatedScope });\n\n return updatedScope;\n };\n\n /**\n * Delete a scope\n */\n const deleteScope = (id: AnnotationId): boolean => {\n const state = store.getState();\n const scope = state.scopes.get(id);\n\n if (!scope) return false;\n\n const deletedNumber = scope.number;\n const newScopes = new Map(state.scopes);\n newScopes.delete(id);\n\n // Renumber remaining scopes\n const renumberedScopes = renumberScopes(newScopes, deletedNumber);\n\n store.batch(() => {\n store.setState({\n scopes: renumberedScopes,\n deletingMarkerId: id,\n renumberFrom: deletedNumber,\n });\n\n // Clear the deleting state after animation\n setTimeout(() => {\n store.setState({\n deletingMarkerId: null,\n renumberFrom: null,\n });\n }, 300);\n });\n\n eventBus.emit('scope:delete', { id });\n\n return true;\n };\n\n /**\n * Clear all scopes\n */\n const clearAllScopes = (): Scope[] => {\n const state = store.getState();\n const scopes = Array.from(state.scopes.values());\n\n store.batch(() => {\n store.setState({\n scopes: new Map(),\n selectedAnnotationId: null,\n showClearedFeedback: true,\n });\n\n setTimeout(() => {\n store.setState({ showClearedFeedback: false });\n }, 2000);\n });\n\n eventBus.emit('scopes:clear', { scopes });\n\n return scopes;\n };\n\n /**\n * Select a scope\n */\n const selectScope = (id: AnnotationId | null): void => {\n store.setState({ selectedAnnotationId: id });\n eventBus.emit('scope:select', { id });\n };\n\n /**\n * Get a scope by ID\n */\n const getScope = (id: AnnotationId): Scope | undefined => {\n return store.getState().scopes.get(id);\n };\n\n /**\n * Get all scopes sorted by number\n */\n const getAllScopes = (): Scope[] => {\n return Array.from(store.getState().scopes.values()).sort((a, b) => a.number - b.number);\n };\n\n /**\n * Get scope count\n */\n const getScopeCount = (): number => {\n return store.getState().scopes.size;\n };\n\n return {\n addScope,\n updateScope,\n deleteScope,\n clearAllScopes,\n selectScope,\n getScope,\n getAllScopes,\n getScopeCount,\n };\n}\n\nexport type AnnotationManager = ReturnType<typeof createAnnotationManager>;\n","/**\n * LocalStorage persistence for scopes and settings\n */\n\nimport type { Scope, AnnotationId, Settings, ElementInfo } from '../types';\n\nconst SCOPE_KEY_PREFIX = 'annotation-scopes-';\nconst SETTINGS_KEY = 'annotation-settings';\nconst THEME_KEY = 'annotation-theme';\n\n/** Retention period in milliseconds (7 days) */\nconst RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\n\n/**\n * Serializable version of Scope (without DOM element reference)\n */\ninterface SerializedScope {\n id: AnnotationId;\n number: number;\n comment: string;\n elementInfo: ElementInfo;\n createdAt: number;\n updatedAt: number;\n selectedText: string | null;\n isMultiSelect: boolean;\n clickX: number;\n clickY: number;\n}\n\n/**\n * Get storage key for current page\n */\nfunction getScopeStorageKey(): string {\n return SCOPE_KEY_PREFIX + window.location.pathname;\n}\n\n/**\n * Serialize a scope for storage\n */\nfunction serializeScope(scope: Scope): SerializedScope {\n return {\n id: scope.id,\n number: scope.number,\n comment: scope.comment,\n elementInfo: scope.elementInfo,\n createdAt: scope.createdAt,\n updatedAt: scope.updatedAt,\n selectedText: scope.selectedText,\n isMultiSelect: scope.isMultiSelect,\n clickX: scope.clickX,\n clickY: scope.clickY,\n };\n}\n\n/**\n * Deserialize a scope from storage\n */\nfunction deserializeScope(data: SerializedScope): Scope {\n return {\n ...data,\n element: null, // DOM reference can't be restored\n };\n}\n\n/**\n * Filter out expired scopes\n */\nfunction filterExpired(scopes: SerializedScope[]): SerializedScope[] {\n const cutoff = Date.now() - RETENTION_MS;\n return scopes.filter((scope) => scope.createdAt > cutoff);\n}\n\n/**\n * Save scopes to LocalStorage\n */\nexport function saveScopes(scopes: Map<AnnotationId, Scope>): boolean {\n try {\n const key = getScopeStorageKey();\n const serialized = Array.from(scopes.values()).map(serializeScope);\n localStorage.setItem(key, JSON.stringify(serialized));\n return true;\n } catch (error) {\n console.error('[Annotation] Failed to save scopes:', error);\n return false;\n }\n}\n\n/**\n * Load scopes from LocalStorage\n */\nexport function loadScopes(): Map<AnnotationId, Scope> {\n try {\n const key = getScopeStorageKey();\n const stored = localStorage.getItem(key);\n\n if (!stored) {\n return new Map();\n }\n\n const parsed = JSON.parse(stored) as SerializedScope[];\n const filtered = filterExpired(parsed);\n\n // If we filtered out expired scopes, save the cleaned list\n if (filtered.length !== parsed.length) {\n localStorage.setItem(key, JSON.stringify(filtered));\n }\n\n const scopes = new Map<AnnotationId, Scope>();\n for (const data of filtered) {\n scopes.set(data.id, deserializeScope(data));\n }\n\n return scopes;\n } catch (error) {\n console.error('[Annotation] Failed to load scopes:', error);\n return new Map();\n }\n}\n\n/**\n * Clear scopes from LocalStorage\n */\nexport function clearScopes(): boolean {\n try {\n const key = getScopeStorageKey();\n localStorage.removeItem(key);\n return true;\n } catch (error) {\n console.error('[Annotation] Failed to clear scopes:', error);\n return false;\n }\n}\n\n/**\n * Save settings to LocalStorage\n */\nexport function saveSettings(settings: Settings): boolean {\n try {\n localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));\n return true;\n } catch (error) {\n console.error('[Annotation] Failed to save settings:', error);\n return false;\n }\n}\n\n/**\n * Load settings from LocalStorage\n */\nexport function loadSettings(): Partial<Settings> | null {\n try {\n const stored = localStorage.getItem(SETTINGS_KEY);\n if (!stored) return null;\n return JSON.parse(stored) as Partial<Settings>;\n } catch (error) {\n console.error('[Annotation] Failed to load settings:', error);\n return null;\n }\n}\n\n/**\n * Save theme preference\n */\nexport function saveTheme(theme: 'light' | 'dark'): boolean {\n try {\n localStorage.setItem(THEME_KEY, theme);\n return true;\n } catch (error) {\n console.error('[Annotation] Failed to save theme:', error);\n return false;\n }\n}\n\n/**\n * Load theme preference\n */\nexport function loadTheme(): 'light' | 'dark' | null {\n try {\n const stored = localStorage.getItem(THEME_KEY);\n if (stored === 'light' || stored === 'dark') {\n return stored;\n }\n return null;\n } catch (error) {\n console.error('[Annotation] Failed to load theme:', error);\n return null;\n }\n}\n\n/**\n * Create an auto-save handler that debounces saves\n */\nexport function createAutoSaver(\n getScopes: () => Map<AnnotationId, Scope>,\n debounceMs: number = 1000\n): { save: () => void; flush: () => void; destroy: () => void } {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flush = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n saveScopes(getScopes());\n };\n\n const save = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(flush, debounceMs);\n };\n\n const destroy = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n };\n\n return { save, flush, destroy };\n}\n\n/**\n * Clean up all expired scopes across all pages\n */\nexport function cleanupExpiredScopes(): number {\n let cleaned = 0;\n\n try {\n const keys = Object.keys(localStorage);\n const cutoff = Date.now() - RETENTION_MS;\n\n for (const key of keys) {\n if (!key.startsWith(SCOPE_KEY_PREFIX)) continue;\n\n try {\n const stored = localStorage.getItem(key);\n if (!stored) continue;\n\n const parsed = JSON.parse(stored) as SerializedScope[];\n const filtered = parsed.filter((scope) => scope.createdAt > cutoff);\n\n if (filtered.length === 0) {\n localStorage.removeItem(key);\n cleaned += parsed.length;\n } else if (filtered.length !== parsed.length) {\n localStorage.setItem(key, JSON.stringify(filtered));\n cleaned += parsed.length - filtered.length;\n }\n } catch {\n // Skip malformed entries\n }\n }\n } catch (error) {\n console.error('[Annotation] Failed to cleanup expired scopes:', error);\n }\n\n return cleaned;\n}\n","/**\n * Markdown output generation for scopes\n */\n\nimport type { Scope, OutputLevel, EnvironmentInfo } from '../types';\nimport { formatStyles } from '../element/styles';\n\n/**\n * Get environment info for forensic output\n */\nexport function getEnvironmentInfo(): EnvironmentInfo {\n return {\n userAgent: navigator.userAgent,\n viewport: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n devicePixelRatio: window.devicePixelRatio,\n url: window.location.href,\n timestamp: new Date().toISOString(),\n scrollPosition: {\n x: window.scrollX,\n y: window.scrollY,\n },\n };\n}\n\n/**\n * Generate compact output for a single scope\n * Format: `1. **button \"Save\"**: Change color to blue`\n */\nfunction generateCompactScope(scope: Scope): string {\n const element = scope.elementInfo.humanReadable;\n const comment = scope.comment || '(no comment)';\n return `${scope.number}. **${element}**: ${comment}`;\n}\n\n/**\n * Generate standard output for a single scope\n */\nfunction generateStandardScope(scope: Scope): string {\n const lines: string[] = [];\n\n lines.push(`### ${scope.number}. ${scope.elementInfo.humanReadable}`);\n lines.push(`**Location:** ${scope.elementInfo.selectorPath}`);\n\n if (scope.selectedText) {\n lines.push(`**Selected text:** \"${scope.selectedText}\"`);\n }\n\n lines.push(`**Feedback:** ${scope.comment || '(no comment)'}`);\n\n return lines.join('\\n');\n}\n\n/**\n * Generate detailed output for a single scope\n */\nfunction generateDetailedScope(scope: Scope): string {\n const lines: string[] = [];\n const info = scope.elementInfo;\n\n lines.push(`### ${scope.number}. ${info.humanReadable}`);\n lines.push('');\n\n // Location info\n lines.push(`**Location:** \\`${info.selectorPath}\\``);\n\n if (info.id) {\n lines.push(`**ID:** ${info.id}`);\n }\n\n if (info.classes.length > 0) {\n lines.push(`**Classes:** ${info.classes.join(', ')}`);\n }\n\n // Position\n const rect = info.rect;\n lines.push(`**Position:** ${Math.round(rect.left)}x${Math.round(rect.top)}, ${Math.round(rect.width)}×${Math.round(rect.height)}px`);\n\n if (info.isFixed) {\n lines.push(`**Positioning:** Fixed/Sticky`);\n }\n\n // Selected text\n if (scope.selectedText) {\n lines.push(`**Selected text:** \"${scope.selectedText}\"`);\n }\n\n // Nearby context\n const ctx = info.nearbyContext;\n if (ctx.parent || ctx.containingLandmark) {\n lines.push('');\n lines.push('**Context:**');\n if (ctx.containingLandmark) {\n lines.push(`- Landmark: ${ctx.containingLandmark}`);\n }\n if (ctx.parent) {\n lines.push(`- Parent: ${ctx.parent}`);\n }\n if (ctx.previousSibling) {\n lines.push(`- Previous: ${ctx.previousSibling}`);\n }\n if (ctx.nextSibling) {\n lines.push(`- Next: ${ctx.nextSibling}`);\n }\n }\n\n lines.push('');\n lines.push(`**Feedback:** ${scope.comment || '(no comment)'}`);\n\n return lines.join('\\n');\n}\n\n/**\n * Generate forensic output for a single scope\n */\nfunction generateForensicScope(scope: Scope, _env: EnvironmentInfo): string {\n const lines: string[] = [];\n const info = scope.elementInfo;\n\n lines.push(`### ${scope.number}. ${info.humanReadable}`);\n lines.push('');\n\n // Full DOM path\n lines.push('#### DOM Path');\n lines.push('```');\n lines.push(info.fullDomPath);\n lines.push('```');\n lines.push('');\n\n // CSS Selector\n lines.push(`**Selector:** \\`${info.selectorPath}\\``);\n lines.push('');\n\n // Element details\n lines.push('#### Element Details');\n lines.push(`- **Tag:** ${info.tagName}`);\n\n if (info.id) {\n lines.push(`- **ID:** ${info.id}`);\n }\n\n if (info.classes.length > 0) {\n lines.push(`- **Classes:** ${info.classes.join(', ')}`);\n }\n\n // Attributes\n const attrEntries = Object.entries(info.attributes);\n if (attrEntries.length > 0) {\n lines.push('- **Attributes:**');\n for (const [key, value] of attrEntries.slice(0, 10)) {\n lines.push(` - ${key}: \"${value}\"`);\n }\n }\n\n // Content preview\n if (info.innerText) {\n lines.push(`- **Text content:** \"${info.innerText}\"`);\n }\n\n lines.push('');\n\n // Bounding box\n lines.push('#### Position & Dimensions');\n const rect = info.rect;\n lines.push(`- **Bounding box:** (${Math.round(rect.left)}, ${Math.round(rect.top)}) to (${Math.round(rect.right)}, ${Math.round(rect.bottom)})`);\n lines.push(`- **Size:** ${Math.round(rect.width)}×${Math.round(rect.height)}px`);\n lines.push(`- **Fixed positioning:** ${info.isFixed ? 'Yes' : 'No'}`);\n lines.push('');\n\n // Accessibility\n lines.push('#### Accessibility');\n const a11y = info.accessibility;\n lines.push(`- **Role:** ${a11y.role || 'none'}`);\n lines.push(`- **Interactive:** ${a11y.isInteractive ? 'Yes' : 'No'}`);\n\n if (a11y.ariaLabel) {\n lines.push(`- **ARIA Label:** \"${a11y.ariaLabel}\"`);\n }\n if (a11y.ariaDescribedBy) {\n lines.push(`- **Described by:** \"${a11y.ariaDescribedBy}\"`);\n }\n if (a11y.tabIndex !== null) {\n lines.push(`- **Tab index:** ${a11y.tabIndex}`);\n }\n lines.push('');\n\n // Computed styles\n if (info.computedStyles) {\n lines.push('#### Computed Styles');\n lines.push('```css');\n lines.push(formatStyles(info.computedStyles as unknown as Record<string, string>));\n lines.push('```');\n lines.push('');\n }\n\n // Context\n const ctx = info.nearbyContext;\n lines.push('#### Context');\n if (ctx.containingLandmark) {\n lines.push(`- **Landmark:** ${ctx.containingLandmark}`);\n }\n if (ctx.parent) {\n lines.push(`- **Parent:** ${ctx.parent}`);\n }\n if (ctx.previousSibling) {\n lines.push(`- **Previous sibling:** ${ctx.previousSibling}`);\n }\n if (ctx.nextSibling) {\n lines.push(`- **Next sibling:** ${ctx.nextSibling}`);\n }\n lines.push('');\n\n // Selected text\n if (scope.selectedText) {\n lines.push(`**Selected text:** \"${scope.selectedText}\"`);\n lines.push('');\n }\n\n // Multi-select info\n if (scope.isMultiSelect) {\n lines.push('*Created via multi-select*');\n lines.push('');\n }\n\n // Timestamps\n lines.push('#### Metadata');\n lines.push(`- **Created:** ${new Date(scope.createdAt).toISOString()}`);\n lines.push(`- **Updated:** ${new Date(scope.updatedAt).toISOString()}`);\n lines.push('');\n\n // Feedback\n lines.push('#### Feedback');\n lines.push(scope.comment || '(no comment)');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate header for output\n */\nfunction generateHeader(level: OutputLevel, scopeCount: number): string {\n const lines: string[] = [];\n const path = window.location.pathname;\n\n lines.push(`## Page Feedback: ${path}`);\n\n if (level === 'compact') {\n lines.push('');\n return lines.join('\\n');\n }\n\n lines.push(`**Viewport:** ${window.innerWidth}×${window.innerHeight}`);\n lines.push(`**Scopes:** ${scopeCount}`);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate forensic header with full environment info\n */\nfunction generateForensicHeader(env: EnvironmentInfo, scopeCount: number): string {\n const lines: string[] = [];\n\n lines.push(`## Page Feedback: ${env.url}`);\n lines.push('');\n lines.push('### Environment');\n lines.push(`- **URL:** ${env.url}`);\n lines.push(`- **Viewport:** ${env.viewport.width}×${env.viewport.height}`);\n lines.push(`- **Device pixel ratio:** ${env.devicePixelRatio}`);\n lines.push(`- **Scroll position:** (${env.scrollPosition.x}, ${env.scrollPosition.y})`);\n lines.push(`- **Timestamp:** ${env.timestamp}`);\n lines.push(`- **User agent:** ${env.userAgent}`);\n lines.push(`- **Total scopes:** ${scopeCount}`);\n lines.push('');\n lines.push('---');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate markdown output for all scopes\n */\nexport function generateOutput(scopes: Scope[], level: OutputLevel): string {\n if (scopes.length === 0) {\n return '## Page Feedback\\n\\nNo scopes created.';\n }\n\n const sortedScopes = [...scopes].sort((a, b) => a.number - b.number);\n const env = level === 'forensic' ? getEnvironmentInfo() : null;\n\n const parts: string[] = [];\n\n // Header\n if (level === 'forensic' && env) {\n parts.push(generateForensicHeader(env, scopes.length));\n } else {\n parts.push(generateHeader(level, scopes.length));\n }\n\n // Scope content\n for (const scope of sortedScopes) {\n switch (level) {\n case 'compact':\n parts.push(generateCompactScope(scope));\n break;\n case 'standard':\n parts.push(generateStandardScope(scope));\n break;\n case 'detailed':\n parts.push(generateDetailedScope(scope));\n break;\n case 'forensic':\n parts.push(generateForensicScope(scope, env!));\n break;\n }\n\n // Add separator between scopes for non-compact levels\n if (level !== 'compact') {\n parts.push('');\n parts.push('---');\n parts.push('');\n }\n }\n\n // For compact level, join with newlines\n if (level === 'compact') {\n return parts.join('\\n');\n }\n\n return parts.join('\\n').trim();\n}\n\n/**\n * Copy output to clipboard\n */\nexport async function copyToClipboard(content: string): Promise<boolean> {\n try {\n await navigator.clipboard.writeText(content);\n return true;\n } catch (error) {\n // Fallback for older browsers\n try {\n const textarea = document.createElement('textarea');\n textarea.value = content;\n textarea.style.position = 'fixed';\n textarea.style.left = '-9999px';\n document.body.appendChild(textarea);\n textarea.select();\n const success = document.execCommand('copy');\n document.body.removeChild(textarea);\n return success;\n } catch {\n console.error('[Annotation] Failed to copy to clipboard:', error);\n return false;\n }\n }\n}\n","/**\n * DOM event handling for Annotation\n */\n\nimport type { AppState, Position } from '../types';\nimport type { Store } from '../store';\nimport type { EventBus } from '../event-bus';\nimport type { EventMap } from '../types';\nimport { collectElementInfo } from '../element';\n\n/** Data attributes used by Annotation */\nconst DATA_TOOLBAR = 'data-annotation-toolbar';\nconst DATA_MARKER = 'data-annotation-marker';\nconst DATA_POPUP = 'data-annotation-popup';\nconst DATA_SETTINGS = 'data-annotation-settings';\n\n/**\n * Check if an element is part of the Annotation UI\n */\nexport function isAnnotationElement(element: Element | null): boolean {\n if (!element) return false;\n\n // Check for the custom element itself (clicks on shadow DOM elements appear as the host)\n if (element.tagName.toLowerCase() === 'agent-ui-annotation') {\n return true;\n }\n\n // Check for the closest agent-ui-annotation ancestor\n if (element.closest('agent-ui-annotation')) {\n return true;\n }\n\n // Check for data attributes (for non-shadow-dom scenarios)\n return (\n element.hasAttribute(DATA_TOOLBAR) ||\n element.hasAttribute(DATA_MARKER) ||\n element.hasAttribute(DATA_POPUP) ||\n element.hasAttribute(DATA_SETTINGS) ||\n element.closest(`[${DATA_TOOLBAR}], [${DATA_MARKER}], [${DATA_POPUP}], [${DATA_SETTINGS}]`) !== null\n );\n}\n\n/**\n * Check if a mouse event originated from within Annotation UI (including shadow DOM)\n */\nexport function isAnnotationEvent(event: MouseEvent): boolean {\n // Use composedPath to check the actual event path including shadow DOM\n const path = event.composedPath();\n for (const target of path) {\n if (target instanceof Element) {\n if (target.tagName.toLowerCase() === 'agent-ui-annotation') {\n return true;\n }\n if (target.hasAttribute && (\n target.hasAttribute(DATA_TOOLBAR) ||\n target.hasAttribute(DATA_MARKER) ||\n target.hasAttribute(DATA_POPUP) ||\n target.hasAttribute(DATA_SETTINGS)\n )) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Get the target element from a mouse event, excluding Annotation elements\n */\nexport function getTargetElement(event: MouseEvent): Element | null {\n const target = event.target as Element;\n\n if (isAnnotationElement(target)) {\n return null;\n }\n\n return target;\n}\n\n/**\n * Get current text selection\n */\nexport function getSelectedText(): string | null {\n const selection = window.getSelection();\n if (!selection || selection.isCollapsed) {\n return null;\n }\n\n const text = selection.toString().trim();\n return text.length > 0 ? text : null;\n}\n\n/**\n * Create DOM event handlers bound to store and event bus\n */\nexport function createEventHandlers(\n store: Store<AppState>,\n eventBus: EventBus<EventMap>\n) {\n let isActive = false;\n\n /**\n * Handle click events\n */\n const handleClick = (event: MouseEvent) => {\n const state = store.getState();\n\n if (state.mode === 'disabled') return;\n\n // Check composedPath to properly detect clicks inside shadow DOM\n if (isAnnotationEvent(event)) return;\n\n // Don't process element selection when settings panel is open\n if (state.settingsPanelVisible) return;\n\n const target = getTargetElement(event);\n if (!target) return;\n\n // Prevent default only when active and targeting interactive elements\n if (state.settings.blockInteractions) {\n const isInteractive = target.matches('a, button, input, select, textarea, [role=\"button\"], [onclick]');\n if (isInteractive) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n\n const includeForensic = state.settings.outputLevel === 'forensic';\n const elementInfo = collectElementInfo(target, includeForensic);\n\n // Store click position:\n // - For fixed elements: use viewport coordinates directly\n // - For non-fixed elements: convert to document coordinates (add scroll offset)\n const clickX = event.clientX;\n const clickY = elementInfo.isFixed ? event.clientY : event.clientY + window.scrollY;\n\n eventBus.emit('element:click', {\n element: target,\n elementInfo,\n clickX,\n clickY\n });\n };\n\n /**\n * Handle mouse down for potential drag selection\n */\n const handleMouseDown = (event: MouseEvent) => {\n const state = store.getState();\n\n if (state.mode !== 'multi-select') return;\n\n const target = event.target as Element;\n if (isAnnotationElement(target)) return;\n\n const position: Position = {\n x: event.clientX,\n y: event.clientY,\n };\n\n eventBus.emit('multiselect:start', { position });\n };\n\n /**\n * Handle mouse move for drag selection\n */\n const handleMouseMove = (event: MouseEvent) => {\n const state = store.getState();\n\n if (!state.isSelecting && state.selectionRect === null) return;\n\n if (state.isSelecting && state.selectionRect) {\n const rect = {\n startX: state.selectionRect.startX,\n startY: state.selectionRect.startY,\n endX: event.clientX,\n endY: event.clientY,\n };\n\n eventBus.emit('multiselect:update', { rect });\n }\n };\n\n /**\n * Handle mouse up to complete drag selection\n */\n const handleMouseUp = (_event: MouseEvent) => {\n const state = store.getState();\n\n if (!state.isSelecting) return;\n\n // Find elements in selection rectangle\n const rect = state.selectionRect;\n if (!rect) return;\n\n const elements = findElementsInRect(rect);\n eventBus.emit('multiselect:end', { elements });\n };\n\n /**\n * Handle scroll events\n */\n const handleScroll = () => {\n store.setState({ scrollY: window.scrollY });\n };\n\n /**\n * Handle keyboard events\n */\n const handleKeyDown = (event: KeyboardEvent) => {\n const state = store.getState();\n\n // Escape to cancel current operation\n if (event.key === 'Escape') {\n if (state.popupVisible) {\n store.setState({ popupVisible: false, popupAnnotationId: null });\n event.preventDefault();\n } else if (state.isSelecting) {\n store.setState({ isSelecting: false, selectionRect: null });\n event.preventDefault();\n } else if (state.mode !== 'disabled') {\n eventBus.emit('deactivate', undefined as never);\n event.preventDefault();\n }\n }\n };\n\n /**\n * Attach event listeners\n */\n const attach = () => {\n if (isActive) return;\n\n document.addEventListener('click', handleClick, true);\n document.addEventListener('mousedown', handleMouseDown, true);\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('mouseup', handleMouseUp, true);\n document.addEventListener('scroll', handleScroll, { passive: true });\n document.addEventListener('keydown', handleKeyDown, true);\n\n isActive = true;\n };\n\n /**\n * Detach event listeners\n */\n const detach = () => {\n if (!isActive) return;\n\n document.removeEventListener('click', handleClick, true);\n document.removeEventListener('mousedown', handleMouseDown, true);\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('mouseup', handleMouseUp, true);\n document.removeEventListener('scroll', handleScroll);\n document.removeEventListener('keydown', handleKeyDown, true);\n\n isActive = false;\n };\n\n return {\n attach,\n detach,\n isActive: () => isActive,\n };\n}\n\n/**\n * Find interactive elements within a selection rectangle\n */\nfunction findElementsInRect(rect: { startX: number; startY: number; endX: number; endY: number }): Element[] {\n // Normalize rectangle\n const minX = Math.min(rect.startX, rect.endX);\n const maxX = Math.max(rect.startX, rect.endX);\n const minY = Math.min(rect.startY, rect.endY);\n const maxY = Math.max(rect.startY, rect.endY);\n\n // Query for interactive elements\n const selector = 'button, a, input, img, p, h1, h2, h3, h4, h5, h6, li, label, td, th';\n const candidates = document.querySelectorAll(selector);\n\n const viewport = {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n\n const results: Element[] = [];\n\n for (const element of candidates) {\n // Skip Annotation elements\n if (isAnnotationElement(element)) continue;\n\n const bounds = element.getBoundingClientRect();\n\n // Skip elements that don't intersect selection\n if (\n bounds.right < minX ||\n bounds.left > maxX ||\n bounds.bottom < minY ||\n bounds.top > maxY\n ) {\n continue;\n }\n\n // Skip elements too large (> 80% viewport width AND > 50% height)\n if (bounds.width > viewport.width * 0.8 && bounds.height > viewport.height * 0.5) {\n continue;\n }\n\n // Skip elements too small (< 10x10)\n if (bounds.width < 10 || bounds.height < 10) {\n continue;\n }\n\n results.push(element);\n }\n\n // Filter out parent elements (keep only leaf nodes in selection)\n return results.filter((element) => {\n return !results.some(\n (other) => other !== element && element.contains(other)\n );\n });\n}\n\nexport type EventHandlers = ReturnType<typeof createEventHandlers>;\n","/**\n * Throttle utility - limits function execution rate\n */\n\nexport type ThrottledFunction<T extends (...args: never[]) => unknown> = {\n (...args: Parameters<T>): void;\n cancel: () => void;\n flush: () => void;\n};\n\n/**\n * Creates a throttled function that only invokes `fn` at most once per `wait` milliseconds\n */\nexport function throttle<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number,\n options: { leading?: boolean; trailing?: boolean } = {}\n): ThrottledFunction<T> {\n const { leading = true, trailing = true } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let lastArgs: Parameters<T> | null = null;\n let lastCallTime: number | null = null;\n let lastInvokeTime = 0;\n\n const invoke = (time: number) => {\n lastInvokeTime = time;\n const args = lastArgs!;\n lastArgs = null;\n fn(...args);\n };\n\n const shouldInvoke = (time: number): boolean => {\n const timeSinceLastCall = lastCallTime !== null ? time - lastCallTime : 0;\n const timeSinceLastInvoke = time - lastInvokeTime;\n\n return (\n lastCallTime === null ||\n timeSinceLastCall >= wait ||\n timeSinceLastCall < 0 ||\n timeSinceLastInvoke >= wait\n );\n };\n\n const remainingWait = (time: number): number => {\n const timeSinceLastCall = lastCallTime !== null ? time - lastCallTime : 0;\n const timeWaiting = wait - timeSinceLastCall;\n\n return Math.max(0, timeWaiting);\n };\n\n const timerExpired = () => {\n const time = Date.now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n timeoutId = setTimeout(timerExpired, remainingWait(time));\n };\n\n const trailingEdge = (time: number) => {\n timeoutId = null;\n if (trailing && lastArgs) {\n invoke(time);\n }\n lastArgs = null;\n };\n\n const cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n lastInvokeTime = 0;\n lastArgs = null;\n lastCallTime = null;\n timeoutId = null;\n };\n\n const flush = () => {\n if (timeoutId !== null) {\n trailingEdge(Date.now());\n }\n };\n\n const throttled = (...args: Parameters<T>) => {\n const time = Date.now();\n const isInvoking = shouldInvoke(time);\n\n lastArgs = args;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timeoutId === null) {\n // First call or after wait period\n if (leading) {\n invoke(time);\n }\n timeoutId = setTimeout(timerExpired, wait);\n }\n }\n };\n\n throttled.cancel = cancel;\n throttled.flush = flush;\n\n return throttled;\n}\n\n/**\n * Creates a debounced function that delays invoking `fn` until after `wait` ms\n * have elapsed since the last time it was invoked\n */\nexport function debounce<T extends (...args: never[]) => unknown>(\n fn: T,\n wait: number,\n options: { leading?: boolean; maxWait?: number } = {}\n): ThrottledFunction<T> {\n const { leading = false, maxWait } = options;\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let lastArgs: Parameters<T> | null = null;\n let lastCallTime: number | null = null;\n let maxTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const invoke = () => {\n const args = lastArgs!;\n lastArgs = null;\n fn(...args);\n };\n\n const cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n if (maxTimeoutId !== null) {\n clearTimeout(maxTimeoutId);\n maxTimeoutId = null;\n }\n lastArgs = null;\n lastCallTime = null;\n };\n\n const flush = () => {\n if (timeoutId !== null && lastArgs) {\n invoke();\n cancel();\n }\n };\n\n const debounced = (...args: Parameters<T>) => {\n const time = Date.now();\n const isLeading = leading && lastCallTime === null;\n\n lastArgs = args;\n lastCallTime = time;\n\n if (isLeading) {\n invoke();\n }\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(() => {\n if (!leading || lastArgs) {\n invoke();\n }\n cancel();\n }, wait);\n\n // Set up max wait timeout if specified\n if (maxWait !== undefined && maxTimeoutId === null) {\n maxTimeoutId = setTimeout(() => {\n if (lastArgs) {\n invoke();\n }\n cancel();\n }, maxWait);\n }\n };\n\n debounced.cancel = cancel;\n debounced.flush = flush;\n\n return debounced;\n}\n","/**\n * Throttled hover detection for element highlighting\n */\n\nimport type { AppState } from '../types';\nimport type { Store } from '../store';\nimport type { EventBus } from '../event-bus';\nimport type { EventMap } from '../types';\nimport { throttle } from '../utils/throttle';\nimport { collectElementInfo } from '../element';\nimport { isAnnotationElement } from './events';\n\nconst THROTTLE_MS = 50;\n\n/**\n * Create hover detection handler\n */\nexport function createHoverDetection(\n store: Store<AppState>,\n eventBus: EventBus<EventMap>\n) {\n let isActive = false;\n let currentElement: Element | null = null;\n\n /**\n * Process hover target\n */\n const processHover = (event: MouseEvent) => {\n const state = store.getState();\n\n // Don't process hover when disabled or selecting\n if (state.mode === 'disabled' || state.isSelecting) {\n if (state.hoveredElement !== null) {\n store.setState({\n hoveredElement: null,\n hoveredElementInfo: null,\n });\n eventBus.emit('element:hover', { element: null, elementInfo: null });\n }\n return;\n }\n\n // When popup or settings panel is open, don't update hover state (keep it stable)\n if (state.popupVisible || state.settingsPanelVisible) {\n return;\n }\n\n const target = event.target as Element;\n\n // Skip Annotation elements\n if (isAnnotationElement(target)) {\n if (currentElement !== null) {\n currentElement = null;\n store.setState({\n hoveredElement: null,\n hoveredElementInfo: null,\n });\n eventBus.emit('element:hover', { element: null, elementInfo: null });\n }\n return;\n }\n\n // Skip if same element\n if (target === currentElement) {\n return;\n }\n\n currentElement = target;\n\n // Collect element info\n const includeForensic = state.settings.outputLevel === 'forensic';\n const elementInfo = collectElementInfo(target, includeForensic);\n\n store.setState({\n hoveredElement: target,\n hoveredElementInfo: elementInfo,\n });\n\n eventBus.emit('element:hover', { element: target, elementInfo });\n };\n\n // Create throttled handler\n const throttledHandler = throttle(processHover, THROTTLE_MS, {\n leading: true,\n trailing: true,\n });\n\n /**\n * Handle mouse leave to clear hover state\n */\n const handleMouseLeave = (event: MouseEvent) => {\n // Only clear if leaving the document\n const relatedTarget = event.relatedTarget as Element | null;\n if (relatedTarget && document.documentElement.contains(relatedTarget)) {\n return;\n }\n\n currentElement = null;\n store.setState({\n hoveredElement: null,\n hoveredElementInfo: null,\n });\n eventBus.emit('element:hover', { element: null, elementInfo: null });\n };\n\n /**\n * Attach hover detection\n */\n const attach = () => {\n if (isActive) return;\n\n document.addEventListener('mousemove', throttledHandler, { passive: true });\n document.addEventListener('mouseleave', handleMouseLeave);\n\n isActive = true;\n };\n\n /**\n * Detach hover detection\n */\n const detach = () => {\n if (!isActive) return;\n\n document.removeEventListener('mousemove', throttledHandler);\n document.removeEventListener('mouseleave', handleMouseLeave);\n throttledHandler.cancel();\n\n currentElement = null;\n store.setState({\n hoveredElement: null,\n hoveredElementInfo: null,\n });\n\n isActive = false;\n };\n\n /**\n * Clear current hover state\n */\n const clearHover = () => {\n currentElement = null;\n store.setState({\n hoveredElement: null,\n hoveredElementInfo: null,\n });\n eventBus.emit('element:hover', { element: null, elementInfo: null });\n };\n\n return {\n attach,\n detach,\n clearHover,\n isActive: () => isActive,\n };\n}\n\nexport type HoverDetection = ReturnType<typeof createHoverDetection>;\n","/**\n * Multi-select drag selection functionality\n */\n\nimport type { AppState, SelectionRect, Position } from '../types';\nimport type { Store } from '../store';\nimport type { EventBus } from '../event-bus';\nimport type { EventMap } from '../types';\nimport { isAnnotationElement } from './events';\n\n/** Minimum drag distance to trigger selection mode */\nconst DRAG_THRESHOLD = 8;\n\n/** Minimum selection area to be valid */\nconst MIN_SELECTION_SIZE = 20;\n\n/**\n * Create multi-select manager\n */\nexport function createMultiSelect(\n store: Store<AppState>,\n eventBus: EventBus<EventMap>\n) {\n let startPosition: Position | null = null;\n let isDragging = false;\n let isActive = false;\n\n /**\n * Prevent text selection during drag\n */\n const preventTextSelection = () => {\n document.body.style.userSelect = 'none';\n document.body.style.webkitUserSelect = 'none';\n };\n\n /**\n * Restore text selection\n */\n const restoreTextSelection = () => {\n document.body.style.userSelect = '';\n document.body.style.webkitUserSelect = '';\n };\n\n /**\n * Handle start of potential drag\n */\n const handleStart = (position: Position) => {\n startPosition = position;\n isDragging = false;\n };\n\n /**\n * Handle mouse move during drag\n */\n const handleMove = (event: MouseEvent) => {\n if (!startPosition) return;\n\n const dx = event.clientX - startPosition.x;\n const dy = event.clientY - startPosition.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n // Start dragging if threshold exceeded\n if (!isDragging && distance > DRAG_THRESHOLD) {\n isDragging = true;\n preventTextSelection();\n\n const rect: SelectionRect = {\n startX: startPosition.x,\n startY: startPosition.y,\n endX: event.clientX,\n endY: event.clientY,\n };\n\n store.setState({\n isSelecting: true,\n selectionRect: rect,\n selectionPreviewElements: findElementsInSelection(rect),\n });\n }\n\n // Update selection rectangle and preview elements\n if (isDragging) {\n const rect: SelectionRect = {\n startX: startPosition.x,\n startY: startPosition.y,\n endX: event.clientX,\n endY: event.clientY,\n };\n\n store.setState({\n selectionRect: rect,\n selectionPreviewElements: findElementsInSelection(rect),\n });\n }\n };\n\n /**\n * Handle end of drag\n */\n const handleEnd = (): Element[] => {\n const state = store.getState();\n const rect = state.selectionRect;\n const previewElements = state.selectionPreviewElements;\n\n // Reset state\n startPosition = null;\n isDragging = false;\n restoreTextSelection();\n\n store.setState({\n isSelecting: false,\n selectionRect: null,\n selectionPreviewElements: [],\n });\n\n if (!rect) return [];\n\n // Check if selection is large enough\n const width = Math.abs(rect.endX - rect.startX);\n const height = Math.abs(rect.endY - rect.startY);\n\n if (width < MIN_SELECTION_SIZE && height < MIN_SELECTION_SIZE) {\n return [];\n }\n\n // Return the preview elements (already calculated during drag)\n return previewElements.length > 0 ? previewElements : findElementsInSelection(rect);\n };\n\n /**\n * Cancel current selection\n */\n const cancel = () => {\n startPosition = null;\n isDragging = false;\n restoreTextSelection();\n store.setState({\n isSelecting: false,\n selectionRect: null,\n selectionPreviewElements: [],\n });\n };\n\n /**\n * Set up event listeners for multi-select mode\n * Works in both 'select' and 'multi-select' modes\n */\n const handleMouseDown = (event: MouseEvent) => {\n const state = store.getState();\n\n // Work in select mode (drag becomes multi) or explicit multi-select mode\n if (state.mode !== 'select' && state.mode !== 'multi-select') return;\n\n // Don't start if popup is open\n if (state.popupVisible) return;\n\n const target = event.target as Element;\n if (isAnnotationElement(target)) return;\n\n // Only track left mouse button\n if (event.button !== 0) return;\n\n handleStart({ x: event.clientX, y: event.clientY });\n };\n\n const handleMouseMove = (event: MouseEvent) => {\n if (!startPosition) return;\n handleMove(event);\n };\n\n const handleMouseUp = () => {\n if (!startPosition) return;\n\n const elements = handleEnd();\n if (elements.length > 0) {\n eventBus.emit('multiselect:end', { elements });\n }\n };\n\n /**\n * Attach multi-select handlers\n */\n const attach = () => {\n if (isActive) return;\n\n document.addEventListener('mousedown', handleMouseDown, true);\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('mouseup', handleMouseUp, true);\n\n isActive = true;\n };\n\n /**\n * Detach multi-select handlers\n */\n const detach = () => {\n if (!isActive) return;\n\n document.removeEventListener('mousedown', handleMouseDown, true);\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('mouseup', handleMouseUp, true);\n\n cancel();\n isActive = false;\n };\n\n return {\n attach,\n detach,\n cancel,\n isActive: () => isActive,\n isDragging: () => isDragging,\n };\n}\n\n/**\n * Find interactive elements within selection rectangle\n */\nfunction findElementsInSelection(rect: SelectionRect): Element[] {\n // Normalize rectangle bounds\n const minX = Math.min(rect.startX, rect.endX);\n const maxX = Math.max(rect.startX, rect.endX);\n const minY = Math.min(rect.startY, rect.endY);\n const maxY = Math.max(rect.startY, rect.endY);\n\n // Query interactive elements\n const selector = 'button, a, input, img, p, h1, h2, h3, h4, h5, h6, li, label, td, th';\n const candidates = document.querySelectorAll(selector);\n\n const viewport = {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n\n const results: Element[] = [];\n\n for (const element of candidates) {\n // Skip Annotation elements\n if (isAnnotationElement(element)) continue;\n\n const bounds = element.getBoundingClientRect();\n\n // Check intersection with selection rectangle\n const intersects =\n bounds.right >= minX &&\n bounds.left <= maxX &&\n bounds.bottom >= minY &&\n bounds.top <= maxY;\n\n if (!intersects) continue;\n\n // Skip elements that are too large\n const isTooLarge =\n bounds.width > viewport.width * 0.8 &&\n bounds.height > viewport.height * 0.5;\n\n if (isTooLarge) continue;\n\n // Skip elements that are too small\n const isTooSmall = bounds.width < 10 || bounds.height < 10;\n\n if (isTooSmall) continue;\n\n results.push(element);\n }\n\n // Filter to keep only leaf nodes (elements that don't contain other selected elements)\n return results.filter((element) => {\n return !results.some(\n (other) => other !== element && element.contains(other)\n );\n });\n}\n\n/**\n * Get normalized selection rectangle (ensures start < end)\n */\nexport function normalizeRect(rect: SelectionRect): {\n x: number;\n y: number;\n width: number;\n height: number;\n} {\n const x = Math.min(rect.startX, rect.endX);\n const y = Math.min(rect.startY, rect.endY);\n const width = Math.abs(rect.endX - rect.startX);\n const height = Math.abs(rect.endY - rect.startY);\n\n return { x, y, width, height };\n}\n\nexport type MultiSelect = ReturnType<typeof createMultiSelect>;\n","/**\n * Animation/video freeze functionality\n */\n\nimport type { AppState } from '../types';\nimport type { Store } from '../store';\nimport type { EventBus } from '../event-bus';\nimport type { EventMap } from '../types';\n\nconst FREEZE_STYLE_ID = 'annotation-freeze-styles';\n\n/** CSS to freeze animations */\nconst FREEZE_CSS = `\n *:not([data-annotation-toolbar] *):not([data-annotation-marker] *):not([data-annotation-popup] *) {\n animation-play-state: paused !important;\n transition: none !important;\n }\n`;\n\n/**\n * Create freeze manager for animations and videos\n */\nexport function createFreezeManager(\n store: Store<AppState>,\n eventBus: EventBus<EventMap>\n) {\n let isFrozen = false;\n let styleElement: HTMLStyleElement | null = null;\n let pausedVideos: WeakSet<HTMLVideoElement> = new WeakSet();\n\n /**\n * Inject freeze stylesheet\n */\n const injectFreezeStyles = () => {\n if (styleElement) return;\n\n styleElement = document.createElement('style');\n styleElement.id = FREEZE_STYLE_ID;\n styleElement.textContent = FREEZE_CSS;\n document.head.appendChild(styleElement);\n };\n\n /**\n * Remove freeze stylesheet\n */\n const removeFreezeStyles = () => {\n if (!styleElement) return;\n\n styleElement.remove();\n styleElement = null;\n };\n\n /**\n * Pause all videos on the page\n */\n const pauseVideos = () => {\n const videos = document.querySelectorAll('video');\n\n for (const video of videos) {\n // Only pause videos that were playing\n if (!video.paused) {\n pausedVideos.add(video);\n video.pause();\n }\n }\n };\n\n /**\n * Resume videos that were paused by freeze\n */\n const resumeVideos = () => {\n const videos = document.querySelectorAll('video');\n\n for (const video of videos) {\n if (pausedVideos.has(video)) {\n video.play().catch(() => {\n // Ignore autoplay errors\n });\n }\n }\n\n pausedVideos = new WeakSet();\n };\n\n /**\n * Freeze all animations and videos\n */\n const freeze = () => {\n if (isFrozen) return;\n\n injectFreezeStyles();\n pauseVideos();\n\n isFrozen = true;\n store.setState({ isFrozen: true });\n eventBus.emit('freeze:toggle', { frozen: true });\n };\n\n /**\n * Unfreeze animations and videos\n */\n const unfreeze = () => {\n if (!isFrozen) return;\n\n removeFreezeStyles();\n resumeVideos();\n\n isFrozen = false;\n store.setState({ isFrozen: false });\n eventBus.emit('freeze:toggle', { frozen: false });\n };\n\n /**\n * Toggle freeze state\n */\n const toggle = () => {\n if (isFrozen) {\n unfreeze();\n } else {\n freeze();\n }\n };\n\n /**\n * Clean up on destroy\n */\n const destroy = () => {\n if (isFrozen) {\n unfreeze();\n }\n };\n\n return {\n freeze,\n unfreeze,\n toggle,\n destroy,\n isFrozen: () => isFrozen,\n };\n}\n\nexport type FreezeManager = ReturnType<typeof createFreezeManager>;\n","/**\n * Cursor style injection for active state\n */\n\nconst CURSOR_STYLE_ID = 'annotation-cursor-styles';\n\n/** CSS for cursor override */\nconst CURSOR_CSS = `\n /* Crosshair for most elements */\n body:not([data-annotation-disabled]) *:not([data-annotation-toolbar] *):not([data-annotation-marker] *):not([data-annotation-popup] *) {\n cursor: crosshair !important;\n }\n\n /* Text cursor for text selection */\n body:not([data-annotation-disabled]) p:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) span:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h1:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h2:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h3:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h4:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h5:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) h6:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) li:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) td:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) th:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) code:not([data-annotation-toolbar] *),\n body:not([data-annotation-disabled]) pre:not([data-annotation-toolbar] *) {\n cursor: text !important;\n }\n\n /* Pointer for Annotation UI elements */\n [data-annotation-marker],\n [data-annotation-marker] *,\n [data-annotation-toolbar] button,\n [data-annotation-popup] button {\n cursor: pointer !important;\n }\n\n /* Default for toolbar */\n [data-annotation-toolbar],\n [data-annotation-toolbar] *,\n [data-annotation-popup],\n [data-annotation-popup] * {\n cursor: default !important;\n }\n\n /* Crosshair for multi-select mode */\n body[data-annotation-multiselect] *:not([data-annotation-toolbar] *):not([data-annotation-marker] *):not([data-annotation-popup] *) {\n cursor: crosshair !important;\n }\n\n /* Move cursor when dragging toolbar */\n body[data-annotation-dragging] * {\n cursor: move !important;\n }\n`;\n\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * Inject cursor override styles\n */\nexport function injectCursorStyles(): void {\n if (styleElement) return;\n\n styleElement = document.createElement('style');\n styleElement.id = CURSOR_STYLE_ID;\n styleElement.textContent = CURSOR_CSS;\n document.head.appendChild(styleElement);\n}\n\n/**\n * Remove cursor override styles\n */\nexport function removeCursorStyles(): void {\n if (!styleElement) return;\n\n styleElement.remove();\n styleElement = null;\n}\n\n/**\n * Set multi-select mode cursor\n */\nexport function setMultiSelectMode(enabled: boolean): void {\n if (enabled) {\n document.body.setAttribute('data-annotation-multiselect', '');\n } else {\n document.body.removeAttribute('data-annotation-multiselect');\n }\n}\n\n/**\n * Set dragging mode cursor\n */\nexport function setDraggingMode(enabled: boolean): void {\n if (enabled) {\n document.body.setAttribute('data-annotation-dragging', '');\n } else {\n document.body.removeAttribute('data-annotation-dragging');\n }\n}\n\n/**\n * Set disabled state\n */\nexport function setDisabledState(disabled: boolean): void {\n if (disabled) {\n document.body.setAttribute('data-annotation-disabled', '');\n } else {\n document.body.removeAttribute('data-annotation-disabled');\n }\n}\n\n/**\n * Clean up all cursor-related attributes and styles\n */\nexport function cleanupCursorStyles(): void {\n removeCursorStyles();\n document.body.removeAttribute('data-annotation-multiselect');\n document.body.removeAttribute('data-annotation-dragging');\n document.body.removeAttribute('data-annotation-disabled');\n}\n","/**\n * Core controller - ties together all core functionality\n */\n\nimport type { AppState, Scope, AnnotationId, Settings, ToolMode, OutputLevel, EventMap } from './types';\nimport { createStore, type Store } from './store';\nimport { createEventBus, type EventBus } from './event-bus';\nimport { createInitialState, DEFAULT_SETTINGS } from './state';\nimport { createAnnotationManager, type AnnotationManager } from './scopes/scope';\nimport {\n loadScopes,\n loadSettings,\n saveSettings,\n createAutoSaver,\n} from './scopes/persistence';\nimport { generateOutput, copyToClipboard } from './scopes/output';\nimport { createEventHandlers } from './dom/events';\nimport { createHoverDetection } from './dom/hover-detection';\nimport { createMultiSelect } from './dom/multi-select';\nimport { createFreezeManager, type FreezeManager } from './dom/freeze';\nimport {\n injectCursorStyles,\n setMultiSelectMode,\n setDisabledState,\n cleanupCursorStyles,\n} from './dom/cursor';\nimport { collectElementInfo } from './element';\n\nexport interface AnnotationCoreOptions {\n /** Initial settings override */\n settings?: Partial<Settings>;\n /** Whether to load persisted scopes */\n loadPersisted?: boolean;\n /** Callback when a scope is created */\n onScopeCreate?: (scope: Scope) => void;\n /** Callback when a scope is updated */\n onScopeUpdate?: (scope: Scope) => void;\n /** Callback when a scope is deleted */\n onScopeDelete?: (id: AnnotationId) => void;\n /** Callback when all scopes are cleared */\n onScopesClear?: (scopes: Scope[]) => void;\n /** Callback when output is copied */\n onCopy?: (content: string, level: OutputLevel) => void;\n /** Whether to copy to clipboard automatically */\n copyToClipboard?: boolean;\n}\n\nexport interface AnnotationCore {\n /** Store for state management */\n store: Store<AppState>;\n /** Event bus for cross-component communication */\n eventBus: EventBus<EventMap>;\n /** Scope manager for CRUD operations */\n scopes: AnnotationManager;\n /** Freeze manager for animations/videos */\n freeze: FreezeManager;\n\n /** Activate the tool */\n activate: (mode?: ToolMode) => void;\n /** Deactivate the tool */\n deactivate: () => void;\n /** Toggle activation */\n toggle: () => void;\n /** Check if active */\n isActive: () => boolean;\n\n /** Set tool mode */\n setMode: (mode: ToolMode) => void;\n /** Get current mode */\n getMode: () => ToolMode;\n\n /** Update settings */\n updateSettings: (settings: Partial<Settings>) => void;\n /** Get current settings */\n getSettings: () => Settings;\n\n /** Generate and copy output */\n copyOutput: (level?: OutputLevel) => Promise<boolean>;\n /** Get output without copying */\n getOutput: (level?: OutputLevel) => string;\n\n /** Show popup for creating/editing scope */\n showPopup: (scopeId?: AnnotationId) => void;\n /** Hide popup */\n hidePopup: () => void;\n\n /** Subscribe to state changes */\n subscribe: (listener: (state: AppState) => void) => () => void;\n\n /** Destroy and clean up */\n destroy: () => void;\n}\n\n/**\n * Create the core Annotation controller\n */\nexport function createAnnotationCore(options: AnnotationCoreOptions = {}): AnnotationCore {\n const {\n settings: initialSettings,\n loadPersisted = true,\n onScopeCreate,\n onScopeUpdate,\n onScopeDelete,\n onScopesClear,\n onCopy,\n copyToClipboard: shouldCopyToClipboard = true,\n } = options;\n\n // Load persisted data\n const persistedSettings = loadPersisted ? loadSettings() : null;\n const persistedScopes = loadPersisted ? loadScopes() : new Map();\n\n // Merge settings\n const mergedSettings: Settings = {\n ...DEFAULT_SETTINGS,\n ...persistedSettings,\n ...initialSettings,\n };\n\n // Create store with initial state\n const store = createStore(\n createInitialState({\n settings: mergedSettings,\n scopes: persistedScopes,\n })\n );\n\n // Create event bus\n const eventBus = createEventBus<EventMap>();\n\n // Create managers\n const scopeManager = createAnnotationManager(store, eventBus);\n const freezeManager = createFreezeManager(store, eventBus);\n const eventHandlers = createEventHandlers(store, eventBus);\n const hoverDetection = createHoverDetection(store, eventBus);\n const multiSelect = createMultiSelect(store, eventBus);\n\n // Create auto-saver\n const autoSaver = createAutoSaver(() => store.getState().scopes, 1000);\n\n // Set up event listeners for callbacks\n if (onScopeCreate) {\n eventBus.on('scope:create', ({ scope }) => onScopeCreate(scope));\n }\n\n if (onScopeUpdate) {\n eventBus.on('scope:update', ({ scope }) => onScopeUpdate(scope));\n }\n\n if (onScopeDelete) {\n eventBus.on('scope:delete', ({ id }) => onScopeDelete(id));\n }\n\n if (onScopesClear) {\n eventBus.on('scopes:clear', ({ scopes }) => onScopesClear(scopes));\n }\n\n // Auto-save on scope changes\n eventBus.on('scope:create', () => autoSaver.save());\n eventBus.on('scope:update', () => autoSaver.save());\n eventBus.on('scope:delete', () => autoSaver.save());\n eventBus.on('scopes:clear', () => autoSaver.save());\n\n // Save settings on change\n eventBus.on('settings:change', ({ settings }) => {\n const currentSettings = store.getState().settings;\n saveSettings({ ...currentSettings, ...settings });\n });\n\n // Handle element clicks to create scopes\n eventBus.on('element:click', ({ element, elementInfo, clickX, clickY }) => {\n const state = store.getState();\n\n if (state.mode === 'disabled') return;\n\n // clickX/clickY from event are:\n // - Fixed elements: viewport coords\n // - Non-fixed elements: document coords (viewport + scroll at click time)\n //\n // For popup positioning, we need viewport coords.\n // For scope/marker storage, we use the coords as-is (document for non-fixed, viewport for fixed).\n const viewportY = elementInfo.isFixed ? clickY : clickY - window.scrollY;\n\n // Show popup for creating scope with pending marker\n store.setState({\n popupVisible: true,\n popupAnnotationId: null,\n popupElementInfo: elementInfo,\n popupClickX: clickX, // X is always viewport-relative\n popupClickY: viewportY, // Convert to viewport for popup positioning\n pendingMarkerX: clickX, // Document coords for marker\n pendingMarkerY: clickY,\n pendingMarkerIsFixed: elementInfo.isFixed,\n hoveredElement: element,\n hoveredElementInfo: elementInfo,\n });\n });\n\n // Handle multi-select completion\n eventBus.on('multiselect:end', ({ elements }) => {\n if (elements.length === 0) return;\n\n const state = store.getState();\n const includeForensic = state.settings.outputLevel === 'forensic';\n\n // Collect element info for all selected elements\n const elementInfos = elements.map(el => collectElementInfo(el, includeForensic));\n\n // Position popup near the center of the selection area\n const rects = elements.map(el => el.getBoundingClientRect());\n const minX = Math.min(...rects.map(r => r.left));\n const maxX = Math.max(...rects.map(r => r.right));\n const minY = Math.min(...rects.map(r => r.top));\n const maxY = Math.max(...rects.map(r => r.bottom));\n const centerX = (minX + maxX) / 2;\n const centerY = (minY + maxY) / 2;\n\n store.setState({\n popupVisible: true,\n popupAnnotationId: null,\n popupElementInfo: elementInfos[0], // Primary element for display\n popupClickX: centerX,\n popupClickY: centerY,\n pendingMarkerX: 0, // No single pending marker for multi-select\n pendingMarkerY: 0,\n pendingMarkerIsFixed: false,\n multiSelectElements: elements,\n multiSelectInfos: elementInfos,\n hoveredElement: elements[0],\n hoveredElementInfo: elementInfos[0],\n });\n });\n\n /**\n * Activate the tool\n */\n const activate = (mode: ToolMode = 'select') => {\n const state = store.getState();\n if (state.mode !== 'disabled') return;\n\n store.batch(() => {\n store.setState({\n mode,\n toolbarExpanded: true,\n markersVisible: true,\n scrollY: window.scrollY, // Initialize scroll position\n });\n });\n\n // Attach event handlers\n eventHandlers.attach();\n hoverDetection.attach();\n multiSelect.attach(); // Always attach for drag-to-select functionality\n\n // Inject cursor styles\n injectCursorStyles();\n setDisabledState(false);\n\n if (mode === 'multi-select') {\n setMultiSelectMode(true);\n }\n\n eventBus.emit('activate', undefined as never);\n eventBus.emit('mode:change', { mode });\n };\n\n /**\n * Deactivate the tool\n */\n const deactivate = () => {\n const state = store.getState();\n if (state.mode === 'disabled') return;\n\n store.batch(() => {\n store.setState({\n mode: 'disabled',\n toolbarExpanded: false,\n popupVisible: false,\n popupAnnotationId: null,\n isSelecting: false,\n selectionRect: null,\n });\n });\n\n // Detach event handlers\n eventHandlers.detach();\n hoverDetection.detach();\n multiSelect.detach();\n\n // Clean up cursor styles\n cleanupCursorStyles();\n\n // Unfreeze if frozen\n if (state.isFrozen) {\n freezeManager.unfreeze();\n }\n\n eventBus.emit('deactivate', undefined as never);\n eventBus.emit('mode:change', { mode: 'disabled' });\n };\n\n /**\n * Toggle activation\n */\n const toggle = () => {\n const state = store.getState();\n if (state.mode === 'disabled') {\n activate();\n } else {\n deactivate();\n }\n };\n\n /**\n * Check if active\n */\n const isActive = () => store.getState().mode !== 'disabled';\n\n /**\n * Set tool mode\n */\n const setMode = (mode: ToolMode) => {\n const state = store.getState();\n\n if (mode === 'disabled') {\n deactivate();\n return;\n }\n\n if (state.mode === 'disabled') {\n activate(mode);\n return;\n }\n\n // Switch between select and multi-select\n if (mode === 'multi-select' && state.mode !== 'multi-select') {\n multiSelect.attach();\n setMultiSelectMode(true);\n } else if (mode === 'select' && state.mode === 'multi-select') {\n multiSelect.detach();\n setMultiSelectMode(false);\n }\n\n store.setState({ mode });\n eventBus.emit('mode:change', { mode });\n };\n\n /**\n * Get current mode\n */\n const getMode = () => store.getState().mode;\n\n /**\n * Update settings\n */\n const updateSettings = (newSettings: Partial<Settings>) => {\n const state = store.getState();\n const merged = { ...state.settings, ...newSettings };\n\n store.setState({ settings: merged });\n eventBus.emit('settings:change', { settings: newSettings });\n };\n\n /**\n * Get current settings\n */\n const getSettings = () => store.getState().settings;\n\n /**\n * Generate and copy output\n */\n const copyOutput = async (level?: OutputLevel): Promise<boolean> => {\n const state = store.getState();\n const outputLevel = level || state.settings.outputLevel;\n const scopes = scopeManager.getAllScopes();\n\n const content = generateOutput(scopes, outputLevel);\n\n let success = true;\n if (shouldCopyToClipboard) {\n success = await copyToClipboard(content);\n }\n\n if (success) {\n store.setState({ showCopiedFeedback: true });\n setTimeout(() => {\n store.setState({ showCopiedFeedback: false });\n }, 2000);\n\n if (onCopy) {\n onCopy(content, outputLevel);\n }\n\n eventBus.emit('output:copy', { content, level: outputLevel });\n\n // Auto-clear if enabled\n if (state.settings.autoClearAfterCopy) {\n scopeManager.clearAllScopes();\n }\n }\n\n return success;\n };\n\n /**\n * Get output without copying\n */\n const getOutput = (level?: OutputLevel): string => {\n const state = store.getState();\n const outputLevel = level || state.settings.outputLevel;\n const scopes = scopeManager.getAllScopes();\n\n return generateOutput(scopes, outputLevel);\n };\n\n /**\n * Show popup for creating/editing scope\n */\n const showPopup = (scopeId?: AnnotationId) => {\n if (scopeId) {\n // Editing existing scope - use its stored click position\n const scope = store.getState().scopes.get(scopeId);\n if (scope) {\n store.setState({\n popupVisible: true,\n popupAnnotationId: scopeId,\n popupElementInfo: scope.elementInfo,\n popupClickX: scope.clickX,\n popupClickY: scope.clickY,\n });\n return;\n }\n }\n store.setState({\n popupVisible: true,\n popupAnnotationId: scopeId || null,\n });\n };\n\n /**\n * Hide popup\n */\n const hidePopup = () => {\n store.setState({\n popupVisible: false,\n popupAnnotationId: null,\n popupElementInfo: null,\n popupClickX: 0,\n popupClickY: 0,\n pendingMarkerX: 0,\n pendingMarkerY: 0,\n pendingMarkerIsFixed: false,\n multiSelectElements: [],\n multiSelectInfos: [],\n });\n };\n\n /**\n * Subscribe to state changes\n */\n const subscribe = (listener: (state: AppState) => void) => {\n return store.subscribe(listener);\n };\n\n /**\n * Destroy and clean up\n */\n const destroy = () => {\n deactivate();\n autoSaver.flush();\n autoSaver.destroy();\n freezeManager.destroy();\n eventBus.destroy();\n store.destroy();\n };\n\n return {\n store,\n eventBus,\n scopes: scopeManager,\n freeze: freezeManager,\n activate,\n deactivate,\n toggle,\n isActive,\n setMode,\n getMode,\n updateSettings,\n getSettings,\n copyOutput,\n getOutput,\n showPopup,\n hidePopup,\n subscribe,\n destroy,\n };\n}\n","/**\n * Theme CSS variables and constants\n */\n\nexport const LIGHT_THEME = {\n // Background\n '--as-bg-primary': 'rgba(255, 255, 255, 0.95)',\n '--as-bg-secondary': 'rgba(245, 245, 245, 0.95)',\n '--as-bg-hover': 'rgba(0, 0, 0, 0.05)',\n '--as-bg-active': 'rgba(0, 0, 0, 0.1)',\n '--as-bg-overlay': 'rgba(255, 255, 255, 0.8)',\n\n // Text\n '--as-text-primary': '#1a1a1a',\n '--as-text-secondary': '#666666',\n '--as-text-muted': '#999999',\n '--as-text-inverse': '#ffffff',\n\n // Border\n '--as-border-primary': 'rgba(0, 0, 0, 0.1)',\n '--as-border-secondary': 'rgba(0, 0, 0, 0.05)',\n\n // Accent (scope color)\n '--as-accent': '#AF52DE',\n '--as-accent-hover': '#9B47C7',\n '--as-accent-light': 'rgba(175, 82, 222, 0.1)',\n\n // Status\n '--as-success': '#34C759',\n '--as-warning': '#FF9500',\n '--as-error': '#FF3B30',\n\n // Shadow\n '--as-shadow-sm': '0 1px 2px rgba(0, 0, 0, 0.05)',\n '--as-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.1)',\n '--as-shadow-lg': '0 8px 24px rgba(0, 0, 0, 0.15)',\n\n // Blur\n '--as-backdrop-blur': 'blur(12px)',\n};\n\nexport const DARK_THEME = {\n // Background\n '--as-bg-primary': 'rgba(24, 24, 27, 0.95)',\n '--as-bg-secondary': 'rgba(39, 39, 42, 0.95)',\n '--as-bg-hover': 'rgba(255, 255, 255, 0.1)',\n '--as-bg-active': 'rgba(255, 255, 255, 0.15)',\n '--as-bg-overlay': 'rgba(24, 24, 27, 0.8)',\n\n // Text\n '--as-text-primary': '#ffffff',\n '--as-text-secondary': '#a1a1aa',\n '--as-text-muted': '#71717a',\n '--as-text-inverse': '#1a1a1a',\n\n // Border\n '--as-border-primary': 'rgba(255, 255, 255, 0.1)',\n '--as-border-secondary': 'rgba(255, 255, 255, 0.05)',\n\n // Accent (scope color)\n '--as-accent': '#AF52DE',\n '--as-accent-hover': '#C77DFF',\n '--as-accent-light': 'rgba(175, 82, 222, 0.2)',\n\n // Status\n '--as-success': '#34C759',\n '--as-warning': '#FF9500',\n '--as-error': '#FF3B30',\n\n // Shadow\n '--as-shadow-sm': '0 1px 2px rgba(0, 0, 0, 0.2)',\n '--as-shadow-md': '0 4px 12px rgba(0, 0, 0, 0.3)',\n '--as-shadow-lg': '0 8px 24px rgba(0, 0, 0, 0.4)',\n\n // Blur\n '--as-backdrop-blur': 'blur(12px)',\n};\n\n/** Shared CSS variables (theme-independent) */\nexport const SHARED_VARS = {\n // Spacing\n '--as-space-xs': '4px',\n '--as-space-sm': '8px',\n '--as-space-md': '12px',\n '--as-space-lg': '16px',\n '--as-space-xl': '24px',\n\n // Border radius\n '--as-radius-sm': '4px',\n '--as-radius-md': '8px',\n '--as-radius-lg': '12px',\n '--as-radius-full': '9999px',\n\n // Typography\n '--as-font-family': '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n '--as-font-mono': 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, monospace',\n '--as-font-size-xs': '10px',\n '--as-font-size-sm': '12px',\n '--as-font-size-md': '14px',\n '--as-font-size-lg': '16px',\n\n // Transitions\n '--as-transition-fast': '100ms ease',\n '--as-transition-normal': '200ms ease',\n '--as-transition-slow': '300ms ease',\n\n // Z-index\n '--as-z-toolbar': '999999',\n '--as-z-markers': '999998',\n '--as-z-popup': '1000000',\n '--as-z-tooltip': '1000001',\n '--as-z-overlay': '999997',\n};\n\n/**\n * Generate CSS variables string for a theme\n */\nexport function generateThemeCSS(theme: 'light' | 'dark'): string {\n const themeVars = theme === 'light' ? LIGHT_THEME : DARK_THEME;\n const allVars = { ...SHARED_VARS, ...themeVars };\n\n return Object.entries(allVars)\n .map(([key, value]) => `${key}: ${value};`)\n .join('\\n');\n}\n\n/**\n * Get the resolved theme based on mode\n */\nexport function resolveTheme(mode: 'light' | 'dark' | 'auto'): 'light' | 'dark' {\n if (mode === 'auto') {\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n return mode;\n}\n\n/**\n * Get accent color by name\n */\nexport function getAccentColor(name: string): string {\n const colors: Record<string, string> = {\n purple: '#AF52DE',\n blue: '#3c82f7',\n cyan: '#5AC8FA',\n green: '#34C759',\n yellow: '#FFD60A',\n orange: '#FF9500',\n red: '#FF3B30',\n };\n\n return colors[name] || colors.purple;\n}\n","/**\n * Shadow DOM styles for Annotation web component\n */\n\nimport { LIGHT_THEME, DARK_THEME, SHARED_VARS } from '../themes/variables';\n\n/**\n * Generate CSS string from variable object\n */\nfunction varsToCSS(vars: Record<string, string>): string {\n return Object.entries(vars)\n .map(([key, value]) => `${key}: ${value};`)\n .join('\\n ');\n}\n\n/**\n * Main stylesheet for the Annotation web component\n */\nexport const componentStyles = `\n /* CSS Variables */\n :host {\n ${varsToCSS(SHARED_VARS)}\n ${varsToCSS(LIGHT_THEME)}\n }\n\n :host([data-theme=\"dark\"]) {\n ${varsToCSS(DARK_THEME)}\n }\n\n @media (prefers-color-scheme: dark) {\n :host([data-theme=\"auto\"]) {\n ${varsToCSS(DARK_THEME)}\n }\n }\n\n /* Reset */\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* Base styles */\n :host {\n all: initial;\n font-family: var(--as-font-family);\n font-size: var(--as-font-size-md);\n color: var(--as-text-primary);\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n /* Toolbar container */\n .toolbar {\n position: fixed;\n z-index: var(--as-z-toolbar);\n display: flex;\n align-items: center;\n gap: var(--as-space-sm);\n padding: var(--as-space-sm) var(--as-space-md);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-full);\n box-shadow: var(--as-shadow-lg);\n backdrop-filter: var(--as-backdrop-blur);\n user-select: none;\n transition: transform var(--as-transition-normal), opacity var(--as-transition-normal);\n }\n\n .toolbar.collapsed {\n padding: var(--as-space-sm);\n }\n\n .toolbar.dragging {\n cursor: move;\n opacity: 0.9;\n }\n\n /* Toolbar entrance animation */\n .toolbar.entering {\n animation: toolbar-enter 0.3s ease-out;\n }\n\n @keyframes toolbar-enter {\n from {\n opacity: 0;\n transform: scale(0.9) translateY(10px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n\n /* Toolbar buttons */\n .toolbar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--as-radius-md);\n color: var(--as-text-primary);\n cursor: pointer;\n transition: background var(--as-transition-fast), color var(--as-transition-fast);\n }\n\n .toolbar-btn:hover {\n background: var(--as-bg-hover);\n }\n\n .toolbar-btn:active {\n background: var(--as-bg-active);\n }\n\n .toolbar-btn.active {\n background: var(--as-accent-light);\n color: var(--as-accent);\n }\n\n .toolbar-btn svg {\n width: 18px;\n height: 18px;\n }\n\n /* Toggle button (collapsed state) */\n .toggle-btn {\n position: relative;\n width: 36px;\n height: 36px;\n }\n\n .toggle-btn .badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--as-accent);\n border-radius: var(--as-radius-full);\n color: var(--as-text-inverse);\n font-size: var(--as-font-size-xs);\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n /* Separator */\n .separator {\n width: 1px;\n height: 20px;\n background: var(--as-border-primary);\n margin: 0 var(--as-space-xs);\n }\n\n /* Scope count */\n .scope-count {\n display: flex;\n align-items: center;\n gap: var(--as-space-xs);\n padding: 0 var(--as-space-sm);\n font-size: var(--as-font-size-sm);\n font-weight: 500;\n color: var(--as-text-secondary);\n }\n\n .scope-count .count {\n color: var(--as-text-primary);\n font-weight: 600;\n }\n\n /* Feedback toast */\n .feedback {\n position: absolute;\n top: -40px;\n left: 50%;\n transform: translateX(-50%);\n padding: var(--as-space-sm) var(--as-space-md);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n box-shadow: var(--as-shadow-md);\n font-size: var(--as-font-size-sm);\n white-space: nowrap;\n animation: feedback-enter 0.2s ease-out;\n }\n\n @keyframes feedback-enter {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .feedback.success {\n border-color: var(--as-success);\n color: var(--as-success);\n }\n\n /* Markers container */\n .markers {\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: var(--as-z-markers);\n pointer-events: none;\n }\n\n /* Individual marker */\n .marker {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n background: var(--as-accent);\n border: 2px solid white;\n border-radius: 50%;\n color: white;\n font-size: var(--as-font-size-xs);\n font-weight: 700;\n box-shadow: var(--as-shadow-md);\n pointer-events: auto;\n cursor: pointer;\n transform: translate(-50%, -50%);\n transition: transform var(--as-transition-fast), box-shadow var(--as-transition-fast);\n }\n\n .marker:hover {\n transform: translate(-50%, -50%) scale(1.15);\n box-shadow: var(--as-shadow-lg);\n }\n\n .marker.fixed {\n position: fixed;\n }\n\n .marker.pending {\n opacity: 0.7;\n animation: marker-pulse 1s ease-in-out infinite;\n }\n\n @keyframes marker-pulse {\n 0%, 100% { transform: translate(-50%, -50%) scale(1); }\n 50% { transform: translate(-50%, -50%) scale(1.1); }\n }\n\n /* Marker animations */\n .marker.entering {\n animation: marker-enter 0.25s ease-out;\n }\n\n .marker.exiting {\n animation: marker-exit 0.2s ease-in forwards;\n }\n\n @keyframes marker-enter {\n from {\n opacity: 0;\n transform: translate(-50%, -50%) scale(0);\n }\n to {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n }\n\n @keyframes marker-exit {\n from {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n }\n to {\n opacity: 0;\n transform: translate(-50%, -50%) scale(0);\n }\n }\n\n /* Marker tooltip */\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n padding: var(--as-space-sm) var(--as-space-md);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n box-shadow: var(--as-shadow-md);\n font-size: var(--as-font-size-sm);\n white-space: nowrap;\n max-width: 300px;\n pointer-events: none;\n z-index: var(--as-z-tooltip);\n animation: tooltip-enter 0.15s ease-out;\n }\n\n .marker-tooltip::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 6px solid transparent;\n border-top-color: var(--as-bg-primary);\n }\n\n @keyframes tooltip-enter {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n }\n\n .tooltip-element {\n font-weight: 500;\n color: var(--as-text-primary);\n margin-bottom: 2px;\n }\n\n .tooltip-comment {\n color: var(--as-text-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n /* Popup - Popover style (positioned near click point) */\n .popup-popover {\n position: fixed;\n z-index: var(--as-z-popup);\n width: 340px;\n padding: var(--as-space-lg);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-lg);\n box-shadow: var(--as-shadow-lg);\n animation: popover-enter 0.15s ease-out;\n }\n\n @keyframes popover-enter {\n from {\n opacity: 0;\n transform: scale(0.95) translateY(-4px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n }\n\n .popup-popover.shake {\n animation: popup-shake 0.3s ease-out;\n }\n\n @keyframes popup-shake {\n 0%, 100% { transform: translateX(0); }\n 25% { transform: translateX(-8px); }\n 75% { transform: translateX(8px); }\n }\n\n .popup-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--as-space-md);\n }\n\n .popup-element {\n font-weight: 500;\n color: var(--as-text-primary);\n font-size: var(--as-font-size-md);\n }\n\n .popup-path {\n font-family: var(--as-font-mono);\n font-size: var(--as-font-size-xs);\n color: var(--as-text-muted);\n margin-top: 2px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .popup-multiselect-header {\n flex: 1;\n min-width: 0;\n }\n\n .popup-element-list {\n list-style: none;\n margin: var(--as-space-xs) 0 0 0;\n padding: 0;\n font-size: var(--as-font-size-xs);\n color: var(--as-text-secondary);\n max-height: 80px;\n overflow-y: auto;\n }\n\n .popup-element-list li {\n padding: 2px 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .popup-close {\n padding: var(--as-space-xs);\n background: transparent;\n border: none;\n border-radius: var(--as-radius-sm);\n color: var(--as-text-muted);\n cursor: pointer;\n transition: background var(--as-transition-fast), color var(--as-transition-fast);\n }\n\n .popup-close:hover {\n background: var(--as-bg-hover);\n color: var(--as-text-primary);\n }\n\n .popup-body {\n margin-bottom: var(--as-space-lg);\n }\n\n .popup-textarea {\n width: 100%;\n min-height: 100px;\n padding: var(--as-space-md);\n background: var(--as-bg-secondary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n color: var(--as-text-primary);\n font-family: inherit;\n font-size: var(--as-font-size-md);\n line-height: 1.5;\n resize: vertical;\n transition: border-color var(--as-transition-fast);\n }\n\n .popup-textarea:focus {\n outline: none;\n border-color: var(--as-accent);\n }\n\n .popup-textarea::placeholder {\n color: var(--as-text-muted);\n }\n\n .popup-footer {\n display: flex;\n justify-content: flex-end;\n gap: var(--as-space-sm);\n }\n\n .popup-btn {\n padding: var(--as-space-sm) var(--as-space-lg);\n background: transparent;\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n color: var(--as-text-primary);\n font-size: var(--as-font-size-sm);\n font-weight: 500;\n cursor: pointer;\n transition: background var(--as-transition-fast), border-color var(--as-transition-fast);\n }\n\n .popup-btn:hover {\n background: var(--as-bg-hover);\n }\n\n .popup-btn.primary {\n background: var(--as-accent);\n border-color: var(--as-accent);\n color: white;\n }\n\n .popup-btn.primary:hover {\n background: var(--as-accent-hover);\n border-color: var(--as-accent-hover);\n }\n\n .popup-btn.danger {\n color: var(--as-error);\n }\n\n .popup-btn.danger:hover {\n background: rgba(255, 59, 48, 0.1);\n }\n\n /* Hover tooltip (follows cursor) */\n .hover-tooltip {\n position: fixed;\n z-index: var(--as-z-tooltip);\n padding: var(--as-space-sm) var(--as-space-md);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n box-shadow: var(--as-shadow-md);\n font-size: var(--as-font-size-sm);\n max-width: 350px;\n pointer-events: none;\n }\n\n .hover-element {\n font-weight: 500;\n color: var(--as-text-primary);\n margin-bottom: 2px;\n }\n\n .hover-path {\n font-family: var(--as-font-mono);\n font-size: var(--as-font-size-xs);\n color: var(--as-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* Selection rectangle */\n .selection-rect {\n position: fixed;\n z-index: var(--as-z-overlay);\n border: 2px dashed var(--as-accent);\n background: var(--as-accent-light);\n pointer-events: none;\n }\n\n /* Highlight overlay */\n .highlight {\n position: fixed;\n z-index: var(--as-z-overlay);\n border: 2px solid var(--as-accent);\n background: var(--as-accent-light);\n pointer-events: none;\n transition: all 0.1s ease-out;\n }\n\n /* Settings panel */\n .settings-panel {\n position: absolute;\n bottom: calc(100% + var(--as-space-md));\n right: 0;\n width: 280px;\n padding: var(--as-space-md);\n background: var(--as-bg-primary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-lg);\n box-shadow: var(--as-shadow-lg);\n animation: settings-enter 0.2s ease-out;\n }\n\n @keyframes settings-enter {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .settings-title {\n font-weight: 600;\n margin-bottom: var(--as-space-md);\n padding-bottom: var(--as-space-sm);\n border-bottom: 1px solid var(--as-border-primary);\n }\n\n .settings-group {\n margin-bottom: var(--as-space-md);\n }\n\n .settings-label {\n display: block;\n font-size: var(--as-font-size-sm);\n color: var(--as-text-secondary);\n margin-bottom: var(--as-space-xs);\n }\n\n .settings-select {\n width: 100%;\n padding: var(--as-space-sm);\n background: var(--as-bg-secondary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-md);\n color: var(--as-text-primary);\n font-size: var(--as-font-size-sm);\n cursor: pointer;\n }\n\n .settings-select:focus {\n outline: none;\n border-color: var(--as-accent);\n }\n\n .settings-toggle {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--as-space-sm) 0;\n }\n\n .settings-toggle-label {\n font-size: var(--as-font-size-sm);\n }\n\n .settings-switch {\n position: relative;\n width: 40px;\n height: 22px;\n background: var(--as-bg-secondary);\n border: 1px solid var(--as-border-primary);\n border-radius: var(--as-radius-full);\n cursor: pointer;\n transition: background var(--as-transition-fast);\n }\n\n .settings-switch.active {\n background: var(--as-accent);\n border-color: var(--as-accent);\n }\n\n .settings-switch::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n background: white;\n border-radius: 50%;\n transition: transform var(--as-transition-fast);\n }\n\n .settings-switch.active::after {\n transform: translateX(18px);\n }\n\n /* Color picker */\n .color-picker {\n display: flex;\n gap: var(--as-space-xs);\n flex-wrap: wrap;\n }\n\n .color-option {\n width: 24px;\n height: 24px;\n border: 2px solid transparent;\n border-radius: 50%;\n cursor: pointer;\n transition: transform var(--as-transition-fast), border-color var(--as-transition-fast);\n }\n\n .color-option:hover {\n transform: scale(1.15);\n }\n\n .color-option.active {\n border-color: var(--as-text-primary);\n }\n\n /* Utility classes */\n .hidden {\n display: none !important;\n }\n\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* Skip animation for elements that have already animated */\n .no-animate {\n animation: none !important;\n }\n`;\n","/**\n * Toolbar template and icons\n */\n\n/** SVG Icons */\nexport const icons = {\n scope: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <circle cx=\"12\" cy=\"12\" r=\"6\"/>\n <circle cx=\"12\" cy=\"12\" r=\"2\"/>\n </svg>`,\n\n freeze: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 2v20M2 12h20M4.93 4.93l14.14 14.14M19.07 4.93L4.93 19.07\"/>\n </svg>`,\n\n unfreeze: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polygon points=\"5 3 19 12 5 21 5 3\"/>\n </svg>`,\n\n eye: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\"/>\n </svg>`,\n\n eyeOff: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24\"/>\n <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/>\n </svg>`,\n\n copy: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/>\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/>\n </svg>`,\n\n trash: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\"/>\n <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 <line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/>\n <line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/>\n </svg>`,\n\n sun: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"5\"/>\n <line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\"/>\n <line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\"/>\n <line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\"/>\n <line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\"/>\n <line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\"/>\n <line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\"/>\n <line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\"/>\n <line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\"/>\n </svg>`,\n\n moon: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/>\n </svg>`,\n\n x: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>`,\n\n settings: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"3\"/>\n <path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"/>\n </svg>`,\n\n multiSelect: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\"/>\n <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\"/>\n <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\"/>\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\"/>\n </svg>`,\n\n check: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"/>\n </svg>`,\n};\n\n/**\n * Render collapsed toolbar\n */\nexport function renderCollapsedToolbar(scopeCount: number): string {\n return `\n <div class=\"toolbar collapsed\" data-annotation-toolbar>\n <button class=\"toolbar-btn toggle-btn\" title=\"Activate agent-ui-annotation\" data-action=\"toggle\">\n ${icons.scope}\n ${scopeCount > 0 ? `<span class=\"badge\">${scopeCount}</span>` : ''}\n </button>\n </div>\n `;\n}\n\n/**\n * Render expanded toolbar\n */\nexport function renderExpandedToolbar(options: {\n scopeCount: number;\n isFrozen: boolean;\n markersVisible: boolean;\n isDarkMode: boolean;\n showCopiedFeedback: boolean;\n showClearedFeedback: boolean;\n showEntranceAnimation?: boolean;\n settingsPanelHtml?: string;\n}): string {\n const {\n scopeCount,\n isFrozen,\n markersVisible,\n isDarkMode,\n showCopiedFeedback,\n showClearedFeedback,\n showEntranceAnimation = false,\n settingsPanelHtml = '',\n } = options;\n\n return `\n <div class=\"toolbar${showEntranceAnimation ? ' entering' : ''}\" data-annotation-toolbar>\n ${showCopiedFeedback ? '<div class=\"feedback success\">Copied to clipboard!</div>' : ''}\n ${showClearedFeedback ? '<div class=\"feedback\">Cleared all scopes</div>' : ''}\n ${settingsPanelHtml}\n\n <button class=\"toolbar-btn ${isFrozen ? 'active' : ''}\" title=\"${isFrozen ? 'Unfreeze' : 'Freeze'} animations\" data-action=\"freeze\">\n ${isFrozen ? icons.unfreeze : icons.freeze}\n </button>\n\n <button class=\"toolbar-btn ${markersVisible ? 'active' : ''}\" title=\"${markersVisible ? 'Hide' : 'Show'} markers\" data-action=\"toggle-markers\">\n ${markersVisible ? icons.eye : icons.eyeOff}\n </button>\n\n <div class=\"separator\"></div>\n\n <div class=\"scope-count\">\n ${icons.scope}\n <span class=\"count\">${scopeCount}</span>\n </div>\n\n <div class=\"separator\"></div>\n\n <button class=\"toolbar-btn\" title=\"Copy to clipboard\" data-action=\"copy\" ${scopeCount === 0 ? 'disabled' : ''}>\n ${icons.copy}\n </button>\n\n <button class=\"toolbar-btn\" title=\"Clear all\" data-action=\"clear\" ${scopeCount === 0 ? 'disabled' : ''}>\n ${icons.trash}\n </button>\n\n <div class=\"separator\"></div>\n\n <button class=\"toolbar-btn\" title=\"Toggle theme\" data-action=\"theme\">\n ${isDarkMode ? icons.sun : icons.moon}\n </button>\n\n <button class=\"toolbar-btn\" title=\"Settings\" data-action=\"settings\">\n ${icons.settings}\n </button>\n\n <button class=\"toolbar-btn\" title=\"Close\" data-action=\"close\">\n ${icons.x}\n </button>\n </div>\n `;\n}\n","/**\n * Marker template\n */\n\nimport type { Scope } from '../../core/types';\n\nexport interface MarkerRenderOptions {\n scope: Scope;\n isHovered: boolean;\n isExiting: boolean;\n isAnimating: boolean;\n scrollY: number;\n accentColor: string;\n skipTooltipAnimation?: boolean;\n}\n\n/**\n * Calculate marker position based on click coordinates\n *\n * Click coordinates are stored as:\n * - Fixed elements: viewport coordinates\n * - Non-fixed elements: document coordinates (viewport + scroll at click time)\n *\n * Rendering:\n * - Fixed elements: use stored coords directly (CSS position: fixed)\n * - Non-fixed elements: subtract current scroll to get viewport position\n */\nfunction getMarkerPosition(scope: Scope, scrollY: number): { x: number; y: number; isFixed: boolean } {\n const isFixed = scope.elementInfo.isFixed;\n const x = scope.clickX;\n const y = scope.clickY;\n\n if (isFixed) {\n // Fixed elements: coords are viewport-relative, use directly\n return { x, y, isFixed: true };\n }\n\n // Non-fixed elements: coords are document-relative, convert to viewport\n return { x, y: y - scrollY, isFixed: false };\n}\n\n/**\n * Render a single marker\n */\nexport function renderMarker(options: MarkerRenderOptions): string {\n const { scope, isHovered, isExiting, isAnimating, scrollY, accentColor, skipTooltipAnimation = false } = options;\n\n const pos = getMarkerPosition(scope, scrollY);\n\n const classes = [\n 'marker',\n pos.isFixed ? 'fixed' : '',\n isExiting ? 'exiting' : '',\n isAnimating ? 'entering' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const style = `\n left: ${pos.x}px;\n top: ${pos.y}px;\n background-color: ${accentColor};\n `;\n\n return `\n <div\n class=\"${classes}\"\n style=\"${style}\"\n data-annotation-marker\n data-scope-id=\"${scope.id}\"\n title=\"${scope.elementInfo.humanReadable}\"\n >\n ${scope.number}\n ${isHovered ? renderMarkerTooltip(scope, skipTooltipAnimation) : ''}\n </div>\n `;\n}\n\n/**\n * Render marker tooltip\n */\nfunction renderMarkerTooltip(scope: Scope, skipAnimation: boolean): string {\n const element = scope.elementInfo.humanReadable;\n const comment = scope.comment\n ? scope.comment.length > 100\n ? scope.comment.slice(0, 100) + '...'\n : scope.comment\n : '(no comment)';\n\n return `\n <div class=\"marker-tooltip${skipAnimation ? ' no-animate' : ''}\">\n <div class=\"tooltip-element\">${escapeHtml(element)}</div>\n <div class=\"tooltip-comment\">${escapeHtml(comment)}</div>\n </div>\n `;\n}\n\nexport interface PendingMarker {\n x: number;\n y: number;\n isFixed: boolean;\n}\n\n/**\n * Render a pending marker (shown while popup is open before scope is created)\n */\nfunction renderPendingMarker(pending: PendingMarker, scrollY: number, accentColor: string, nextNumber: number): string {\n const x = pending.x;\n const y = pending.isFixed ? pending.y : pending.y - scrollY;\n\n const style = `\n left: ${x}px;\n top: ${y}px;\n background-color: ${accentColor};\n opacity: 0.7;\n `;\n\n return `\n <div\n class=\"marker pending${pending.isFixed ? ' fixed' : ''}\"\n style=\"${style}\"\n data-annotation-marker\n data-pending=\"true\"\n >\n ${nextNumber}\n </div>\n `;\n}\n\n/**\n * Render all markers\n */\nexport function renderMarkers(options: {\n scopes: Scope[];\n hoveredMarkerId: string | null;\n exitingMarkers: Set<string>;\n animatingMarkers: Set<string>;\n scrollY: number;\n accentColor: string;\n pendingMarker?: PendingMarker | null;\n pendingMarkers?: PendingMarker[];\n skipTooltipAnimation?: boolean;\n}): string {\n const { scopes, hoveredMarkerId, exitingMarkers, animatingMarkers, scrollY, accentColor, pendingMarker, pendingMarkers = [], skipTooltipAnimation = false } = options;\n\n const markerHtml = scopes\n .map((scope) =>\n renderMarker({\n scope,\n isHovered: scope.id === hoveredMarkerId,\n isExiting: exitingMarkers.has(scope.id),\n isAnimating: animatingMarkers.has(scope.id),\n scrollY,\n accentColor,\n skipTooltipAnimation,\n })\n )\n .join('');\n\n // Add pending markers if popup is open for new scope(s)\n let pendingHtml = '';\n\n if (pendingMarkers.length > 0) {\n // Multi-select: render pending markers for all selected elements\n pendingHtml = pendingMarkers\n .map((pm, i) => renderPendingMarker(pm, scrollY, accentColor, scopes.length + 1 + i))\n .join('');\n } else if (pendingMarker) {\n // Single selection: render one pending marker\n pendingHtml = renderPendingMarker(pendingMarker, scrollY, accentColor, scopes.length + 1);\n }\n\n return `<div class=\"markers\">${markerHtml}${pendingHtml}</div>`;\n}\n\n/**\n * Escape HTML entities\n */\nfunction escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n","/**\n * Popup template for scope creation/editing\n */\n\nimport type { Scope, ElementInfo } from '../../core/types';\nimport { icons } from './toolbar';\n\nexport interface PopupRenderOptions {\n elementInfo: ElementInfo | null;\n existingScope: Scope | null;\n isShaking: boolean;\n clickX: number;\n clickY: number;\n /** Multiple element infos when multi-select */\n multiSelectInfos?: ElementInfo[];\n}\n\n/**\n * Calculate popup position near click point\n */\nfunction calculatePopupPosition(clickX: number, clickY: number): { left: string; top: string } {\n const popupWidth = 340;\n const popupHeight = 220;\n const margin = 12;\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Default: position to the right of the click point\n let left = clickX + margin;\n let top = clickY - popupHeight / 2;\n\n // If would overflow right edge, position to the left of click point\n if (left + popupWidth > viewportWidth - margin) {\n left = clickX - popupWidth - margin;\n }\n\n // If would overflow left edge, center horizontally at click point\n if (left < margin) {\n left = Math.max(margin, clickX - popupWidth / 2);\n }\n\n // Clamp to viewport bounds\n left = Math.max(margin, Math.min(left, viewportWidth - popupWidth - margin));\n\n // Vertical positioning\n if (top < margin) {\n top = margin;\n }\n if (top + popupHeight > viewportHeight - margin) {\n top = viewportHeight - popupHeight - margin;\n }\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n };\n}\n\n/**\n * Render the popup as a popover near the click point\n */\nexport function renderPopup(options: PopupRenderOptions): string {\n const { elementInfo, existingScope, isShaking, clickX, clickY, multiSelectInfos = [] } = options;\n\n if (!elementInfo && !existingScope) {\n return '';\n }\n\n const isMultiSelect = multiSelectInfos.length > 1;\n const info = existingScope?.elementInfo || elementInfo!;\n const comment = existingScope?.comment || '';\n const isEditing = !!existingScope;\n\n const position = calculatePopupPosition(clickX, clickY);\n\n // Build header content based on single vs multi-select\n let headerContent: string;\n if (isMultiSelect) {\n const elementList = multiSelectInfos\n .slice(0, 5)\n .map(i => `<li>${escapeHtml(i.humanReadable)}</li>`)\n .join('');\n const remaining = multiSelectInfos.length > 5 ? `<li>...and ${multiSelectInfos.length - 5} more</li>` : '';\n\n headerContent = `\n <div class=\"popup-multiselect-header\">\n <div class=\"popup-element\">${multiSelectInfos.length} elements selected</div>\n <ul class=\"popup-element-list\">${elementList}${remaining}</ul>\n </div>\n `;\n } else {\n headerContent = `\n <div>\n <div class=\"popup-element\">${escapeHtml(info.humanReadable)}</div>\n <div class=\"popup-path\">${escapeHtml(info.selectorPath)}</div>\n </div>\n `;\n }\n\n return `\n <div class=\"popup-popover ${isShaking ? 'shake' : ''}\" style=\"left: ${position.left}; top: ${position.top};\" data-annotation-popup>\n <div class=\"popup-header\">\n ${headerContent}\n <button class=\"popup-close\" data-action=\"popup-close\" title=\"Close\">\n ${icons.x}\n </button>\n </div>\n\n <div class=\"popup-body\">\n <textarea\n class=\"popup-textarea\"\n placeholder=\"${isMultiSelect ? 'Add feedback for all selected elements...' : 'Add your feedback...'}\"\n data-popup-input\n autofocus\n >${escapeHtml(comment)}</textarea>\n </div>\n\n <div class=\"popup-footer\">\n ${isEditing ? `\n <button class=\"popup-btn danger\" data-action=\"popup-delete\">\n Delete\n </button>\n ` : ''}\n <button class=\"popup-btn\" data-action=\"popup-cancel\">\n Cancel\n </button>\n <button class=\"popup-btn primary\" data-action=\"popup-submit\">\n ${isEditing ? 'Save' : isMultiSelect ? `Add ${multiSelectInfos.length} Scopes` : 'Add Scope'}\n </button>\n </div>\n </div>\n `;\n}\n\n/**\n * Render empty state (no popup)\n */\nexport function renderEmptyPopup(): string {\n return '';\n}\n\n/**\n * Escape HTML entities\n */\nfunction escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n","/**\n * Hover tooltip template\n */\n\nimport type { ElementInfo } from '../../core/types';\n\nexport interface TooltipRenderOptions {\n elementInfo: ElementInfo;\n x: number;\n y: number;\n}\n\n/**\n * Calculate tooltip position to keep it in viewport\n */\nfunction calculateTooltipPosition(x: number, y: number): { left: string; top: string } {\n const padding = 16;\n const tooltipWidth = 350; // max-width from CSS\n const tooltipHeight = 60; // approximate height\n\n let left = x + padding;\n let top = y + padding;\n\n // Keep within viewport\n if (left + tooltipWidth > window.innerWidth) {\n left = x - tooltipWidth - padding;\n }\n\n if (top + tooltipHeight > window.innerHeight) {\n top = y - tooltipHeight - padding;\n }\n\n // Ensure not negative\n left = Math.max(padding, left);\n top = Math.max(padding, top);\n\n return {\n left: `${left}px`,\n top: `${top}px`,\n };\n}\n\n/**\n * Render hover tooltip\n */\nexport function renderHoverTooltip(options: TooltipRenderOptions): string {\n const { elementInfo, x, y } = options;\n const pos = calculateTooltipPosition(x, y);\n\n return `\n <div class=\"hover-tooltip\" style=\"left: ${pos.left}; top: ${pos.top};\">\n <div class=\"hover-element\">${escapeHtml(elementInfo.humanReadable)}</div>\n <div class=\"hover-path\">${escapeHtml(elementInfo.selectorPath)}</div>\n </div>\n `;\n}\n\n/**\n * Render empty tooltip\n */\nexport function renderEmptyTooltip(): string {\n return '';\n}\n\n/**\n * Render element highlight overlay\n */\nexport function renderHighlight(rect: DOMRect | null, accentColor: string): string {\n if (!rect) return '';\n\n return `\n <div\n class=\"highlight\"\n style=\"\n left: ${rect.left}px;\n top: ${rect.top}px;\n width: ${rect.width}px;\n height: ${rect.height}px;\n border-color: ${accentColor};\n background-color: ${accentColor}20;\n \"\n ></div>\n `;\n}\n\n/**\n * Render selection rectangle for multi-select\n */\nexport function renderSelectionRect(rect: { x: number; y: number; width: number; height: number } | null, accentColor: string): string {\n if (!rect) return '';\n\n return `\n <div\n class=\"selection-rect\"\n style=\"\n left: ${rect.x}px;\n top: ${rect.y}px;\n width: ${rect.width}px;\n height: ${rect.height}px;\n border-color: ${accentColor};\n background-color: ${accentColor}20;\n \"\n ></div>\n `;\n}\n\n/**\n * Escape HTML entities\n */\nfunction escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n}\n","/**\n * Core TypeScript interfaces for Annotation\n */\n\n/** Unique identifier for scopes */\nexport type AnnotationId = string;\n\n/** Position coordinates */\nexport interface Position {\n x: number;\n y: number;\n}\n\n/** Element bounding rectangle */\nexport interface ElementRect {\n top: number;\n left: number;\n width: number;\n height: number;\n bottom: number;\n right: number;\n}\n\n/** Accessibility information for an element */\nexport interface AccessibilityInfo {\n role: string | null;\n ariaLabel: string | null;\n ariaDescribedBy: string | null;\n ariaLabelledBy: string | null;\n tabIndex: number | null;\n isInteractive: boolean;\n}\n\n/** Computed styles subset for forensic output */\nexport interface ComputedStylesSubset {\n display: string;\n position: string;\n visibility: string;\n opacity: string;\n zIndex: string;\n overflow: string;\n pointerEvents: string;\n cursor: string;\n backgroundColor: string;\n color: string;\n fontSize: string;\n fontFamily: string;\n fontWeight: string;\n lineHeight: string;\n padding: string;\n margin: string;\n border: string;\n borderRadius: string;\n boxShadow: string;\n transform: string;\n transition: string;\n}\n\n/** Element context for nearby elements */\nexport interface NearbyContext {\n parent: string | null;\n previousSibling: string | null;\n nextSibling: string | null;\n containingLandmark: string | null;\n}\n\n/** Full element information collected for scope */\nexport interface ElementInfo {\n /** Human-readable identifier like 'button \"Save\"' */\n humanReadable: string;\n /** CSS selector path */\n selectorPath: string;\n /** Full DOM path for forensic output */\n fullDomPath: string;\n /** Element tag name */\n tagName: string;\n /** Element ID if present */\n id: string | null;\n /** Class list */\n classes: string[];\n /** Bounding rectangle */\n rect: ElementRect;\n /** Accessibility info */\n accessibility: AccessibilityInfo;\n /** Computed styles (forensic) */\n computedStyles: ComputedStylesSubset | null;\n /** Nearby element context */\n nearbyContext: NearbyContext;\n /** Inner text (truncated) */\n innerText: string;\n /** Element attributes */\n attributes: Record<string, string>;\n /** Whether element is fixed/sticky positioned */\n isFixed: boolean;\n}\n\n/** Single scope (annotation) */\nexport interface Scope {\n id: AnnotationId;\n /** Display number (1-based) */\n number: number;\n /** User's comment/note */\n comment: string;\n /** Element information snapshot */\n elementInfo: ElementInfo;\n /** Original DOM element reference (may become stale) */\n element: Element | null;\n /** Timestamp of creation */\n createdAt: number;\n /** Timestamp of last update */\n updatedAt: number;\n /** Selected text at time of scope creation */\n selectedText: string | null;\n /** Whether created via multi-select */\n isMultiSelect: boolean;\n /** Click X coordinate (viewport-relative) */\n clickX: number;\n /** Click Y coordinate (viewport-relative) */\n clickY: number;\n}\n\n/** Type alias for Annotation (same as Scope) */\nexport type Annotation = Scope;\n\n/** Output detail level */\nexport type OutputLevel = 'compact' | 'standard' | 'detailed' | 'forensic';\n\n/** Theme mode */\nexport type ThemeMode = 'light' | 'dark' | 'auto';\n\n/** Toolbar position */\nexport type ToolbarPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\n/** Tool mode */\nexport type ToolMode = 'select' | 'multi-select' | 'disabled';\n\n/** Settings configuration */\nexport interface Settings {\n theme: ThemeMode;\n outputLevel: OutputLevel;\n toolbarPosition: ToolbarPosition;\n showTooltips: boolean;\n showMarkerNumbers: boolean;\n freezeOnScope: boolean;\n persistScopes: boolean;\n scopeColor: string;\n blockInteractions: boolean;\n autoClearAfterCopy: boolean;\n}\n\n/** Selection rectangle for multi-select */\nexport interface SelectionRect {\n startX: number;\n startY: number;\n endX: number;\n endY: number;\n}\n\n/** Environment info for forensic output */\nexport interface EnvironmentInfo {\n userAgent: string;\n viewport: { width: number; height: number };\n devicePixelRatio: number;\n url: string;\n timestamp: string;\n scrollPosition: { x: number; y: number };\n}\n\n/** Event types emitted by the event bus */\nexport type EventMap = {\n 'scope:create': { scope: Scope };\n 'scope:update': { scope: Scope };\n 'scope:delete': { id: AnnotationId };\n 'scope:select': { id: AnnotationId | null };\n 'scopes:clear': { scopes: Scope[] };\n 'element:hover': { element: Element | null; elementInfo: ElementInfo | null };\n 'element:click': { element: Element; elementInfo: ElementInfo; clickX: number; clickY: number };\n 'mode:change': { mode: ToolMode };\n 'toolbar:toggle': { expanded: boolean };\n 'toolbar:drag': { position: Position };\n 'settings:change': { settings: Partial<Settings> };\n 'output:copy': { content: string; level: OutputLevel };\n 'multiselect:start': { position: Position };\n 'multiselect:update': { rect: SelectionRect };\n 'multiselect:end': { elements: Element[] };\n 'freeze:toggle': { frozen: boolean };\n 'activate': undefined;\n 'deactivate': undefined;\n}\n\n/** Store state shape */\nexport interface AppState {\n /** Map of all scopes by ID */\n scopes: Map<AnnotationId, Scope>;\n /** Currently selected scope ID */\n selectedAnnotationId: AnnotationId | null;\n /** Currently hovered element */\n hoveredElement: Element | null;\n /** Info about hovered element */\n hoveredElementInfo: ElementInfo | null;\n /** Current tool mode */\n mode: ToolMode;\n /** Whether toolbar is expanded */\n toolbarExpanded: boolean;\n /** Toolbar position */\n toolbarPosition: Position;\n /** User settings */\n settings: Settings;\n /** Whether currently drag-selecting */\n isSelecting: boolean;\n /** Current selection rectangle */\n selectionRect: SelectionRect | null;\n /** Elements currently within selection rectangle (for preview highlighting) */\n selectionPreviewElements: Element[];\n /** Whether animations/videos are frozen */\n isFrozen: boolean;\n /** Whether popup is visible */\n popupVisible: boolean;\n /** ID of scope being edited in popup */\n popupAnnotationId: AnnotationId | null;\n /** Element info for popup (stored separately from hover to prevent clearing) */\n popupElementInfo: ElementInfo | null;\n /** Click position for popup placement (viewport coords) */\n popupClickX: number;\n popupClickY: number;\n /** Click position for marker placement (document coords for non-fixed, viewport for fixed) */\n pendingMarkerX: number;\n pendingMarkerY: number;\n /** Whether pending marker element is fixed */\n pendingMarkerIsFixed: boolean;\n /** Multiple selected elements for batch scope creation */\n multiSelectElements: Element[];\n /** Element infos for multi-select (parallel array to multiSelectElements) */\n multiSelectInfos: ElementInfo[];\n /** Whether markers are visible */\n markersVisible: boolean;\n /** Set of marker IDs that are animating */\n animatingMarkers: Set<AnnotationId>;\n /** Set of marker IDs that are exiting */\n exitingMarkers: Set<AnnotationId>;\n /** ID of marker being deleted */\n deletingMarkerId: AnnotationId | null;\n /** Marker ID to start renumbering from */\n renumberFrom: number | null;\n /** Whether \"copied\" feedback is showing */\n showCopiedFeedback: boolean;\n /** Whether \"cleared\" feedback is showing */\n showClearedFeedback: boolean;\n /** Current scroll position */\n scrollY: number;\n /** Whether entrance animation should play */\n showEntranceAnimation: boolean;\n /** Whether toolbar is being dragged */\n isDraggingToolbar: boolean;\n /** Whether settings panel is visible */\n settingsPanelVisible: boolean;\n}\n\n/** Custom element events */\nexport interface AnnotationEventDetail {\n 'agentscope:scope': { scope: Scope };\n 'agentscope:update': { scope: Scope };\n 'agentscope:delete': { id: AnnotationId };\n 'agentscope:clear': { scopes: Scope[] };\n 'agentscope:copy': { content: string; level: OutputLevel };\n 'agentscope:error': { message: string; error?: Error };\n}\n\n/** Marker color options */\nexport const SCOPE_COLORS = {\n purple: '#AF52DE',\n blue: '#3c82f7',\n cyan: '#5AC8FA',\n green: '#34C759',\n yellow: '#FFD60A',\n orange: '#FF9500',\n red: '#FF3B30',\n} as const;\n\nexport type AnnotationColor = keyof typeof SCOPE_COLORS;\n","/**\n * Settings panel template\n */\n\nimport type { Settings, OutputLevel } from '../../core/types';\nimport { SCOPE_COLORS } from '../../core/types';\n\nexport interface SettingsPanelOptions {\n settings: Settings;\n skipAnimation?: boolean;\n}\n\n/**\n * Render the settings panel\n */\nexport function renderSettingsPanel(options: SettingsPanelOptions): string {\n const { settings, skipAnimation = false } = options;\n\n const outputLevelOptions: { value: OutputLevel; label: string }[] = [\n { value: 'compact', label: 'Compact' },\n { value: 'standard', label: 'Standard' },\n { value: 'detailed', label: 'Detailed' },\n { value: 'forensic', label: 'Forensic' },\n ];\n\n const colorOptions = Object.entries(SCOPE_COLORS).map(([name, hex]) => ({\n name,\n hex,\n active: settings.scopeColor === hex,\n }));\n\n return `\n <div class=\"settings-panel${skipAnimation ? ' no-animate' : ''}\" data-annotation-settings>\n <div class=\"settings-title\">Settings</div>\n\n <div class=\"settings-group\">\n <label class=\"settings-label\">Output Level</label>\n <select class=\"settings-select\" data-setting=\"outputLevel\">\n ${outputLevelOptions\n .map(\n (opt) =>\n `<option value=\"${opt.value}\" ${settings.outputLevel === opt.value ? 'selected' : ''}>${opt.label}</option>`\n )\n .join('')}\n </select>\n </div>\n\n <div class=\"settings-group\">\n <label class=\"settings-label\">Marker Color</label>\n <div class=\"color-picker\">\n ${colorOptions\n .map(\n (color) =>\n `<button\n class=\"color-option ${color.active ? 'active' : ''}\"\n style=\"background: ${color.hex};\"\n data-setting=\"scopeColor\"\n data-value=\"${color.hex}\"\n title=\"${color.name}\"\n ></button>`\n )\n .join('')}\n </div>\n </div>\n\n <div class=\"settings-group\">\n <div class=\"settings-toggle\">\n <span class=\"settings-toggle-label\">Block page interactions</span>\n <button\n class=\"settings-switch ${settings.blockInteractions ? 'active' : ''}\"\n data-setting=\"blockInteractions\"\n data-value=\"${!settings.blockInteractions}\"\n title=\"Prevent clicks from activating buttons/links while annotating\"\n ></button>\n </div>\n </div>\n\n <div class=\"settings-group\">\n <div class=\"settings-toggle\">\n <span class=\"settings-toggle-label\">Show tooltips</span>\n <button\n class=\"settings-switch ${settings.showTooltips ? 'active' : ''}\"\n data-setting=\"showTooltips\"\n data-value=\"${!settings.showTooltips}\"\n ></button>\n </div>\n </div>\n\n <div class=\"settings-group\">\n <div class=\"settings-toggle\">\n <span class=\"settings-toggle-label\">Auto-clear after copy</span>\n <button\n class=\"settings-switch ${settings.autoClearAfterCopy ? 'active' : ''}\"\n data-setting=\"autoClearAfterCopy\"\n data-value=\"${!settings.autoClearAfterCopy}\"\n ></button>\n </div>\n </div>\n </div>\n `;\n}\n","/**\n * Annotation Custom Element (Web Component)\n */\n\nimport type { AppState, Settings, OutputLevel, ThemeMode } from '../core/types';\nimport { createAnnotationCore, type AnnotationCore } from '../core/controller';\nimport { resolveTheme } from '../themes/variables';\nimport { componentStyles } from './styles';\nimport {\n renderCollapsedToolbar,\n renderExpandedToolbar,\n renderMarkers,\n renderPopup,\n renderHoverTooltip,\n renderHighlight,\n renderSelectionRect,\n renderSettingsPanel,\n} from './templates';\nimport { normalizeRect } from '../core/dom/multi-select';\n\n/**\n * Annotation Web Component\n *\n * Usage:\n * ```html\n * <agent-ui-annotation theme=\"auto\" output-level=\"standard\"></agent-ui-annotation>\n * ```\n *\n * Events:\n * - annotation:scope - Fired when a scope is created\n * - annotation:update - Fired when a scope is updated\n * - annotation:delete - Fired when a scope is deleted\n * - annotation:clear - Fired when all scopes are cleared\n * - annotation:copy - Fired when output is copied\n */\nexport class AnnotationElement extends HTMLElement {\n private core: AnnotationCore | null = null;\n private shadow: ShadowRoot;\n private unsubscribe: (() => void) | null = null;\n private styleElement: HTMLStyleElement;\n private contentElement: HTMLDivElement;\n\n // Popup state\n private isComposing = false;\n private popupShaking = false;\n\n // Hover tracking\n private mouseX = 0;\n private mouseY = 0;\n private hoveredMarkerId: string | null = null;\n\n // Track if toolbar has been shown before (to prevent re-animation)\n private toolbarShownOnce = false;\n\n // Track if settings panel has animated (to prevent re-animation on state changes)\n private settingsPanelAnimated = false;\n\n // Track which marker tooltip has animated (to prevent re-animation)\n private animatedMarkerTooltipId: string | null = null;\n\n // Track last rendered settings to avoid unnecessary re-renders when settings panel is open\n private lastRenderedSettings: string | null = null;\n\n static get observedAttributes() {\n return ['theme', 'output-level', 'scope-color', 'disabled'];\n }\n\n constructor() {\n super();\n\n // Create shadow DOM\n this.shadow = this.attachShadow({ mode: 'open' });\n\n // Create style element\n this.styleElement = document.createElement('style');\n this.styleElement.textContent = componentStyles;\n\n // Create content container\n this.contentElement = document.createElement('div');\n this.contentElement.className = 'annotation-root';\n\n this.shadow.appendChild(this.styleElement);\n this.shadow.appendChild(this.contentElement);\n }\n\n connectedCallback() {\n // Initialize core\n this.core = createAnnotationCore({\n settings: this.getSettingsFromAttributes(),\n loadPersisted: true,\n onScopeCreate: (scope) => this.dispatchScopeEvent('annotation:scope', { scope }),\n onScopeUpdate: (scope) => this.dispatchScopeEvent('annotation:update', { scope }),\n onScopeDelete: (id) => this.dispatchScopeEvent('annotation:delete', { id }),\n onScopesClear: (scopes) => this.dispatchScopeEvent('annotation:clear', { scopes }),\n onCopy: (content, level) => this.dispatchScopeEvent('annotation:copy', { content, level }),\n });\n\n // Subscribe to state changes\n this.unsubscribe = this.core.subscribe((state) => this.render(state));\n\n // Set up event listeners\n this.setupEventListeners();\n\n // Initial render\n this.render(this.core.store.getState());\n\n // Set theme attribute for CSS\n this.updateThemeAttribute();\n }\n\n disconnectedCallback() {\n // Clean up\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n\n if (this.core) {\n this.core.destroy();\n this.core = null;\n }\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {\n if (oldValue === newValue || !this.core) return;\n\n switch (name) {\n case 'theme':\n this.core.updateSettings({ theme: (newValue as ThemeMode) || 'auto' });\n this.updateThemeAttribute();\n break;\n\n case 'output-level':\n this.core.updateSettings({ outputLevel: (newValue as OutputLevel) || 'standard' });\n break;\n\n case 'scope-color':\n this.core.updateSettings({ scopeColor: newValue || '#AF52DE' });\n break;\n\n case 'disabled':\n if (newValue !== null) {\n this.core.deactivate();\n }\n break;\n }\n }\n\n /**\n * Public API\n */\n\n activate() {\n this.core?.activate();\n }\n\n deactivate() {\n this.core?.deactivate();\n }\n\n toggle() {\n this.core?.toggle();\n }\n\n async copyOutput(level?: OutputLevel): Promise<boolean> {\n return this.core?.copyOutput(level) ?? false;\n }\n\n getOutput(level?: OutputLevel): string {\n return this.core?.getOutput(level) ?? '';\n }\n\n clearAll() {\n this.core?.scopes.clearAllScopes();\n }\n\n /**\n * Private methods\n */\n\n private getSettingsFromAttributes(): Partial<Settings> {\n const settings: Partial<Settings> = {};\n\n const theme = this.getAttribute('theme');\n if (theme === 'light' || theme === 'dark' || theme === 'auto') {\n settings.theme = theme;\n }\n\n const outputLevel = this.getAttribute('output-level');\n if (outputLevel === 'compact' || outputLevel === 'standard' || outputLevel === 'detailed' || outputLevel === 'forensic') {\n settings.outputLevel = outputLevel;\n }\n\n const scopeColor = this.getAttribute('scope-color');\n if (scopeColor) {\n settings.scopeColor = scopeColor;\n }\n\n return settings;\n }\n\n private updateThemeAttribute() {\n if (!this.core) return;\n\n const theme = this.core.getSettings().theme;\n const resolved = resolveTheme(theme);\n\n this.setAttribute('data-theme', theme);\n // Also set resolved theme for CSS\n if (theme === 'auto') {\n this.setAttribute('data-resolved-theme', resolved);\n }\n }\n\n private setupEventListeners() {\n // Handle clicks on toolbar buttons\n this.shadow.addEventListener('click', this.handleClick.bind(this));\n\n // Handle mouse events for hover\n this.shadow.addEventListener('mouseover', this.handleMouseOver.bind(this));\n this.shadow.addEventListener('mouseout', this.handleMouseOut.bind(this));\n\n // Track mouse position for tooltip\n document.addEventListener('mousemove', this.handleMouseMove.bind(this));\n\n // Handle keyboard in popup\n this.shadow.addEventListener('keydown', this.handleKeyDown.bind(this) as EventListener);\n\n // Handle IME composition\n this.shadow.addEventListener('compositionstart', () => { this.isComposing = true; });\n this.shadow.addEventListener('compositionend', () => { this.isComposing = false; });\n\n // Handle select change for settings\n this.shadow.addEventListener('change', this.handleChange.bind(this));\n\n // Close settings panel when clicking outside\n document.addEventListener('click', this.handleDocumentClick.bind(this));\n }\n\n private handleDocumentClick(event: Event) {\n if (!this.core) return;\n\n const state = this.core.store.getState();\n if (!state.settingsPanelVisible) return;\n\n // Check if click was inside the Annotation element\n const path = event.composedPath();\n const clickedInside = path.some((el) => el === this);\n\n if (!clickedInside) {\n this.core.store.setState({ settingsPanelVisible: false });\n }\n }\n\n private handleChange(event: Event) {\n const target = event.target as HTMLElement;\n this.handleSettingChange(target);\n }\n\n private handleClick(event: Event) {\n const target = event.target as HTMLElement;\n const action = target.closest('[data-action]')?.getAttribute('data-action');\n const scopeId = target.closest('[data-scope-id]')?.getAttribute('data-scope-id');\n\n if (!this.core) return;\n\n switch (action) {\n case 'toggle':\n this.core.toggle();\n break;\n\n case 'close':\n this.core.deactivate();\n break;\n\n case 'freeze':\n this.core.freeze.toggle();\n break;\n\n case 'toggle-markers': {\n const state = this.core.store.getState();\n this.core.store.setState({ markersVisible: !state.markersVisible });\n break;\n }\n\n case 'copy':\n this.core.copyOutput();\n break;\n\n case 'clear':\n this.core.scopes.clearAllScopes();\n break;\n\n case 'theme': {\n const currentTheme = this.core.getSettings().theme;\n const resolved = resolveTheme(currentTheme);\n const newTheme = resolved === 'dark' ? 'light' : 'dark';\n this.core.updateSettings({ theme: newTheme });\n this.updateThemeAttribute();\n break;\n }\n\n case 'settings': {\n const currentState = this.core.store.getState();\n this.core.store.setState({ settingsPanelVisible: !currentState.settingsPanelVisible });\n break;\n }\n\n case 'popup-close':\n case 'popup-cancel':\n this.core.hidePopup();\n break;\n\n case 'popup-submit':\n this.handlePopupSubmit();\n break;\n\n case 'popup-delete':\n this.handlePopupDelete();\n break;\n }\n\n // Handle marker click\n if (scopeId && !action) {\n this.core.showPopup(scopeId);\n }\n\n // Handle settings panel changes\n const settingAttr = target.closest('[data-setting]')?.getAttribute('data-setting');\n if (settingAttr) {\n this.handleSettingChange(target);\n }\n }\n\n private handleSettingChange(target: HTMLElement) {\n if (!this.core) return;\n\n const settingElement = target.closest('[data-setting]') as HTMLElement;\n if (!settingElement) return;\n\n const setting = settingElement.getAttribute('data-setting');\n const value = settingElement.getAttribute('data-value');\n\n switch (setting) {\n case 'outputLevel': {\n const select = settingElement as HTMLSelectElement;\n this.core.updateSettings({ outputLevel: select.value as OutputLevel });\n break;\n }\n\n case 'scopeColor':\n if (value) {\n this.core.updateSettings({ scopeColor: value });\n }\n break;\n\n case 'blockInteractions':\n this.core.updateSettings({ blockInteractions: value === 'true' });\n break;\n\n case 'showTooltips':\n this.core.updateSettings({ showTooltips: value === 'true' });\n break;\n\n case 'autoClearAfterCopy':\n this.core.updateSettings({ autoClearAfterCopy: value === 'true' });\n break;\n }\n }\n\n private handleMouseOver(event: Event) {\n const target = event.target as HTMLElement;\n const marker = target.closest('[data-scope-id]');\n\n if (marker) {\n this.hoveredMarkerId = marker.getAttribute('data-scope-id');\n this.render(this.core!.store.getState());\n }\n }\n\n private handleMouseOut(event: Event) {\n const target = event.target as HTMLElement;\n const marker = target.closest('[data-scope-id]');\n\n if (marker) {\n this.hoveredMarkerId = null;\n this.render(this.core!.store.getState());\n }\n }\n\n private handleMouseMove(event: MouseEvent) {\n this.mouseX = event.clientX;\n this.mouseY = event.clientY;\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n const target = event.target as HTMLElement;\n\n if (!target.matches('[data-popup-input]')) return;\n\n // Submit on Enter (unless composing or shift held)\n if (event.key === 'Enter' && !event.shiftKey && !this.isComposing) {\n event.preventDefault();\n this.handlePopupSubmit();\n }\n\n // Cancel on Escape\n if (event.key === 'Escape') {\n event.preventDefault();\n this.core?.hidePopup();\n }\n }\n\n private handlePopupSubmit() {\n if (!this.core) return;\n\n const state = this.core.store.getState();\n const textarea = this.shadow.querySelector('[data-popup-input]') as HTMLTextAreaElement;\n const comment = textarea?.value?.trim() || '';\n\n if (state.popupAnnotationId) {\n // Update existing scope\n this.core.scopes.updateScope(state.popupAnnotationId, { comment });\n } else if (state.multiSelectElements.length > 1) {\n // Multi-select: create scopes for all selected elements\n for (let i = 0; i < state.multiSelectElements.length; i++) {\n const element = state.multiSelectElements[i];\n const elementInfo = state.multiSelectInfos[i];\n\n // Position marker at element center\n const rect = element.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n\n // Convert to document coords for non-fixed elements\n const isFixed = elementInfo.isFixed;\n const clickX = centerX;\n const clickY = isFixed ? centerY : centerY + window.scrollY;\n\n this.core.scopes.addScope(element, comment, {\n clickX,\n clickY,\n isMultiSelect: true,\n });\n }\n } else if (state.hoveredElement && state.popupElementInfo) {\n // Single element selection\n // Convert viewport coords to document coords for non-fixed elements\n const isFixed = state.popupElementInfo.isFixed;\n const clickX = state.popupClickX;\n const clickY = isFixed ? state.popupClickY : state.popupClickY + window.scrollY;\n\n // Create new scope with click position\n this.core.scopes.addScope(state.hoveredElement, comment, {\n clickX,\n clickY,\n });\n }\n\n this.core.hidePopup();\n }\n\n private handlePopupDelete() {\n if (!this.core) return;\n\n const state = this.core.store.getState();\n if (state.popupAnnotationId) {\n this.core.scopes.deleteScope(state.popupAnnotationId);\n this.core.hidePopup();\n }\n }\n\n private dispatchScopeEvent(name: string, detail: unknown) {\n this.dispatchEvent(\n new CustomEvent(name, {\n detail,\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private render(state: AppState) {\n const settings = state.settings;\n const scopes = Array.from(state.scopes.values()).sort((a, b) => a.number - b.number);\n const resolvedTheme = resolveTheme(settings.theme);\n\n // When settings panel is open, skip re-renders unless settings/visibility actually changed\n // This prevents the dropdown from closing when DOM is rebuilt\n if (state.settingsPanelVisible) {\n const currentSettingsKey = JSON.stringify({\n settings,\n settingsPanelVisible: state.settingsPanelVisible,\n scopeCount: scopes.length,\n isFrozen: state.isFrozen,\n markersVisible: state.markersVisible,\n theme: resolvedTheme,\n });\n\n if (this.lastRenderedSettings === currentSettingsKey) {\n // Nothing relevant changed, skip re-render to keep dropdown open\n return;\n }\n this.lastRenderedSettings = currentSettingsKey;\n } else {\n this.lastRenderedSettings = null;\n }\n\n let html = '';\n\n // Toolbar\n if (state.toolbarExpanded) {\n // Only show entrance animation on first expand\n const showEntranceAnimation = !this.toolbarShownOnce;\n if (showEntranceAnimation) {\n this.toolbarShownOnce = true;\n }\n\n // Track settings panel animation\n let settingsPanelHtml = '';\n if (state.settingsPanelVisible) {\n const skipSettingsAnimation = this.settingsPanelAnimated;\n settingsPanelHtml = renderSettingsPanel({ settings, skipAnimation: skipSettingsAnimation });\n this.settingsPanelAnimated = true;\n } else {\n // Reset when panel is hidden so animation plays again on next open\n this.settingsPanelAnimated = false;\n }\n\n html += renderExpandedToolbar({\n scopeCount: scopes.length,\n isFrozen: state.isFrozen,\n markersVisible: state.markersVisible,\n isDarkMode: resolvedTheme === 'dark',\n showCopiedFeedback: state.showCopiedFeedback,\n showClearedFeedback: state.showClearedFeedback,\n showEntranceAnimation,\n settingsPanelHtml,\n });\n } else {\n // Reset the flag when toolbar is collapsed so animation plays again on next expand\n this.toolbarShownOnce = false;\n this.settingsPanelAnimated = false;\n html += renderCollapsedToolbar(scopes.length);\n }\n\n // Markers\n if (state.toolbarExpanded && state.markersVisible) {\n // Show pending marker(s) if popup is open for new scope(s) (not editing existing)\n let pendingMarker = null;\n let pendingMarkers: Array<{ x: number; y: number; isFixed: boolean }> = [];\n\n if (state.popupVisible && !state.popupAnnotationId) {\n if (state.multiSelectElements.length > 1) {\n // Multi-select: create pending markers for all selected elements\n pendingMarkers = state.multiSelectElements.map((el, i) => {\n const rect = el.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const isFixed = state.multiSelectInfos[i]?.isFixed || false;\n\n return {\n x: centerX,\n y: isFixed ? centerY : centerY + window.scrollY,\n isFixed,\n };\n });\n } else if (state.pendingMarkerX !== 0) {\n // Single selection: show one pending marker\n pendingMarker = {\n x: state.pendingMarkerX,\n y: state.pendingMarkerY,\n isFixed: state.pendingMarkerIsFixed,\n };\n }\n }\n\n // Track marker tooltip animation - skip if same marker is still hovered\n const skipTooltipAnimation = this.hoveredMarkerId !== null && this.hoveredMarkerId === this.animatedMarkerTooltipId;\n if (this.hoveredMarkerId !== null) {\n this.animatedMarkerTooltipId = this.hoveredMarkerId;\n } else {\n this.animatedMarkerTooltipId = null;\n }\n\n html += renderMarkers({\n scopes,\n hoveredMarkerId: this.hoveredMarkerId,\n exitingMarkers: state.exitingMarkers,\n animatingMarkers: state.animatingMarkers,\n scrollY: state.scrollY,\n accentColor: settings.scopeColor,\n pendingMarker,\n pendingMarkers,\n skipTooltipAnimation,\n });\n }\n\n // Popup\n if (state.popupVisible) {\n const existingScope = state.popupAnnotationId ? state.scopes.get(state.popupAnnotationId) : null;\n html += renderPopup({\n elementInfo: existingScope?.elementInfo || state.popupElementInfo,\n existingScope: existingScope || null,\n isShaking: this.popupShaking,\n clickX: existingScope ? existingScope.clickX : state.popupClickX,\n clickY: existingScope ? existingScope.clickY : state.popupClickY,\n multiSelectInfos: state.multiSelectInfos,\n });\n }\n\n // Hover tooltip (only when not showing popup)\n if (state.toolbarExpanded && !state.popupVisible && state.hoveredElementInfo && settings.showTooltips) {\n html += renderHoverTooltip({\n elementInfo: state.hoveredElementInfo,\n x: this.mouseX,\n y: this.mouseY,\n });\n\n // Highlight\n if (state.hoveredElement) {\n const rect = state.hoveredElement.getBoundingClientRect();\n html += renderHighlight(rect, settings.scopeColor);\n }\n }\n\n // Selection rectangle and preview highlights\n if (state.isSelecting && state.selectionRect) {\n const normalized = normalizeRect(state.selectionRect);\n html += renderSelectionRect(normalized, settings.scopeColor);\n\n // Render highlights for elements within selection\n for (const element of state.selectionPreviewElements) {\n const rect = element.getBoundingClientRect();\n html += renderHighlight(rect, settings.scopeColor);\n }\n }\n\n this.contentElement.innerHTML = html;\n\n // Position toolbar\n this.positionToolbar(state);\n\n // Focus textarea in popup\n if (state.popupVisible) {\n const textarea = this.shadow.querySelector('[data-popup-input]') as HTMLTextAreaElement;\n textarea?.focus();\n }\n }\n\n private positionToolbar(state: AppState) {\n const toolbar = this.shadow.querySelector('.toolbar') as HTMLElement;\n if (!toolbar) return;\n\n // Default to bottom-right\n const padding = 20;\n const { toolbarPosition } = state.settings;\n\n let x: number, y: number;\n\n switch (toolbarPosition) {\n case 'top-left':\n x = padding;\n y = padding;\n break;\n case 'top-right':\n x = window.innerWidth - toolbar.offsetWidth - padding;\n y = padding;\n break;\n case 'bottom-left':\n x = padding;\n y = window.innerHeight - toolbar.offsetHeight - padding;\n break;\n case 'bottom-right':\n default:\n x = window.innerWidth - toolbar.offsetWidth - padding;\n y = window.innerHeight - toolbar.offsetHeight - padding;\n break;\n }\n\n // Use custom position if set\n if (state.toolbarPosition.x !== 20 || state.toolbarPosition.y !== 20) {\n x = state.toolbarPosition.x;\n y = state.toolbarPosition.y;\n }\n\n toolbar.style.left = `${x}px`;\n toolbar.style.top = `${y}px`;\n }\n}\n\n/**\n * Register the custom element\n */\nexport function registerAnnotationElement(tagName: string = 'agent-ui-annotation') {\n if (!customElements.get(tagName)) {\n customElements.define(tagName, AnnotationElement);\n }\n}\n","/**\n * Vanilla JS adapter for Annotation\n */\n\nimport type { Scope, AnnotationId, OutputLevel, ThemeMode, Settings } from '../../core/types';\nimport {\n AnnotationElement,\n registerAnnotationElement,\n} from '../../element/annotation-element';\n\n// Ensure custom element is registered\nregisterAnnotationElement();\n\nexport interface AnnotationOptions {\n /** Container element to append Annotation to (defaults to document.body) */\n container?: HTMLElement;\n /** Theme mode */\n theme?: ThemeMode;\n /** Output detail level */\n outputLevel?: OutputLevel;\n /** Scope marker color */\n scopeColor?: string;\n /** Whether to auto-activate on mount */\n autoActivate?: boolean;\n /** Callback when a scope is created */\n onScopeCreate?: (scope: Scope) => void;\n /** Callback when a scope is updated */\n onScopeUpdate?: (scope: Scope) => void;\n /** Callback when a scope is deleted */\n onScopeDelete?: (id: AnnotationId) => void;\n /** Callback when all scopes are cleared */\n onScopesClear?: (scopes: Scope[]) => void;\n /** Callback when output is copied */\n onCopy?: (content: string, level: OutputLevel) => void;\n}\n\nexport interface AnnotationInstance {\n /** The underlying custom element */\n element: AnnotationElement;\n /** Activate the tool */\n activate: () => void;\n /** Deactivate the tool */\n deactivate: () => void;\n /** Toggle activation */\n toggle: () => void;\n /** Copy output to clipboard */\n copyOutput: (level?: OutputLevel) => Promise<boolean>;\n /** Get output without copying */\n getOutput: (level?: OutputLevel) => string;\n /** Clear all scopes */\n clearAll: () => void;\n /** Destroy and remove the element */\n destroy: () => void;\n}\n\n/**\n * Create an Annotation instance\n *\n * @example\n * ```js\n * import { createAnnotation } from 'annotation/vanilla';\n *\n * const scope = createAnnotation({\n * theme: 'auto',\n * onScopeCreate: (scope) => console.log('Created:', scope),\n * });\n *\n * // Later:\n * scope.activate();\n * ```\n */\nexport function createAnnotation(options: AnnotationOptions = {}): AnnotationInstance {\n const {\n container = document.body,\n theme = 'auto',\n outputLevel = 'standard',\n scopeColor,\n autoActivate = false,\n onScopeCreate,\n onScopeUpdate,\n onScopeDelete,\n onScopesClear,\n onCopy,\n } = options;\n\n // Create element\n const element = document.createElement('agent-ui-annotation') as AnnotationElement;\n\n // Set attributes\n element.setAttribute('theme', theme);\n element.setAttribute('output-level', outputLevel);\n if (scopeColor) {\n element.setAttribute('scope-color', scopeColor);\n }\n\n // Add event listeners\n if (onScopeCreate) {\n element.addEventListener('annotation:scope', ((e: CustomEvent) => {\n onScopeCreate(e.detail.scope);\n }) as EventListener);\n }\n\n if (onScopeUpdate) {\n element.addEventListener('annotation:update', ((e: CustomEvent) => {\n onScopeUpdate(e.detail.scope);\n }) as EventListener);\n }\n\n if (onScopeDelete) {\n element.addEventListener('annotation:delete', ((e: CustomEvent) => {\n onScopeDelete(e.detail.id);\n }) as EventListener);\n }\n\n if (onScopesClear) {\n element.addEventListener('annotation:clear', ((e: CustomEvent) => {\n onScopesClear(e.detail.scopes);\n }) as EventListener);\n }\n\n if (onCopy) {\n element.addEventListener('annotation:copy', ((e: CustomEvent) => {\n onCopy(e.detail.content, e.detail.level);\n }) as EventListener);\n }\n\n // Append to container\n container.appendChild(element);\n\n // Auto-activate if requested\n if (autoActivate) {\n // Wait for next tick to ensure element is connected\n requestAnimationFrame(() => {\n element.activate();\n });\n }\n\n return {\n element,\n\n activate() {\n element.activate();\n },\n\n deactivate() {\n element.deactivate();\n },\n\n toggle() {\n element.toggle();\n },\n\n async copyOutput(level?: OutputLevel) {\n return element.copyOutput(level);\n },\n\n getOutput(level?: OutputLevel) {\n return element.getOutput(level);\n },\n\n clearAll() {\n element.clearAll();\n },\n\n destroy() {\n element.remove();\n },\n };\n}\n\n/**\n * Initialize Annotation with a simple API\n *\n * @example\n * ```js\n * import { init } from 'annotation/vanilla';\n *\n * const scope = init(); // Creates and activates immediately\n * ```\n */\nexport function init(options: Omit<AnnotationOptions, 'autoActivate'> = {}): AnnotationInstance {\n return createAnnotation({ ...options, autoActivate: true });\n}\n\n// Re-export types\nexport type { Scope, AnnotationId, OutputLevel, ThemeMode, Settings };\nexport { AnnotationElement, registerAnnotationElement };\n","/**\n * Annotation - Web page annotation toolbar for AI coding agents\n *\n * @example Basic usage (auto-registers custom element)\n * ```js\n * import 'annotation';\n *\n * // Add to HTML:\n * // <agent-ui-annotation theme=\"auto\"></agent-ui-annotation>\n * ```\n *\n * @example Vanilla JS\n * ```js\n * import { createAnnotation } from 'annotation';\n *\n * const scope = createAnnotation({\n * theme: 'dark',\n * onScopeCreate: (scope) => console.log('New scope:', scope),\n * });\n *\n * scope.activate();\n * ```\n *\n * @example React\n * ```jsx\n * import { Annotation } from 'annotation/react';\n *\n * function App() {\n * return (\n * <Annotation\n * theme=\"auto\"\n * onScopeCreate={(scope) => console.log('New scope:', scope)}\n * />\n * );\n * }\n * ```\n */\n\n// Auto-register custom element\nimport { registerAnnotationElement } from './element/annotation-element';\nregisterAnnotationElement();\n\n// Core exports\nexport {\n // Types\n type AnnotationId,\n type Position,\n type ElementRect,\n type AccessibilityInfo,\n type ComputedStylesSubset,\n type NearbyContext,\n type ElementInfo,\n type Scope,\n type OutputLevel,\n type ThemeMode,\n type ToolbarPosition,\n type ToolMode,\n type Settings,\n type SelectionRect,\n type EnvironmentInfo,\n type EventMap,\n type AppState,\n type AnnotationEventDetail,\n type AnnotationColor,\n SCOPE_COLORS,\n\n // Controller\n createAnnotationCore,\n type AnnotationCore,\n type AnnotationCoreOptions,\n\n // Store\n createStore,\n type Store,\n\n // Event Bus\n createEventBus,\n type EventBus,\n\n // Element utilities\n identifyElement,\n generateSelectorPath,\n collectElementInfo,\n} from './core';\n\n// Web Component\nexport {\n AnnotationElement,\n registerAnnotationElement,\n} from './element';\n\n// Vanilla adapter\nexport {\n createAnnotation,\n init,\n type AnnotationOptions,\n type AnnotationInstance,\n} from './adapters/vanilla';\n\n// Theme utilities\nexport {\n resolveTheme,\n getAccentColor,\n} from './themes';\n"],"names":["createStore","initialState","state","listeners","isBatching","hasChanges","isDestroyed","notify","entry","selected","error","partial","nextPartial","nextState","key","listener","selector","fn","newInitialState","createEventBus","handlers","emit","event","payload","eventHandlers","handler","on","unsubscribe","DEFAULT_SETTINGS","DEFAULT_TOOLBAR_POSITION","createInitialState","overrides","MAX_TEXT_LENGTH","truncate","text","maxLength","cleaned","getVisibleText","element","_a","clone","el","getAriaLabel","label","labelledBy","labelElement","getFormLabel","id","parentLabel","containsOnlyIcon","children","hasOnlySvg","child","textContent","identifyButton","ariaLabel","title","type","identifyLink","href","url","identifyInput","placeholder","name","desc","identifySelect","identifyTextarea","identifyHeading","level","identifyTextBlock","identifyImage","alt","src","filename","identifySvg","identifyVideo","identifyTableCell","isHeader","identifyListItem","identifyLabel","identifyContainer","role","classList","semanticClasses","cls","lowerCls","semantic","dataTestId","identifyElement","tagName","CSS_MODULE_HASH_PATTERN","HASH_PATTERNS","UTILITY_PREFIXES","cleanClassName","className","trimmed","prefix","pattern","match","cleanClassList","classes","cleanedName","getMeaningfulClasses","getFirstMeaningfulClass","meaningful","MAX_PATH_DEPTH","SKIP_TAGS","ANCHOR_TAGS","getElementSelector","cleanId","meaningfulClass","testId","isUniqueSelector","matches","getNthChildSuffix","parent","siblings","buildPathSegments","segments","current","depth","generateSelectorPath","directSelector","path","lastSegment","nthSuffix","generateFullDomPath","segment","index","INTERACTIVE_SELECTORS","isInteractive","getRole","explicitRole","getInputRole","getTabIndex","getReferencedText","attrValue","ids","texts","getAccessibilityInfo","getContainingLandmark","landmarkRoles","landmarkTags","describeLandmark","labelText","formatPropertyName","camelCase","getForensicStyles","computed","formatStyles","styles","prop","value","isFixedOrSticky","position","getElementRect","rect","getNearbyContext","prevSibling","nextSibling","landmark","getElementAttributes","result","skipAttrs","attr","getInnerText","collectElementInfo","includeForensic","generateAnnotationId","getNextScopeNumber","scopes","s","createScope","comment","existingScopes","options","selectedText","isMultiSelect","clickX","clickY","now","elementInfo","updateScopeComment","scope","renumberScopes","deletedNumber","newScopes","createAnnotationManager","store","eventBus","updates","updatedScope","renumberedScopes","a","b","SCOPE_KEY_PREFIX","SETTINGS_KEY","RETENTION_MS","getScopeStorageKey","serializeScope","deserializeScope","data","filterExpired","cutoff","saveScopes","serialized","loadScopes","stored","parsed","filtered","saveSettings","settings","loadSettings","createAutoSaver","getScopes","debounceMs","timeoutId","flush","getEnvironmentInfo","generateCompactScope","generateStandardScope","lines","generateDetailedScope","info","ctx","generateForensicScope","_env","attrEntries","a11y","generateHeader","scopeCount","generateForensicHeader","env","generateOutput","sortedScopes","parts","copyToClipboard","content","textarea","success","DATA_TOOLBAR","DATA_MARKER","DATA_POPUP","DATA_SETTINGS","isAnnotationElement","isAnnotationEvent","target","getTargetElement","createEventHandlers","isActive","handleClick","handleMouseDown","handleMouseMove","handleMouseUp","_event","elements","findElementsInRect","handleScroll","handleKeyDown","minX","maxX","minY","maxY","candidates","viewport","results","bounds","other","throttle","wait","leading","trailing","lastArgs","lastCallTime","lastInvokeTime","invoke","time","args","shouldInvoke","timeSinceLastCall","timeSinceLastInvoke","remainingWait","timeWaiting","timerExpired","trailingEdge","cancel","throttled","isInvoking","THROTTLE_MS","createHoverDetection","currentElement","throttledHandler","handleMouseLeave","relatedTarget","DRAG_THRESHOLD","MIN_SELECTION_SIZE","createMultiSelect","startPosition","isDragging","preventTextSelection","restoreTextSelection","handleStart","handleMove","dx","dy","distance","findElementsInSelection","handleEnd","previewElements","width","height","normalizeRect","x","y","FREEZE_STYLE_ID","FREEZE_CSS","createFreezeManager","isFrozen","styleElement","pausedVideos","injectFreezeStyles","removeFreezeStyles","pauseVideos","videos","video","resumeVideos","freeze","unfreeze","CURSOR_STYLE_ID","CURSOR_CSS","injectCursorStyles","removeCursorStyles","setMultiSelectMode","enabled","setDisabledState","disabled","cleanupCursorStyles","createAnnotationCore","initialSettings","loadPersisted","onScopeCreate","onScopeUpdate","onScopeDelete","onScopesClear","onCopy","shouldCopyToClipboard","persistedSettings","persistedScopes","mergedSettings","scopeManager","freezeManager","hoverDetection","multiSelect","autoSaver","currentSettings","viewportY","elementInfos","rects","r","centerX","centerY","activate","mode","deactivate","newSettings","merged","outputLevel","scopeId","LIGHT_THEME","DARK_THEME","SHARED_VARS","resolveTheme","getAccentColor","colors","varsToCSS","vars","componentStyles","icons","renderCollapsedToolbar","renderExpandedToolbar","markersVisible","isDarkMode","showCopiedFeedback","showClearedFeedback","showEntranceAnimation","settingsPanelHtml","getMarkerPosition","scrollY","isFixed","renderMarker","isHovered","isExiting","isAnimating","accentColor","skipTooltipAnimation","pos","style","renderMarkerTooltip","skipAnimation","escapeHtml","renderPendingMarker","pending","nextNumber","renderMarkers","hoveredMarkerId","exitingMarkers","animatingMarkers","pendingMarker","pendingMarkers","markerHtml","pendingHtml","pm","i","div","calculatePopupPosition","viewportWidth","viewportHeight","left","top","renderPopup","existingScope","isShaking","multiSelectInfos","isEditing","headerContent","elementList","remaining","calculateTooltipPosition","renderHoverTooltip","renderHighlight","renderSelectionRect","SCOPE_COLORS","renderSettingsPanel","outputLevelOptions","colorOptions","hex","opt","color","AnnotationElement","__publicField","oldValue","newValue","theme","scopeColor","resolved","_b","_c","action","currentTheme","newTheme","currentState","settingElement","setting","select","marker","detail","resolvedTheme","currentSettingsKey","html","skipSettingsAnimation","normalized","toolbar","padding","toolbarPosition","registerAnnotationElement","createAnnotation","container","autoActivate","e","init"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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"}
|