refinekit 0.2.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"refiner.js","sources":["../src/annotation-store.ts","../src/toolbar.ts","../src/overlay.ts","../src/annotation-dialog.ts","../src/annotation-marker.ts","../src/settings.ts","../src/mcp-bridge.ts","../src/refiner.ts","../src/styles.ts","../src/selector.ts","../src/index.ts"],"sourcesContent":["import { Annotation } from './types';\n\ntype Listener = (annotation: Annotation) => void;\n\nexport class AnnotationStore {\n private annotations: Map<string, Annotation> = new Map();\n private listeners: Map<string, Set<Listener>> = new Map();\n\n add(targetSelector: string, targetRect: DOMRect, text: string): Annotation {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n targetSelector,\n targetRect: {\n x: targetRect.x,\n y: targetRect.y,\n width: targetRect.width,\n height: targetRect.height,\n },\n text,\n timestamp: Date.now(),\n resolved: false,\n };\n this.annotations.set(annotation.id, annotation);\n this.emit('add', annotation);\n return annotation;\n }\n\n resolve(id: string): void {\n const annotation = this.annotations.get(id);\n if (annotation) {\n annotation.resolved = true;\n this.emit('resolve', annotation);\n }\n }\n\n remove(id: string): void {\n const annotation = this.annotations.get(id);\n if (annotation) {\n this.annotations.delete(id);\n this.emit('remove', annotation);\n }\n }\n\n get(id: string): Annotation | undefined {\n return this.annotations.get(id);\n }\n\n getAll(): Annotation[] {\n return Array.from(this.annotations.values());\n }\n\n getPending(): Annotation[] {\n return this.getAll().filter((a) => !a.resolved);\n }\n\n getCount(): number {\n return this.annotations.size;\n }\n\n exportJSON(): string {\n return JSON.stringify(this.getAll(), null, 2);\n }\n\n on(event: string, listener: Listener): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n off(event: string, listener: Listener): void {\n this.listeners.get(event)?.delete(listener);\n }\n\n private emit(event: string, annotation: Annotation): void {\n this.listeners.get(event)?.forEach((fn) => fn(annotation));\n }\n}\n","export class Toolbar {\n readonly el: HTMLElement;\n private collapsed = true;\n private countBadge!: HTMLElement;\n private expandBadge!: HTMLElement;\n private innerEl!: HTMLElement;\n private copyBtn!: HTMLElement;\n private clearBtn!: HTMLElement;\n private toggleBtn!: HTMLElement;\n private settingsOpen = false;\n\n onCopy?: () => void;\n onClear?: () => void;\n onSettings?: () => void;\n onCollapse?: () => void;\n onExpand?: () => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-toolbar';\n this.el.setAttribute('data-refiner-toolbar', '');\n this.el.setAttribute('data-collapsed', 'true');\n this.render();\n root.appendChild(this.el);\n\n // Expand on first load after a short delay\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.collapsed = false;\n this.el.setAttribute('data-collapsed', 'false');\n this.updateBadgeVisibility();\n });\n });\n }\n\n private render(): void {\n const pill = document.createElement('div');\n pill.className = 'toolbar-pill';\n\n // Inner (collapsible buttons)\n this.innerEl = document.createElement('div');\n this.innerEl.className = 'toolbar-inner';\n\n // Note count\n this.countBadge = document.createElement('span');\n this.countBadge.className = 'toolbar-count';\n this.countBadge.textContent = '0';\n this.innerEl.appendChild(this.createBtn(\n this.countBadge,\n 'Annotations',\n null,\n ));\n\n // Copy\n const copyIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`;\n const checkIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n this.copyBtn = this.createBtn(\n copyIcon,\n 'Copy annotations',\n () => {\n if (this.copyBtn.classList.contains('disabled')) return;\n this.onCopy?.();\n this.copyBtn.querySelector('.toolbar-icon')!.innerHTML = checkIcon;\n setTimeout(() => {\n this.copyBtn.querySelector('.toolbar-icon')!.innerHTML = copyIcon;\n }, 1500);\n },\n );\n this.copyBtn.classList.add('disabled');\n this.innerEl.appendChild(this.copyBtn);\n\n // Clear all\n this.clearBtn = this.createBtn(\n `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>`,\n 'Clear all',\n () => {\n if (this.clearBtn.classList.contains('disabled')) return;\n this.onClear?.();\n },\n );\n this.clearBtn.classList.add('disabled');\n this.innerEl.appendChild(this.clearBtn);\n\n // Settings\n this.innerEl.appendChild(this.createBtn(\n `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.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-4 0v-.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-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.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 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.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 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n 'Settings',\n () => this.onSettings?.(),\n ));\n\n // Divider\n const divider = document.createElement('div');\n divider.className = 'toolbar-divider';\n this.innerEl.appendChild(divider);\n\n pill.appendChild(this.innerEl);\n\n // Toggle button (always visible — pen when collapsed, X when expanded)\n const penIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\"/></svg>`;\n const xIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\n this.toggleBtn = this.createBtn(\n penIcon,\n '',\n () => this.toggleCollapse(),\n );\n this.toggleBtn.classList.add('toolbar-toggle-btn');\n pill.appendChild(this.toggleBtn);\n\n // Badge for collapsed state\n this.expandBadge = document.createElement('span');\n this.expandBadge.className = 'toolbar-expand-badge hidden';\n this.expandBadge.textContent = '0';\n pill.appendChild(this.expandBadge);\n\n this.el.appendChild(pill);\n\n // Update toggle icon on transition end\n this.el.addEventListener('transitionend', () => {\n const icon = this.toggleBtn.querySelector('.toolbar-icon')!;\n icon.innerHTML = this.collapsed ? penIcon : xIcon;\n });\n }\n\n private createBtn(content: string | HTMLElement, tooltip: string, onClick: (() => void) | null): HTMLElement {\n const btn = document.createElement('button');\n btn.className = 'toolbar-btn';\n\n const iconWrap = document.createElement('span');\n iconWrap.className = 'toolbar-icon';\n if (typeof content === 'string') {\n iconWrap.innerHTML = content;\n } else {\n iconWrap.appendChild(content);\n }\n btn.appendChild(iconWrap);\n\n if (tooltip) {\n const tip = document.createElement('span');\n tip.className = 'toolbar-tooltip';\n tip.textContent = tooltip;\n btn.appendChild(tip);\n }\n\n if (onClick) {\n btn.addEventListener('click', onClick);\n }\n\n return btn;\n }\n\n private toggleCollapse(): void {\n this.collapsed = !this.collapsed;\n this.el.setAttribute('data-collapsed', String(this.collapsed));\n this.updateBadgeVisibility();\n if (this.collapsed) {\n this.onCollapse?.();\n } else {\n this.onExpand?.();\n }\n }\n\n setSettingsOpen(open: boolean): void {\n this.settingsOpen = open;\n this.el.classList.toggle('tooltips-hidden', open);\n }\n\n updateCount(count: number): void {\n this.countBadge.textContent = String(count);\n this.expandBadge.textContent = String(count);\n this.updateBadgeVisibility(count);\n\n const empty = count === 0;\n this.copyBtn.classList.toggle('disabled', empty);\n this.clearBtn.classList.toggle('disabled', empty);\n }\n\n private updateBadgeVisibility(count?: number): void {\n const c = count ?? parseInt(this.expandBadge.textContent || '0', 10);\n this.expandBadge.classList.toggle('hidden', c === 0 || !this.collapsed);\n }\n}\n","export class Overlay {\n readonly el: HTMLElement;\n private highlight: HTMLElement;\n private enabled = true;\n private blocking = true;\n private currentTarget: Element | null = null;\n private highlightColor = '#7C3AED';\n\n onClick?: (target: Element, rect: DOMRect) => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-overlay';\n this.el.setAttribute('data-blocking', 'true');\n\n this.highlight = document.createElement('div');\n this.highlight.className = 'refiner-highlight';\n this.highlight.style.display = 'none';\n\n root.appendChild(this.highlight);\n root.appendChild(this.el);\n\n this.el.addEventListener('mousemove', this.handleMouseMove);\n this.el.addEventListener('click', this.handleClick);\n this.el.addEventListener('mouseleave', () => this.hideHighlight());\n\n document.addEventListener('keydown', this.handleKeyBlock, true);\n }\n\n private isOverOwnUI(x: number, y: number): boolean {\n const shadowEl = this.root.elementFromPoint(x, y);\n if (!shadowEl) return false;\n if (shadowEl === this.el || shadowEl === this.highlight) return false;\n return true;\n }\n\n private handleMouseMove = (e: MouseEvent): void => {\n if (!this.enabled) return;\n if (this.isOverOwnUI(e.clientX, e.clientY)) {\n this.hideHighlight();\n return;\n }\n\n const target = this.getElementAt(e.clientX, e.clientY);\n if (target && target !== this.currentTarget) {\n this.currentTarget = target;\n this.showHighlight(target);\n }\n };\n\n private handleClick = (e: MouseEvent): void => {\n if (!this.enabled) return;\n if (this.isOverOwnUI(e.clientX, e.clientY)) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n const target = this.getElementAt(e.clientX, e.clientY);\n if (target) {\n const rect = target.getBoundingClientRect();\n this.onClick?.(target, rect);\n }\n };\n\n private handleKeyBlock = (e: KeyboardEvent): void => {\n if (!this.enabled || !this.blocking) return;\n // Allow keys when focus is inside refiner's own UI (e.g. annotation dialog textarea)\n const target = e.target as Element;\n if (target && (target === this.root.host || this.root.host.contains(target))) return;\n\n e.preventDefault();\n e.stopPropagation();\n };\n\n private getElementAt(x: number, y: number): Element | null {\n this.el.style.pointerEvents = 'none';\n this.highlight.style.pointerEvents = 'none';\n\n const el = document.elementFromPoint(x, y);\n\n this.el.style.pointerEvents = '';\n this.highlight.style.pointerEvents = '';\n\n if (el && el === this.root.host) return null;\n return el;\n }\n\n private showHighlight(target: Element): void {\n const rect = target.getBoundingClientRect();\n this.highlight.style.display = 'block';\n this.highlight.style.top = `${rect.top - 2}px`;\n this.highlight.style.left = `${rect.left - 2}px`;\n this.highlight.style.width = `${rect.width + 4}px`;\n this.highlight.style.height = `${rect.height + 4}px`;\n this.highlight.style.borderColor = this.highlightColor;\n }\n\n private hideHighlight(): void {\n this.highlight.style.display = 'none';\n this.currentTarget = null;\n }\n\n setHighlightColor(color: string): void {\n this.highlightColor = color;\n }\n\n setBlocking(blocking: boolean): void {\n this.blocking = blocking;\n this.el.setAttribute('data-blocking', String(blocking));\n if (!blocking) {\n this.hideHighlight();\n }\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n this.el.classList.toggle('hidden', !enabled);\n if (!enabled) this.hideHighlight();\n }\n}\n","export class AnnotationDialog {\n readonly el: HTMLElement;\n private textarea!: HTMLTextAreaElement;\n private addBtn!: HTMLButtonElement;\n\n onSubmit?: (text: string) => void;\n onCancel?: () => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-dialog hidden';\n this.render();\n root.appendChild(this.el);\n }\n\n private render(): void {\n // Header\n const header = document.createElement('div');\n header.className = 'dialog-header';\n const label = document.createElement('span');\n label.textContent = 'What should change?';\n header.appendChild(label);\n this.el.appendChild(header);\n\n // Textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'dialog-textarea';\n this.textarea.placeholder = 'Describe the issue or improvement...';\n this.textarea.addEventListener('input', () => {\n this.addBtn.disabled = this.textarea.value.trim().length === 0;\n });\n this.textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && this.textarea.value.trim()) {\n this.submit();\n }\n if (e.key === 'Escape') {\n this.hide();\n this.onCancel?.();\n }\n });\n this.el.appendChild(this.textarea);\n\n // Actions\n const actions = document.createElement('div');\n actions.className = 'dialog-actions';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'dialog-btn dialog-btn-cancel';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n this.hide();\n this.onCancel?.();\n });\n\n this.addBtn = document.createElement('button');\n this.addBtn.className = 'dialog-btn dialog-btn-add';\n this.addBtn.textContent = 'Add';\n this.addBtn.disabled = true;\n this.addBtn.addEventListener('click', () => this.submit());\n\n actions.appendChild(cancelBtn);\n actions.appendChild(this.addBtn);\n this.el.appendChild(actions);\n }\n\n private submit(): void {\n const text = this.textarea.value.trim();\n if (text) {\n this.onSubmit?.(text);\n this.hide();\n }\n }\n\n show(x: number, y: number): void {\n // Position: prefer below-right of click, but keep on screen\n const dialogW = 320;\n const dialogH = 200;\n let left = x + 12;\n let top = y + 12;\n\n if (left + dialogW > window.innerWidth - 16) {\n left = x - dialogW - 12;\n }\n if (top + dialogH > window.innerHeight - 16) {\n top = y - dialogH - 12;\n }\n\n this.el.style.left = `${Math.max(16, left)}px`;\n this.el.style.top = `${Math.max(16, top)}px`;\n this.el.classList.remove('hidden');\n\n this.textarea.value = '';\n this.addBtn.disabled = true;\n requestAnimationFrame(() => this.textarea.focus());\n }\n\n hide(): void {\n this.el.classList.add('hidden');\n this.textarea.value = '';\n }\n\n isVisible(): boolean {\n return !this.el.classList.contains('hidden');\n }\n}\n","import { Annotation } from './types';\nimport { AnnotationStore } from './annotation-store';\n\ninterface MarkerElement {\n el: HTMLElement;\n annotation: Annotation;\n}\n\nexport class AnnotationMarkers {\n private markers: Map<string, MarkerElement> = new Map();\n private container: HTMLElement;\n private rafId: number | null = null;\n private color = '#7C3AED';\n\n constructor(private root: ShadowRoot, private store: AnnotationStore) {\n this.container = document.createElement('div');\n this.container.className = 'refiner-markers';\n root.appendChild(this.container);\n\n store.on('add', (annotation) => this.addMarker(annotation));\n store.on('resolve', (annotation) => this.updateMarker(annotation));\n store.on('remove', (annotation) => this.removeMarker(annotation.id));\n\n const reposition = () => this.repositionAll();\n window.addEventListener('scroll', reposition, { passive: true });\n window.addEventListener('resize', reposition, { passive: true });\n }\n\n private addMarker(annotation: Annotation): void {\n const el = document.createElement('div');\n el.className = 'refiner-marker';\n el.setAttribute('data-annotation-marker', annotation.id);\n el.setAttribute('data-resolved', String(annotation.resolved));\n el.style.background = this.color;\n\n const index = this.markers.size + 1;\n el.textContent = String(index);\n\n // Tooltip\n const tooltip = document.createElement('div');\n tooltip.className = 'marker-tooltip';\n\n const tooltipText = document.createElement('div');\n tooltipText.textContent = annotation.text;\n tooltip.appendChild(tooltipText);\n\n const tooltipActions = document.createElement('div');\n tooltipActions.className = 'marker-tooltip-actions';\n\n const resolveBtn = document.createElement('button');\n resolveBtn.className = 'marker-tooltip-btn resolve';\n resolveBtn.textContent = 'Resolve';\n resolveBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.store.resolve(annotation.id);\n });\n\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'marker-tooltip-btn delete';\n deleteBtn.textContent = 'Delete';\n deleteBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.store.remove(annotation.id);\n });\n\n tooltipActions.appendChild(resolveBtn);\n tooltipActions.appendChild(deleteBtn);\n tooltip.appendChild(tooltipActions);\n el.appendChild(tooltip);\n\n this.positionMarker(el, annotation);\n this.container.appendChild(el);\n this.markers.set(annotation.id, { el, annotation });\n }\n\n private updateMarker(annotation: Annotation): void {\n const marker = this.markers.get(annotation.id);\n if (marker) {\n marker.annotation = annotation;\n marker.el.setAttribute('data-resolved', String(annotation.resolved));\n }\n }\n\n private removeMarker(id: string): void {\n const marker = this.markers.get(id);\n if (marker) {\n marker.el.remove();\n this.markers.delete(id);\n this.renumber();\n }\n }\n\n private renumber(): void {\n let i = 1;\n for (const [, marker] of this.markers) {\n const firstText = marker.el.childNodes[0];\n if (firstText && firstText.nodeType === Node.TEXT_NODE) {\n firstText.textContent = String(i);\n }\n i++;\n }\n }\n\n private positionMarker(el: HTMLElement, annotation: Annotation): void {\n const target = this.queryTarget(annotation.targetSelector);\n if (target) {\n const rect = target.getBoundingClientRect();\n el.style.top = `${rect.top - 8}px`;\n el.style.left = `${rect.right - 8}px`;\n } else {\n el.style.top = `${annotation.targetRect.y - 8}px`;\n el.style.left = `${annotation.targetRect.x + annotation.targetRect.width - 8}px`;\n }\n }\n\n private queryTarget(selector: string): Element | null {\n try {\n return document.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n setColor(color: string): void {\n this.color = color;\n for (const [, marker] of this.markers) {\n marker.el.style.background = color;\n }\n }\n\n clearAll(): void {\n for (const [id] of this.markers) {\n this.removeMarker(id);\n }\n }\n\n private repositionAll(): void {\n if (this.rafId !== null) return;\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n for (const [, marker] of this.markers) {\n this.positionMarker(marker.el, marker.annotation);\n }\n });\n }\n}\n","const MARKER_COLORS = [\n { id: 'purple', color: '#7C3AED' },\n { id: 'blue', color: '#2563EB' },\n { id: 'green', color: '#059669' },\n { id: 'yellow', color: '#D97706' },\n { id: 'orange', color: '#EA580C' },\n { id: 'red', color: '#DC2626' },\n { id: 'pink', color: '#DB2777' },\n];\n\nexport interface Settings {\n clearOnCopy: boolean;\n blockInteractions: boolean;\n markerColor: string;\n}\n\nexport class SettingsPanel {\n readonly el: HTMLElement;\n private visible = false;\n private mcpDot!: HTMLElement;\n private mcpLabel!: HTMLElement;\n private settings: Settings = {\n clearOnCopy: false,\n blockInteractions: true,\n markerColor: '#7C3AED',\n };\n\n onChange?: (settings: Settings) => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'settings-panel hidden';\n this.render();\n root.appendChild(this.el);\n }\n\n private render(): void {\n // Header\n const header = document.createElement('div');\n header.className = 'settings-header';\n const title = document.createElement('span');\n title.className = 'settings-title';\n title.textContent = 'reFiner';\n const version = document.createElement('span');\n version.className = 'settings-version';\n version.textContent = 'v0.1.0';\n header.appendChild(title);\n header.appendChild(version);\n this.el.appendChild(header);\n\n this.el.appendChild(this.createDivider());\n\n // Marker color\n const colorSection = document.createElement('div');\n colorSection.className = 'settings-section';\n const colorLabel = document.createElement('span');\n colorLabel.className = 'settings-label';\n colorLabel.textContent = 'Marker Colour';\n colorSection.appendChild(colorLabel);\n\n const colorRow = document.createElement('div');\n colorRow.className = 'settings-color-row';\n for (const mc of MARKER_COLORS) {\n const swatch = document.createElement('button');\n swatch.className = 'settings-swatch';\n swatch.style.background = mc.color;\n swatch.setAttribute('data-color', mc.color);\n if (mc.color === this.settings.markerColor) {\n swatch.classList.add('selected');\n }\n swatch.addEventListener('click', () => {\n colorRow.querySelectorAll('.settings-swatch').forEach((s) =>\n s.classList.remove('selected')\n );\n swatch.classList.add('selected');\n this.settings.markerColor = mc.color;\n this.emitChange();\n });\n colorRow.appendChild(swatch);\n }\n colorSection.appendChild(colorRow);\n this.el.appendChild(colorSection);\n\n this.el.appendChild(this.createDivider());\n\n // Clear on copy\n this.el.appendChild(this.createCheckbox(\n 'Clear on copy',\n this.settings.clearOnCopy,\n (checked) => {\n this.settings.clearOnCopy = checked;\n this.emitChange();\n },\n ));\n\n // Block page interactions\n this.el.appendChild(this.createCheckbox(\n 'Block page interactions',\n this.settings.blockInteractions,\n (checked) => {\n this.settings.blockInteractions = checked;\n this.emitChange();\n },\n ));\n\n this.el.appendChild(this.createDivider());\n\n // MCP status\n const mcpRow = document.createElement('div');\n mcpRow.className = 'settings-mcp-row';\n\n this.mcpDot = document.createElement('span');\n this.mcpDot.className = 'settings-mcp-dot disconnected';\n\n this.mcpLabel = document.createElement('span');\n this.mcpLabel.className = 'settings-check-label';\n this.mcpLabel.textContent = 'MCP Disconnected';\n\n mcpRow.appendChild(this.mcpDot);\n mcpRow.appendChild(this.mcpLabel);\n this.el.appendChild(mcpRow);\n }\n\n private createCheckbox(label: string, initial: boolean, onChange: (v: boolean) => void): HTMLElement {\n const row = document.createElement('label');\n row.className = 'settings-check-row';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'settings-checkbox';\n checkbox.checked = initial;\n checkbox.addEventListener('change', () => onChange(checkbox.checked));\n\n const text = document.createElement('span');\n text.className = 'settings-check-label';\n text.textContent = label;\n\n row.appendChild(checkbox);\n row.appendChild(text);\n return row;\n }\n\n private createDivider(): HTMLElement {\n const div = document.createElement('div');\n div.className = 'settings-divider';\n return div;\n }\n\n private emitChange(): void {\n this.onChange?.({ ...this.settings });\n }\n\n toggle(): void {\n this.visible = !this.visible;\n this.el.classList.toggle('hidden', !this.visible);\n }\n\n hide(): void {\n this.visible = false;\n this.el.classList.add('hidden');\n }\n\n isVisible(): boolean {\n return this.visible;\n }\n\n setMcpStatus(connected: boolean): void {\n this.mcpDot.className = `settings-mcp-dot ${connected ? 'connected' : 'disconnected'}`;\n this.mcpLabel.textContent = connected ? 'MCP Connected' : 'MCP Disconnected';\n }\n\n getSettings(): Settings {\n return { ...this.settings };\n }\n}\n","import { AnnotationStore } from './annotation-store';\nimport { Annotation } from './types';\n\nexport class McpBridge {\n private baseUrl: string;\n private sessionId: string | null = null;\n private connected = false;\n private retryTimer: ReturnType<typeof setInterval> | null = null;\n\n onChange?: (connected: boolean) => void;\n\n constructor(\n private store: AnnotationStore,\n port: number = 4848,\n ) {\n this.baseUrl = `http://localhost:${port}`;\n this.discover();\n\n // Wire up store events\n this.store.on('add', (annotation) => this.postAnnotation(annotation));\n this.store.on('resolve', (annotation) => this.patchAnnotation(annotation));\n }\n\n private async discover(): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/health`);\n const data = await res.json();\n if (data && typeof data === 'object' && 'status' in data && data.status === 'ok') {\n this.connected = true;\n this.onChange?.(true);\n await this.createSession();\n this.stopRetry();\n }\n } catch {\n this.connected = false;\n this.onChange?.(false);\n this.startRetry();\n }\n }\n\n private startRetry(): void {\n if (this.retryTimer) return;\n this.retryTimer = setInterval(() => this.discover(), 5000);\n }\n\n private stopRetry(): void {\n if (this.retryTimer) {\n clearInterval(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n private async createSession(): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/sessions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n url: window.location.href,\n title: document.title || window.location.pathname,\n }),\n });\n const session = await res.json();\n this.sessionId = session.id;\n } catch {\n // Session creation failed — annotations won't sync but local still works\n }\n }\n\n private async postAnnotation(annotation: Annotation): Promise<void> {\n if (!this.connected || !this.sessionId) return;\n\n try {\n await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n targetSelector: annotation.targetSelector,\n targetRect: annotation.targetRect,\n text: annotation.text,\n }),\n });\n } catch {\n // Silently fail — local annotation still exists\n }\n }\n\n private async patchAnnotation(annotation: Annotation): Promise<void> {\n if (!this.connected) return;\n\n try {\n await fetch(`${this.baseUrl}/annotations/${annotation.id}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n resolved: true,\n summary: 'Resolved from browser',\n }),\n });\n } catch {\n // Silently fail\n }\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n destroy(): void {\n this.stopRetry();\n }\n}\n","import { RefinerOptions } from './types';\nimport { STYLES } from './styles';\nimport { AnnotationStore } from './annotation-store';\nimport { Toolbar } from './toolbar';\nimport { Overlay } from './overlay';\nimport { AnnotationDialog } from './annotation-dialog';\nimport { AnnotationMarkers } from './annotation-marker';\nimport { SettingsPanel } from './settings';\nimport { generateSelector } from './selector';\nimport { McpBridge } from './mcp-bridge';\n\nexport class Refiner {\n private host: HTMLDivElement;\n private shadow: ShadowRoot;\n private store: AnnotationStore;\n private toolbar: Toolbar;\n private overlay: Overlay;\n private dialog: AnnotationDialog;\n private markers: AnnotationMarkers;\n private settings: SettingsPanel;\n private mcpBridge: McpBridge | null = null;\n private currentTarget: Element | null = null;\n private currentRect: DOMRect | null = null;\n private clearOnCopy = false;\n\n constructor(options: RefinerOptions = {}) {\n // Create shadow host\n this.host = document.createElement('div');\n this.host.id = 'refiner-host';\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = STYLES;\n this.shadow.appendChild(style);\n\n // Initialize components\n this.store = new AnnotationStore();\n this.toolbar = new Toolbar(this.shadow);\n this.settings = new SettingsPanel(this.shadow);\n this.overlay = new Overlay(this.shadow);\n this.dialog = new AnnotationDialog(this.shadow);\n this.markers = new AnnotationMarkers(this.shadow, this.store);\n\n // Wire up toolbar\n this.toolbar.onCopy = () => this.copyAnnotations();\n this.toolbar.onClear = () => this.clearAnnotations();\n this.toolbar.onSettings = () => {\n this.settings.toggle();\n this.toolbar.setSettingsOpen(this.settings.isVisible());\n };\n\n this.toolbar.onCollapse = () => {\n this.settings.hide();\n this.toolbar.setSettingsOpen(false);\n this.overlay.setEnabled(false);\n this.host.style.pointerEvents = 'none';\n };\n\n this.toolbar.onExpand = () => {\n this.overlay.setEnabled(true);\n this.host.style.pointerEvents = '';\n };\n\n // Wire up settings\n this.settings.onChange = (s) => {\n this.clearOnCopy = s.clearOnCopy;\n this.overlay.setBlocking(s.blockInteractions);\n this.markers.setColor(s.markerColor);\n this.overlay.setHighlightColor(s.markerColor);\n };\n\n // Wire up overlay click\n this.overlay.onClick = (target, rect) => {\n if (this.settings.isVisible()) {\n this.settings.hide();\n return;\n }\n if (this.dialog.isVisible()) {\n this.dialog.hide();\n return;\n }\n this.currentTarget = target;\n this.currentRect = rect;\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n this.dialog.show(centerX, centerY);\n };\n\n // Wire up dialog submit\n this.dialog.onSubmit = (text) => {\n if (this.currentTarget && this.currentRect) {\n const selector = generateSelector(this.currentTarget);\n this.store.add(selector, this.currentRect, text);\n this.toolbar.updateCount(this.store.getCount());\n }\n this.currentTarget = null;\n this.currentRect = null;\n };\n\n this.dialog.onCancel = () => {\n this.currentTarget = null;\n this.currentRect = null;\n };\n\n // Update count on resolve/remove\n this.store.on('resolve', () => this.toolbar.updateCount(this.store.getCount()));\n this.store.on('remove', () => this.toolbar.updateCount(this.store.getCount()));\n\n // MCP bridge (auto-discover by default)\n if (options.mcpEnabled !== false) {\n this.mcpBridge = new McpBridge(this.store, options.mcpPort);\n this.mcpBridge.onChange = (connected) => {\n this.settings.setMcpStatus(connected);\n };\n }\n\n // Mount\n document.body.appendChild(this.host);\n\n if (options.enabled === false) {\n this.disable();\n }\n }\n\n enable(): void {\n this.host.style.display = '';\n this.overlay.setEnabled(true);\n }\n\n disable(): void {\n this.host.style.display = 'none';\n this.overlay.setEnabled(false);\n }\n\n destroy(): void {\n this.mcpBridge?.destroy();\n this.host.remove();\n }\n\n getAnnotations() {\n return this.store.getAll();\n }\n\n getAnnotationCount(): number {\n return this.store.getCount();\n }\n\n formatForAgent(): string {\n const annotations = this.store.getAll();\n if (annotations.length === 0) return 'No annotations.';\n\n const pageTitle = document.title || window.location.pathname;\n const pathname = window.location.pathname;\n const filename = pathname.substring(pathname.lastIndexOf('/') + 1) || 'index.html';\n const lines: string[] = [\n `# Design Annotations — ${pageTitle}`,\n `**File:** \\`${filename}\\``,\n '',\n ];\n\n for (let i = 0; i < annotations.length; i++) {\n const a = annotations[i];\n const status = a.resolved ? ' (resolved)' : '';\n lines.push(`## ${i + 1}.${status}`);\n lines.push(`**Element:** \\`${a.targetSelector}\\``);\n lines.push(`**Issue:** ${a.text}`);\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n clearAnnotations(): void {\n const all = this.store.getAll();\n for (const a of all) {\n this.store.remove(a.id);\n }\n this.toolbar.updateCount(0);\n }\n\n copyAnnotations(): void {\n const text = this.formatForAgent();\n navigator.clipboard.writeText(text);\n\n if (this.clearOnCopy) {\n this.clearAnnotations();\n }\n }\n}\n","export const STYLES = `\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed=\"true\"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed=\"true\"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking=\"true\"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking=\"false\"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved=\"true\"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n`;\n","/**\n * Generate a stable CSS selector for a DOM element.\n * Priority: #id > tag.class > nth-child path\n */\nexport function generateSelector(el: Element): string {\n if (el.id) {\n return `#${CSS.escape(el.id)}`;\n }\n\n // Try tag + distinctive class\n if (el.classList.length > 0) {\n const tag = el.tagName.toLowerCase();\n const classSelector = `${tag}.${Array.from(el.classList).map(CSS.escape).join('.')}`;\n if (document.querySelectorAll(classSelector).length === 1) {\n return classSelector;\n }\n }\n\n // Build nth-child path\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n parts.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c: Element) => c.tagName === current!.tagName\n );\n if (siblings.length === 1) {\n parts.unshift(tag);\n } else {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n}\n","import { Refiner } from './refiner';\nimport type { Annotation, RefinerOptions } from './types';\n\nexport { Refiner };\nexport type { Annotation, RefinerOptions };\n\n// Auto-initialize when loaded via script tag\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const init = () => {\n // Skip if already initialized (e.g. bookmarklet + script tag both present)\n if ((window as any).__refiner) return;\n\n // Read config from script tag data attributes\n const script = document.currentScript as HTMLScriptElement | null;\n const position = (script?.dataset.refinerPosition as 'left' | 'right') ?? 'right';\n const enabled = script?.dataset.refinerEnabled !== 'false';\n const mcpPort = script?.dataset.refinerMcpPort ? parseInt(script.dataset.refinerMcpPort, 10) : undefined;\n const mcpEnabled = script?.dataset.refinerMcpEnabled !== 'false';\n\n const refiner = new Refiner({ position, enabled, mcpPort, mcpEnabled });\n (window as any).__refiner = refiner;\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', init);\n } else {\n init();\n }\n}\n"],"names":["AnnotationStore","constructor","this","annotations","Map","listeners","add","targetSelector","targetRect","text","annotation","id","crypto","randomUUID","x","y","width","height","timestamp","Date","now","resolved","set","emit","resolve","get","remove","delete","getAll","Array","from","values","getPending","filter","a","getCount","size","exportJSON","JSON","stringify","on","event","listener","has","Set","off","forEach","fn","Toolbar","root","collapsed","settingsOpen","el","document","createElement","className","setAttribute","render","appendChild","requestAnimationFrame","updateBadgeVisibility","pill","innerEl","countBadge","textContent","createBtn","copyIcon","copyBtn","classList","contains","onCopy","querySelector","innerHTML","setTimeout","clearBtn","onClear","onSettings","divider","penIcon","toggleBtn","toggleCollapse","expandBadge","addEventListener","content","tooltip","onClick","btn","iconWrap","tip","String","onCollapse","onExpand","setSettingsOpen","open","toggle","updateCount","count","empty","c","parseInt","Overlay","enabled","blocking","currentTarget","highlightColor","handleMouseMove","e","isOverOwnUI","clientX","clientY","hideHighlight","target","getElementAt","showHighlight","handleClick","preventDefault","stopPropagation","rect","getBoundingClientRect","handleKeyBlock","host","highlight","style","display","shadowEl","elementFromPoint","pointerEvents","top","left","borderColor","setHighlightColor","color","setBlocking","setEnabled","AnnotationDialog","header","label","textarea","placeholder","addBtn","disabled","value","trim","length","key","metaKey","ctrlKey","submit","hide","onCancel","actions","cancelBtn","onSubmit","show","window","innerWidth","innerHeight","Math","max","focus","isVisible","AnnotationMarkers","store","markers","rafId","container","addMarker","updateMarker","removeMarker","reposition","repositionAll","passive","background","index","tooltipText","tooltipActions","resolveBtn","deleteBtn","positionMarker","marker","renumber","i","firstText","childNodes","nodeType","Node","TEXT_NODE","queryTarget","right","selector","setColor","clearAll","MARKER_COLORS","SettingsPanel","visible","settings","clearOnCopy","blockInteractions","markerColor","title","version","createDivider","colorSection","colorLabel","colorRow","mc","swatch","querySelectorAll","s","emitChange","createCheckbox","checked","mcpRow","mcpDot","mcpLabel","initial","onChange","row","checkbox","type","div","setMcpStatus","connected","getSettings","McpBridge","port","sessionId","retryTimer","baseUrl","discover","postAnnotation","patchAnnotation","res","fetch","data","json","status","createSession","stopRetry","startRetry","setInterval","clearInterval","method","headers","body","url","location","href","pathname","session","summary","isConnected","destroy","Refiner","options","mcpBridge","currentRect","shadow","attachShadow","mode","toolbar","overlay","dialog","copyAnnotations","clearAnnotations","centerX","centerY","CSS","escape","classSelector","tagName","toLowerCase","map","join","parts","current","documentElement","tag","parent","parentElement","unshift","siblings","children","indexOf","generateSelector","mcpEnabled","mcpPort","disable","enable","getAnnotations","getAnnotationCount","formatForAgent","pageTitle","lines","substring","lastIndexOf","push","all","navigator","clipboard","writeText","init","__refiner","script","currentScript","position","dataset","refinerPosition","refinerEnabled","refinerMcpPort","undefined","refinerMcpEnabled","refiner","readyState"],"mappings":"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"}
1
+ {"version":3,"file":"refiner.js","sources":["../src/annotation-store.ts","../src/toolbar.ts","../src/overlay.ts","../src/annotation-dialog.ts","../src/annotation-marker.ts","../src/settings.ts","../src/mcp-bridge.ts","../src/refiner.ts","../src/styles.ts","../src/selector.ts","../src/index.ts"],"sourcesContent":["import { Annotation } from './types';\n\ntype Listener = (annotation: Annotation) => void;\n\nexport class AnnotationStore {\n private annotations: Map<string, Annotation> = new Map();\n private listeners: Map<string, Set<Listener>> = new Map();\n\n add(targetSelector: string, targetRect: DOMRect, text: string): Annotation {\n const annotation: Annotation = {\n id: crypto.randomUUID(),\n targetSelector,\n targetRect: {\n x: targetRect.x,\n y: targetRect.y,\n width: targetRect.width,\n height: targetRect.height,\n },\n text,\n timestamp: Date.now(),\n resolved: false,\n };\n this.annotations.set(annotation.id, annotation);\n this.emit('add', annotation);\n return annotation;\n }\n\n resolve(id: string): void {\n const annotation = this.annotations.get(id);\n if (annotation) {\n annotation.resolved = true;\n this.emit('resolve', annotation);\n }\n }\n\n remove(id: string): void {\n const annotation = this.annotations.get(id);\n if (annotation) {\n this.annotations.delete(id);\n this.emit('remove', annotation);\n }\n }\n\n get(id: string): Annotation | undefined {\n return this.annotations.get(id);\n }\n\n getAll(): Annotation[] {\n return Array.from(this.annotations.values());\n }\n\n getPending(): Annotation[] {\n return this.getAll().filter((a) => !a.resolved);\n }\n\n getCount(): number {\n return this.annotations.size;\n }\n\n exportJSON(): string {\n return JSON.stringify(this.getAll(), null, 2);\n }\n\n on(event: string, listener: Listener): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n off(event: string, listener: Listener): void {\n this.listeners.get(event)?.delete(listener);\n }\n\n private emit(event: string, annotation: Annotation): void {\n this.listeners.get(event)?.forEach((fn) => fn(annotation));\n }\n}\n","export class Toolbar {\n readonly el: HTMLElement;\n private collapsed = true;\n private countBadge!: HTMLElement;\n private expandBadge!: HTMLElement;\n private innerEl!: HTMLElement;\n private copyBtn!: HTMLElement;\n private clearBtn!: HTMLElement;\n private toggleBtn!: HTMLElement;\n private settingsOpen = false;\n\n onCopy?: () => void;\n onClear?: () => void;\n onSettings?: () => void;\n onCollapse?: () => void;\n onExpand?: () => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-toolbar';\n this.el.setAttribute('data-refiner-toolbar', '');\n this.el.setAttribute('data-collapsed', 'true');\n this.render();\n root.appendChild(this.el);\n\n // Expand on first load after a short delay\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.collapsed = false;\n this.el.setAttribute('data-collapsed', 'false');\n this.updateBadgeVisibility();\n });\n });\n }\n\n private render(): void {\n const pill = document.createElement('div');\n pill.className = 'toolbar-pill';\n\n // Inner (collapsible buttons)\n this.innerEl = document.createElement('div');\n this.innerEl.className = 'toolbar-inner';\n\n // Note count\n this.countBadge = document.createElement('span');\n this.countBadge.className = 'toolbar-count';\n this.countBadge.textContent = '0';\n this.innerEl.appendChild(this.createBtn(\n this.countBadge,\n 'Annotations',\n null,\n ));\n\n // Copy\n const copyIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>`;\n const checkIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n this.copyBtn = this.createBtn(\n copyIcon,\n 'Copy annotations',\n () => {\n if (this.copyBtn.classList.contains('disabled')) return;\n this.onCopy?.();\n this.copyBtn.querySelector('.toolbar-icon')!.innerHTML = checkIcon;\n setTimeout(() => {\n this.copyBtn.querySelector('.toolbar-icon')!.innerHTML = copyIcon;\n }, 1500);\n },\n );\n this.copyBtn.classList.add('disabled');\n this.innerEl.appendChild(this.copyBtn);\n\n // Clear all\n this.clearBtn = this.createBtn(\n `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/></svg>`,\n 'Clear all',\n () => {\n if (this.clearBtn.classList.contains('disabled')) return;\n this.onClear?.();\n },\n );\n this.clearBtn.classList.add('disabled');\n this.innerEl.appendChild(this.clearBtn);\n\n // Settings\n this.innerEl.appendChild(this.createBtn(\n `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><circle cx=\"12\" cy=\"12\" r=\"3\"/><path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.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-4 0v-.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-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.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 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.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 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n 'Settings',\n () => this.onSettings?.(),\n ));\n\n // Divider\n const divider = document.createElement('div');\n divider.className = 'toolbar-divider';\n this.innerEl.appendChild(divider);\n\n pill.appendChild(this.innerEl);\n\n // Toggle button (always visible — pen when collapsed, X when expanded)\n const penIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\"/></svg>`;\n const xIcon = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\n this.toggleBtn = this.createBtn(\n penIcon,\n '',\n () => this.toggleCollapse(),\n );\n this.toggleBtn.classList.add('toolbar-toggle-btn');\n pill.appendChild(this.toggleBtn);\n\n // Badge for collapsed state\n this.expandBadge = document.createElement('span');\n this.expandBadge.className = 'toolbar-expand-badge hidden';\n this.expandBadge.textContent = '0';\n pill.appendChild(this.expandBadge);\n\n this.el.appendChild(pill);\n\n // Update toggle icon on transition end\n this.el.addEventListener('transitionend', () => {\n const icon = this.toggleBtn.querySelector('.toolbar-icon')!;\n icon.innerHTML = this.collapsed ? penIcon : xIcon;\n });\n }\n\n private createBtn(content: string | HTMLElement, tooltip: string, onClick: (() => void) | null): HTMLElement {\n const btn = document.createElement('button');\n btn.className = 'toolbar-btn';\n\n const iconWrap = document.createElement('span');\n iconWrap.className = 'toolbar-icon';\n if (typeof content === 'string') {\n iconWrap.innerHTML = content;\n } else {\n iconWrap.appendChild(content);\n }\n btn.appendChild(iconWrap);\n\n if (tooltip) {\n const tip = document.createElement('span');\n tip.className = 'toolbar-tooltip';\n tip.textContent = tooltip;\n btn.appendChild(tip);\n }\n\n if (onClick) {\n btn.addEventListener('click', onClick);\n }\n\n return btn;\n }\n\n private toggleCollapse(): void {\n this.collapsed = !this.collapsed;\n this.el.setAttribute('data-collapsed', String(this.collapsed));\n this.updateBadgeVisibility();\n if (this.collapsed) {\n this.onCollapse?.();\n } else {\n this.onExpand?.();\n }\n }\n\n setSettingsOpen(open: boolean): void {\n this.settingsOpen = open;\n this.el.classList.toggle('tooltips-hidden', open);\n }\n\n updateCount(count: number): void {\n this.countBadge.textContent = String(count);\n this.expandBadge.textContent = String(count);\n this.updateBadgeVisibility(count);\n\n const empty = count === 0;\n this.copyBtn.classList.toggle('disabled', empty);\n this.clearBtn.classList.toggle('disabled', empty);\n }\n\n private updateBadgeVisibility(count?: number): void {\n const c = count ?? parseInt(this.expandBadge.textContent || '0', 10);\n this.expandBadge.classList.toggle('hidden', c === 0 || !this.collapsed);\n }\n}\n","export class Overlay {\n readonly el: HTMLElement;\n private highlight: HTMLElement;\n private enabled = true;\n private blocking = true;\n private currentTarget: Element | null = null;\n private highlightColor = '#7C3AED';\n\n onClick?: (target: Element, rect: DOMRect) => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-overlay';\n this.el.setAttribute('data-blocking', 'true');\n\n this.highlight = document.createElement('div');\n this.highlight.className = 'refiner-highlight';\n this.highlight.style.display = 'none';\n\n root.appendChild(this.highlight);\n root.appendChild(this.el);\n\n this.el.addEventListener('mousemove', this.handleMouseMove);\n this.el.addEventListener('click', this.handleClick);\n this.el.addEventListener('mouseleave', () => this.hideHighlight());\n\n document.addEventListener('keydown', this.handleKeyBlock, true);\n }\n\n private isOverOwnUI(x: number, y: number): boolean {\n const shadowEl = this.root.elementFromPoint(x, y);\n if (!shadowEl) return false;\n if (shadowEl === this.el || shadowEl === this.highlight) return false;\n return true;\n }\n\n private handleMouseMove = (e: MouseEvent): void => {\n if (!this.enabled) return;\n if (this.isOverOwnUI(e.clientX, e.clientY)) {\n this.hideHighlight();\n return;\n }\n\n const target = this.getElementAt(e.clientX, e.clientY);\n if (target && target !== this.currentTarget) {\n this.currentTarget = target;\n this.showHighlight(target);\n }\n };\n\n private handleClick = (e: MouseEvent): void => {\n if (!this.enabled) return;\n if (this.isOverOwnUI(e.clientX, e.clientY)) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n const target = this.getElementAt(e.clientX, e.clientY);\n if (target) {\n const rect = target.getBoundingClientRect();\n this.onClick?.(target, rect);\n }\n };\n\n private handleKeyBlock = (e: KeyboardEvent): void => {\n if (!this.enabled || !this.blocking) return;\n // Allow keys when focus is inside refiner's own UI (e.g. annotation dialog textarea)\n const target = e.target as Element;\n if (target && (target === this.root.host || this.root.host.contains(target))) return;\n\n e.preventDefault();\n e.stopPropagation();\n };\n\n private getElementAt(x: number, y: number): Element | null {\n this.el.style.pointerEvents = 'none';\n this.highlight.style.pointerEvents = 'none';\n\n const el = document.elementFromPoint(x, y);\n\n this.el.style.pointerEvents = '';\n this.highlight.style.pointerEvents = '';\n\n if (el && el === this.root.host) return null;\n return el;\n }\n\n private showHighlight(target: Element): void {\n const rect = target.getBoundingClientRect();\n this.highlight.style.display = 'block';\n this.highlight.style.top = `${rect.top - 2}px`;\n this.highlight.style.left = `${rect.left - 2}px`;\n this.highlight.style.width = `${rect.width + 4}px`;\n this.highlight.style.height = `${rect.height + 4}px`;\n this.highlight.style.borderColor = this.highlightColor;\n }\n\n private hideHighlight(): void {\n this.highlight.style.display = 'none';\n this.currentTarget = null;\n }\n\n setHighlightColor(color: string): void {\n this.highlightColor = color;\n }\n\n setBlocking(blocking: boolean): void {\n this.blocking = blocking;\n this.el.setAttribute('data-blocking', String(blocking));\n if (!blocking) {\n this.hideHighlight();\n }\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n this.el.classList.toggle('hidden', !enabled);\n if (!enabled) this.hideHighlight();\n }\n}\n","export class AnnotationDialog {\n readonly el: HTMLElement;\n private textarea!: HTMLTextAreaElement;\n private addBtn!: HTMLButtonElement;\n\n onSubmit?: (text: string) => void;\n onCancel?: () => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'refiner-dialog hidden';\n this.render();\n root.appendChild(this.el);\n }\n\n private render(): void {\n // Header\n const header = document.createElement('div');\n header.className = 'dialog-header';\n const label = document.createElement('span');\n label.textContent = 'What should change?';\n header.appendChild(label);\n this.el.appendChild(header);\n\n // Textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'dialog-textarea';\n this.textarea.placeholder = 'Describe the issue or improvement...';\n this.textarea.addEventListener('input', () => {\n this.addBtn.disabled = this.textarea.value.trim().length === 0;\n });\n this.textarea.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && this.textarea.value.trim()) {\n this.submit();\n }\n if (e.key === 'Escape') {\n this.hide();\n this.onCancel?.();\n }\n });\n this.el.appendChild(this.textarea);\n\n // Actions\n const actions = document.createElement('div');\n actions.className = 'dialog-actions';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'dialog-btn dialog-btn-cancel';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n this.hide();\n this.onCancel?.();\n });\n\n this.addBtn = document.createElement('button');\n this.addBtn.className = 'dialog-btn dialog-btn-add';\n this.addBtn.textContent = 'Add';\n this.addBtn.disabled = true;\n this.addBtn.addEventListener('click', () => this.submit());\n\n actions.appendChild(cancelBtn);\n actions.appendChild(this.addBtn);\n this.el.appendChild(actions);\n }\n\n private submit(): void {\n const text = this.textarea.value.trim();\n if (text) {\n this.onSubmit?.(text);\n this.hide();\n }\n }\n\n show(x: number, y: number): void {\n // Position: prefer below-right of click, but keep on screen\n const dialogW = 320;\n const dialogH = 200;\n let left = x + 12;\n let top = y + 12;\n\n if (left + dialogW > window.innerWidth - 16) {\n left = x - dialogW - 12;\n }\n if (top + dialogH > window.innerHeight - 16) {\n top = y - dialogH - 12;\n }\n\n this.el.style.left = `${Math.max(16, left)}px`;\n this.el.style.top = `${Math.max(16, top)}px`;\n this.el.classList.remove('hidden');\n\n this.textarea.value = '';\n this.addBtn.disabled = true;\n requestAnimationFrame(() => this.textarea.focus());\n }\n\n hide(): void {\n this.el.classList.add('hidden');\n this.textarea.value = '';\n }\n\n isVisible(): boolean {\n return !this.el.classList.contains('hidden');\n }\n}\n","import { Annotation } from './types';\nimport { AnnotationStore } from './annotation-store';\n\ninterface MarkerElement {\n el: HTMLElement;\n annotation: Annotation;\n}\n\nexport class AnnotationMarkers {\n private markers: Map<string, MarkerElement> = new Map();\n private container: HTMLElement;\n private rafId: number | null = null;\n private color = '#7C3AED';\n\n constructor(private root: ShadowRoot, private store: AnnotationStore) {\n this.container = document.createElement('div');\n this.container.className = 'refiner-markers';\n root.appendChild(this.container);\n\n store.on('add', (annotation) => this.addMarker(annotation));\n store.on('resolve', (annotation) => this.updateMarker(annotation));\n store.on('remove', (annotation) => this.removeMarker(annotation.id));\n\n const reposition = () => this.repositionAll();\n window.addEventListener('scroll', reposition, { passive: true });\n window.addEventListener('resize', reposition, { passive: true });\n }\n\n private addMarker(annotation: Annotation): void {\n const el = document.createElement('div');\n el.className = 'refiner-marker';\n el.setAttribute('data-annotation-marker', annotation.id);\n el.setAttribute('data-resolved', String(annotation.resolved));\n el.style.background = this.color;\n\n const index = this.markers.size + 1;\n el.textContent = String(index);\n\n // Tooltip\n const tooltip = document.createElement('div');\n tooltip.className = 'marker-tooltip';\n\n const tooltipText = document.createElement('div');\n tooltipText.textContent = annotation.text;\n tooltip.appendChild(tooltipText);\n\n const tooltipActions = document.createElement('div');\n tooltipActions.className = 'marker-tooltip-actions';\n\n const resolveBtn = document.createElement('button');\n resolveBtn.className = 'marker-tooltip-btn resolve';\n resolveBtn.textContent = 'Resolve';\n resolveBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.store.resolve(annotation.id);\n });\n\n const deleteBtn = document.createElement('button');\n deleteBtn.className = 'marker-tooltip-btn delete';\n deleteBtn.textContent = 'Delete';\n deleteBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.store.remove(annotation.id);\n });\n\n tooltipActions.appendChild(resolveBtn);\n tooltipActions.appendChild(deleteBtn);\n tooltip.appendChild(tooltipActions);\n el.appendChild(tooltip);\n\n this.positionMarker(el, annotation);\n this.container.appendChild(el);\n this.markers.set(annotation.id, { el, annotation });\n }\n\n private updateMarker(annotation: Annotation): void {\n const marker = this.markers.get(annotation.id);\n if (marker) {\n marker.annotation = annotation;\n marker.el.setAttribute('data-resolved', String(annotation.resolved));\n }\n }\n\n private removeMarker(id: string): void {\n const marker = this.markers.get(id);\n if (marker) {\n marker.el.remove();\n this.markers.delete(id);\n this.renumber();\n }\n }\n\n private renumber(): void {\n let i = 1;\n for (const [, marker] of this.markers) {\n const firstText = marker.el.childNodes[0];\n if (firstText && firstText.nodeType === Node.TEXT_NODE) {\n firstText.textContent = String(i);\n }\n i++;\n }\n }\n\n private positionMarker(el: HTMLElement, annotation: Annotation): void {\n const target = this.queryTarget(annotation.targetSelector);\n if (target) {\n const rect = target.getBoundingClientRect();\n el.style.top = `${rect.top - 8}px`;\n el.style.left = `${rect.right - 8}px`;\n } else {\n el.style.top = `${annotation.targetRect.y - 8}px`;\n el.style.left = `${annotation.targetRect.x + annotation.targetRect.width - 8}px`;\n }\n }\n\n private queryTarget(selector: string): Element | null {\n try {\n return document.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n setColor(color: string): void {\n this.color = color;\n for (const [, marker] of this.markers) {\n marker.el.style.background = color;\n }\n }\n\n clearAll(): void {\n for (const [id] of this.markers) {\n this.removeMarker(id);\n }\n }\n\n private repositionAll(): void {\n if (this.rafId !== null) return;\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n for (const [, marker] of this.markers) {\n this.positionMarker(marker.el, marker.annotation);\n }\n });\n }\n}\n","const MARKER_COLORS = [\n { id: 'purple', color: '#7C3AED' },\n { id: 'blue', color: '#2563EB' },\n { id: 'green', color: '#059669' },\n { id: 'yellow', color: '#D97706' },\n { id: 'orange', color: '#EA580C' },\n { id: 'red', color: '#DC2626' },\n { id: 'pink', color: '#DB2777' },\n];\n\nexport interface Settings {\n clearOnCopy: boolean;\n blockInteractions: boolean;\n markerColor: string;\n}\n\nexport class SettingsPanel {\n readonly el: HTMLElement;\n private visible = false;\n private mcpDot!: HTMLElement;\n private mcpLabel!: HTMLElement;\n private settings: Settings = {\n clearOnCopy: false,\n blockInteractions: true,\n markerColor: '#7C3AED',\n };\n\n onChange?: (settings: Settings) => void;\n\n constructor(private root: ShadowRoot) {\n this.el = document.createElement('div');\n this.el.className = 'settings-panel hidden';\n this.render();\n root.appendChild(this.el);\n }\n\n private render(): void {\n // Header\n const header = document.createElement('div');\n header.className = 'settings-header';\n const title = document.createElement('span');\n title.className = 'settings-title';\n title.textContent = 'reFiner';\n const version = document.createElement('span');\n version.className = 'settings-version';\n version.textContent = 'v0.1.0';\n header.appendChild(title);\n header.appendChild(version);\n this.el.appendChild(header);\n\n this.el.appendChild(this.createDivider());\n\n // Marker color\n const colorSection = document.createElement('div');\n colorSection.className = 'settings-section';\n const colorLabel = document.createElement('span');\n colorLabel.className = 'settings-label';\n colorLabel.textContent = 'Marker Colour';\n colorSection.appendChild(colorLabel);\n\n const colorRow = document.createElement('div');\n colorRow.className = 'settings-color-row';\n for (const mc of MARKER_COLORS) {\n const swatch = document.createElement('button');\n swatch.className = 'settings-swatch';\n swatch.style.background = mc.color;\n swatch.setAttribute('data-color', mc.color);\n if (mc.color === this.settings.markerColor) {\n swatch.classList.add('selected');\n }\n swatch.addEventListener('click', () => {\n colorRow.querySelectorAll('.settings-swatch').forEach((s) =>\n s.classList.remove('selected')\n );\n swatch.classList.add('selected');\n this.settings.markerColor = mc.color;\n this.emitChange();\n });\n colorRow.appendChild(swatch);\n }\n colorSection.appendChild(colorRow);\n this.el.appendChild(colorSection);\n\n this.el.appendChild(this.createDivider());\n\n // Clear on copy\n this.el.appendChild(this.createCheckbox(\n 'Clear on copy',\n this.settings.clearOnCopy,\n (checked) => {\n this.settings.clearOnCopy = checked;\n this.emitChange();\n },\n ));\n\n // Block page interactions\n this.el.appendChild(this.createCheckbox(\n 'Block page interactions',\n this.settings.blockInteractions,\n (checked) => {\n this.settings.blockInteractions = checked;\n this.emitChange();\n },\n ));\n\n this.el.appendChild(this.createDivider());\n\n // MCP status\n const mcpRow = document.createElement('div');\n mcpRow.className = 'settings-mcp-row';\n\n this.mcpDot = document.createElement('span');\n this.mcpDot.className = 'settings-mcp-dot disconnected';\n\n this.mcpLabel = document.createElement('span');\n this.mcpLabel.className = 'settings-check-label';\n this.mcpLabel.textContent = 'MCP Disconnected';\n\n mcpRow.appendChild(this.mcpDot);\n mcpRow.appendChild(this.mcpLabel);\n this.el.appendChild(mcpRow);\n }\n\n private createCheckbox(label: string, initial: boolean, onChange: (v: boolean) => void): HTMLElement {\n const row = document.createElement('label');\n row.className = 'settings-check-row';\n\n const checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.className = 'settings-checkbox';\n checkbox.checked = initial;\n checkbox.addEventListener('change', () => onChange(checkbox.checked));\n\n const text = document.createElement('span');\n text.className = 'settings-check-label';\n text.textContent = label;\n\n row.appendChild(checkbox);\n row.appendChild(text);\n return row;\n }\n\n private createDivider(): HTMLElement {\n const div = document.createElement('div');\n div.className = 'settings-divider';\n return div;\n }\n\n private emitChange(): void {\n this.onChange?.({ ...this.settings });\n }\n\n toggle(): void {\n this.visible = !this.visible;\n this.el.classList.toggle('hidden', !this.visible);\n }\n\n hide(): void {\n this.visible = false;\n this.el.classList.add('hidden');\n }\n\n isVisible(): boolean {\n return this.visible;\n }\n\n setMcpStatus(connected: boolean): void {\n this.mcpDot.className = `settings-mcp-dot ${connected ? 'connected' : 'disconnected'}`;\n this.mcpLabel.textContent = connected ? 'MCP Connected' : 'MCP Disconnected';\n }\n\n getSettings(): Settings {\n return { ...this.settings };\n }\n}\n","import { AnnotationStore } from './annotation-store';\nimport { Annotation } from './types';\n\nexport class McpBridge {\n private baseUrl: string;\n private sessionId: string | null = null;\n private connected = false;\n private retryTimer: ReturnType<typeof setInterval> | null = null;\n\n onChange?: (connected: boolean) => void;\n\n constructor(\n private store: AnnotationStore,\n port: number = 4848,\n ) {\n this.baseUrl = `http://localhost:${port}`;\n this.discover();\n\n // Wire up store events\n this.store.on('add', (annotation) => this.postAnnotation(annotation));\n this.store.on('resolve', (annotation) => this.patchAnnotation(annotation));\n }\n\n private async discover(): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/health`);\n const data = await res.json();\n if (data && typeof data === 'object' && 'status' in data && data.status === 'ok') {\n this.connected = true;\n this.onChange?.(true);\n await this.createSession();\n this.stopRetry();\n }\n } catch {\n this.connected = false;\n this.onChange?.(false);\n this.startRetry();\n }\n }\n\n private startRetry(): void {\n if (this.retryTimer) return;\n this.retryTimer = setInterval(() => this.discover(), 5000);\n }\n\n private stopRetry(): void {\n if (this.retryTimer) {\n clearInterval(this.retryTimer);\n this.retryTimer = null;\n }\n }\n\n private async createSession(): Promise<void> {\n try {\n const res = await fetch(`${this.baseUrl}/sessions`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n url: window.location.href,\n title: document.title || window.location.pathname,\n }),\n });\n const session = await res.json();\n this.sessionId = session.id;\n } catch {\n // Session creation failed — annotations won't sync but local still works\n }\n }\n\n private async postAnnotation(annotation: Annotation): Promise<void> {\n if (!this.connected || !this.sessionId) return;\n\n try {\n await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n targetSelector: annotation.targetSelector,\n targetRect: annotation.targetRect,\n text: annotation.text,\n }),\n });\n } catch {\n // Silently fail — local annotation still exists\n }\n }\n\n private async patchAnnotation(annotation: Annotation): Promise<void> {\n if (!this.connected) return;\n\n try {\n await fetch(`${this.baseUrl}/annotations/${annotation.id}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n resolved: true,\n summary: 'Resolved from browser',\n }),\n });\n } catch {\n // Silently fail\n }\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n destroy(): void {\n this.stopRetry();\n }\n}\n","import { RefinerOptions } from './types';\nimport { STYLES } from './styles';\nimport { AnnotationStore } from './annotation-store';\nimport { Toolbar } from './toolbar';\nimport { Overlay } from './overlay';\nimport { AnnotationDialog } from './annotation-dialog';\nimport { AnnotationMarkers } from './annotation-marker';\nimport { SettingsPanel } from './settings';\nimport { generateSelector } from './selector';\nimport { McpBridge } from './mcp-bridge';\n\nexport class Refiner {\n private host: HTMLDivElement;\n private shadow: ShadowRoot;\n private store: AnnotationStore;\n private toolbar: Toolbar;\n private overlay: Overlay;\n private dialog: AnnotationDialog;\n private markers: AnnotationMarkers;\n private settings: SettingsPanel;\n private mcpBridge: McpBridge | null = null;\n private currentTarget: Element | null = null;\n private currentRect: DOMRect | null = null;\n private clearOnCopy = false;\n\n constructor(options: RefinerOptions = {}) {\n // Create shadow host\n this.host = document.createElement('div');\n this.host.id = 'refiner-host';\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = STYLES;\n this.shadow.appendChild(style);\n\n // Initialize components\n this.store = new AnnotationStore();\n this.toolbar = new Toolbar(this.shadow);\n this.settings = new SettingsPanel(this.shadow);\n this.overlay = new Overlay(this.shadow);\n this.dialog = new AnnotationDialog(this.shadow);\n this.markers = new AnnotationMarkers(this.shadow, this.store);\n\n // Wire up toolbar\n this.toolbar.onCopy = () => this.copyAnnotations();\n this.toolbar.onClear = () => this.clearAnnotations();\n this.toolbar.onSettings = () => {\n this.settings.toggle();\n this.toolbar.setSettingsOpen(this.settings.isVisible());\n };\n\n this.toolbar.onCollapse = () => {\n this.settings.hide();\n this.toolbar.setSettingsOpen(false);\n this.overlay.setEnabled(false);\n };\n\n this.toolbar.onExpand = () => {\n this.overlay.setEnabled(true);\n };\n\n // Wire up settings\n this.settings.onChange = (s) => {\n this.clearOnCopy = s.clearOnCopy;\n this.overlay.setBlocking(s.blockInteractions);\n this.markers.setColor(s.markerColor);\n this.overlay.setHighlightColor(s.markerColor);\n };\n\n // Wire up overlay click\n this.overlay.onClick = (target, rect) => {\n if (this.settings.isVisible()) {\n this.settings.hide();\n return;\n }\n if (this.dialog.isVisible()) {\n this.dialog.hide();\n return;\n }\n this.currentTarget = target;\n this.currentRect = rect;\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n this.dialog.show(centerX, centerY);\n };\n\n // Wire up dialog submit\n this.dialog.onSubmit = (text) => {\n if (this.currentTarget && this.currentRect) {\n const selector = generateSelector(this.currentTarget);\n this.store.add(selector, this.currentRect, text);\n this.toolbar.updateCount(this.store.getCount());\n }\n this.currentTarget = null;\n this.currentRect = null;\n };\n\n this.dialog.onCancel = () => {\n this.currentTarget = null;\n this.currentRect = null;\n };\n\n // Update count on resolve/remove\n this.store.on('resolve', () => this.toolbar.updateCount(this.store.getCount()));\n this.store.on('remove', () => this.toolbar.updateCount(this.store.getCount()));\n\n // MCP bridge (auto-discover by default)\n if (options.mcpEnabled !== false) {\n this.mcpBridge = new McpBridge(this.store, options.mcpPort);\n this.mcpBridge.onChange = (connected) => {\n this.settings.setMcpStatus(connected);\n };\n }\n\n // Mount\n document.body.appendChild(this.host);\n\n if (options.enabled === false) {\n this.disable();\n }\n }\n\n enable(): void {\n this.host.style.display = '';\n this.overlay.setEnabled(true);\n }\n\n disable(): void {\n this.host.style.display = 'none';\n this.overlay.setEnabled(false);\n }\n\n destroy(): void {\n this.mcpBridge?.destroy();\n this.host.remove();\n }\n\n getAnnotations() {\n return this.store.getAll();\n }\n\n getAnnotationCount(): number {\n return this.store.getCount();\n }\n\n formatForAgent(): string {\n const annotations = this.store.getAll();\n if (annotations.length === 0) return 'No annotations.';\n\n const pageTitle = document.title || window.location.pathname;\n const pathname = window.location.pathname;\n const filename = pathname.substring(pathname.lastIndexOf('/') + 1) || 'index.html';\n const lines: string[] = [\n `# Design Annotations — ${pageTitle}`,\n `**File:** \\`${filename}\\``,\n '',\n ];\n\n for (let i = 0; i < annotations.length; i++) {\n const a = annotations[i];\n const status = a.resolved ? ' (resolved)' : '';\n lines.push(`## ${i + 1}.${status}`);\n lines.push(`**Element:** \\`${a.targetSelector}\\``);\n lines.push(`**Issue:** ${a.text}`);\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n clearAnnotations(): void {\n const all = this.store.getAll();\n for (const a of all) {\n this.store.remove(a.id);\n }\n this.toolbar.updateCount(0);\n }\n\n copyAnnotations(): void {\n const text = this.formatForAgent();\n navigator.clipboard.writeText(text);\n\n if (this.clearOnCopy) {\n this.clearAnnotations();\n }\n }\n}\n","export const STYLES = `\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed=\"true\"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed=\"true\"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: '';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: '';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking=\"true\"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking=\"false\"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved=\"true\"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n`;\n","/**\n * Generate a stable CSS selector for a DOM element.\n * Priority: #id > tag.class > nth-child path\n */\nexport function generateSelector(el: Element): string {\n if (el.id) {\n return `#${CSS.escape(el.id)}`;\n }\n\n // Try tag + distinctive class\n if (el.classList.length > 0) {\n const tag = el.tagName.toLowerCase();\n const classSelector = `${tag}.${Array.from(el.classList).map(CSS.escape).join('.')}`;\n if (document.querySelectorAll(classSelector).length === 1) {\n return classSelector;\n }\n }\n\n // Build nth-child path\n const parts: string[] = [];\n let current: Element | null = el;\n\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n parts.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c: Element) => c.tagName === current!.tagName\n );\n if (siblings.length === 1) {\n parts.unshift(tag);\n } else {\n const index = siblings.indexOf(current) + 1;\n parts.unshift(`${tag}:nth-child(${index})`);\n }\n } else {\n parts.unshift(tag);\n }\n\n current = parent;\n }\n\n return parts.join(' > ');\n}\n","import { Refiner } from './refiner';\nimport type { Annotation, RefinerOptions } from './types';\n\nexport { Refiner };\nexport type { Annotation, RefinerOptions };\n\n// Auto-initialize when loaded via script tag\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n const init = () => {\n // Skip if already initialized (e.g. bookmarklet + script tag both present)\n if ((window as any).__refiner) return;\n\n // Read config from script tag data attributes\n const script = document.currentScript as HTMLScriptElement | null;\n const position = (script?.dataset.refinerPosition as 'left' | 'right') ?? 'right';\n const enabled = script?.dataset.refinerEnabled !== 'false';\n const mcpPort = script?.dataset.refinerMcpPort ? parseInt(script.dataset.refinerMcpPort, 10) : undefined;\n const mcpEnabled = script?.dataset.refinerMcpEnabled !== 'false';\n\n const refiner = new Refiner({ position, enabled, mcpPort, mcpEnabled });\n (window as any).__refiner = refiner;\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', init);\n } else {\n init();\n }\n}\n"],"names":["AnnotationStore","constructor","this","annotations","Map","listeners","add","targetSelector","targetRect","text","annotation","id","crypto","randomUUID","x","y","width","height","timestamp","Date","now","resolved","set","emit","resolve","get","remove","delete","getAll","Array","from","values","getPending","filter","a","getCount","size","exportJSON","JSON","stringify","on","event","listener","has","Set","off","forEach","fn","Toolbar","root","collapsed","settingsOpen","el","document","createElement","className","setAttribute","render","appendChild","requestAnimationFrame","updateBadgeVisibility","pill","innerEl","countBadge","textContent","createBtn","copyIcon","copyBtn","classList","contains","onCopy","querySelector","innerHTML","setTimeout","clearBtn","onClear","onSettings","divider","penIcon","toggleBtn","toggleCollapse","expandBadge","addEventListener","content","tooltip","onClick","btn","iconWrap","tip","String","onCollapse","onExpand","setSettingsOpen","open","toggle","updateCount","count","empty","c","parseInt","Overlay","enabled","blocking","currentTarget","highlightColor","handleMouseMove","e","isOverOwnUI","clientX","clientY","hideHighlight","target","getElementAt","showHighlight","handleClick","preventDefault","stopPropagation","rect","getBoundingClientRect","handleKeyBlock","host","highlight","style","display","shadowEl","elementFromPoint","pointerEvents","top","left","borderColor","setHighlightColor","color","setBlocking","setEnabled","AnnotationDialog","header","label","textarea","placeholder","addBtn","disabled","value","trim","length","key","metaKey","ctrlKey","submit","hide","onCancel","actions","cancelBtn","onSubmit","show","window","innerWidth","innerHeight","Math","max","focus","isVisible","AnnotationMarkers","store","markers","rafId","container","addMarker","updateMarker","removeMarker","reposition","repositionAll","passive","background","index","tooltipText","tooltipActions","resolveBtn","deleteBtn","positionMarker","marker","renumber","i","firstText","childNodes","nodeType","Node","TEXT_NODE","queryTarget","right","selector","setColor","clearAll","MARKER_COLORS","SettingsPanel","visible","settings","clearOnCopy","blockInteractions","markerColor","title","version","createDivider","colorSection","colorLabel","colorRow","mc","swatch","querySelectorAll","s","emitChange","createCheckbox","checked","mcpRow","mcpDot","mcpLabel","initial","onChange","row","checkbox","type","div","setMcpStatus","connected","getSettings","McpBridge","port","sessionId","retryTimer","baseUrl","discover","postAnnotation","patchAnnotation","res","fetch","data","json","status","createSession","stopRetry","startRetry","setInterval","clearInterval","method","headers","body","url","location","href","pathname","session","summary","isConnected","destroy","Refiner","options","mcpBridge","currentRect","shadow","attachShadow","mode","toolbar","overlay","dialog","copyAnnotations","clearAnnotations","centerX","centerY","CSS","escape","classSelector","tagName","toLowerCase","map","join","parts","current","documentElement","tag","parent","parentElement","unshift","siblings","children","indexOf","generateSelector","mcpEnabled","mcpPort","disable","enable","getAnnotations","getAnnotationCount","formatForAgent","pageTitle","lines","substring","lastIndexOf","push","all","navigator","clipboard","writeText","init","__refiner","script","currentScript","position","dataset","refinerPosition","refinerEnabled","refinerMcpPort","undefined","refinerMcpEnabled","refiner","readyState"],"mappings":"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"}
package/dist/refiner.mjs CHANGED
@@ -1,2 +1,2 @@
1
- class t{constructor(){this.annotations=new Map,this.listeners=new Map}add(t,e,n){const i={id:crypto.randomUUID(),targetSelector:t,targetRect:{x:e.x,y:e.y,width:e.width,height:e.height},text:n,timestamp:Date.now(),resolved:!1};return this.annotations.set(i.id,i),this.emit("add",i),i}resolve(t){const e=this.annotations.get(t);e&&(e.resolved=!0,this.emit("resolve",e))}remove(t){const e=this.annotations.get(t);e&&(this.annotations.delete(t),this.emit("remove",e))}get(t){return this.annotations.get(t)}getAll(){return Array.from(this.annotations.values())}getPending(){return this.getAll().filter(t=>!t.resolved)}getCount(){return this.annotations.size}exportJSON(){return JSON.stringify(this.getAll(),null,2)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){this.listeners.get(t)?.delete(e)}emit(t,e){this.listeners.get(t)?.forEach(t=>t(e))}}class e{constructor(t){this.root=t,this.collapsed=!0,this.settingsOpen=!1,this.el=document.createElement("div"),this.el.className="refiner-toolbar",this.el.setAttribute("data-refiner-toolbar",""),this.el.setAttribute("data-collapsed","true"),this.render(),t.appendChild(this.el),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.collapsed=!1,this.el.setAttribute("data-collapsed","false"),this.updateBadgeVisibility()})})}render(){const t=document.createElement("div");t.className="toolbar-pill",this.innerEl=document.createElement("div"),this.innerEl.className="toolbar-inner",this.countBadge=document.createElement("span"),this.countBadge.className="toolbar-count",this.countBadge.textContent="0",this.innerEl.appendChild(this.createBtn(this.countBadge,"Annotations",null));const e='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';this.copyBtn=this.createBtn(e,"Copy annotations",()=>{this.copyBtn.classList.contains("disabled")||(this.onCopy?.(),this.copyBtn.querySelector(".toolbar-icon").innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{this.copyBtn.querySelector(".toolbar-icon").innerHTML=e},1500))}),this.copyBtn.classList.add("disabled"),this.innerEl.appendChild(this.copyBtn),this.clearBtn=this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',"Clear all",()=>{this.clearBtn.classList.contains("disabled")||this.onClear?.()}),this.clearBtn.classList.add("disabled"),this.innerEl.appendChild(this.clearBtn),this.innerEl.appendChild(this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.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-4 0v-.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-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.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 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.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 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',"Settings",()=>this.onSettings?.()));const n=document.createElement("div");n.className="toolbar-divider",this.innerEl.appendChild(n),t.appendChild(this.innerEl);const i='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>';this.toggleBtn=this.createBtn(i,"",()=>this.toggleCollapse()),this.toggleBtn.classList.add("toolbar-toggle-btn"),t.appendChild(this.toggleBtn),this.expandBadge=document.createElement("span"),this.expandBadge.className="toolbar-expand-badge hidden",this.expandBadge.textContent="0",t.appendChild(this.expandBadge),this.el.appendChild(t),this.el.addEventListener("transitionend",()=>{this.toggleBtn.querySelector(".toolbar-icon").innerHTML=this.collapsed?i:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'})}createBtn(t,e,n){const i=document.createElement("button");i.className="toolbar-btn";const s=document.createElement("span");if(s.className="toolbar-icon","string"==typeof t?s.innerHTML=t:s.appendChild(t),i.appendChild(s),e){const t=document.createElement("span");t.className="toolbar-tooltip",t.textContent=e,i.appendChild(t)}return n&&i.addEventListener("click",n),i}toggleCollapse(){this.collapsed=!this.collapsed,this.el.setAttribute("data-collapsed",String(this.collapsed)),this.updateBadgeVisibility(),this.collapsed?this.onCollapse?.():this.onExpand?.()}setSettingsOpen(t){this.settingsOpen=t,this.el.classList.toggle("tooltips-hidden",t)}updateCount(t){this.countBadge.textContent=String(t),this.expandBadge.textContent=String(t),this.updateBadgeVisibility(t);const e=0===t;this.copyBtn.classList.toggle("disabled",e),this.clearBtn.classList.toggle("disabled",e)}updateBadgeVisibility(t){const e=t??parseInt(this.expandBadge.textContent||"0",10);this.expandBadge.classList.toggle("hidden",0===e||!this.collapsed)}}class n{constructor(t){this.root=t,this.enabled=!0,this.blocking=!0,this.currentTarget=null,this.highlightColor="#7C3AED",this.handleMouseMove=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return void this.hideHighlight();const e=this.getElementAt(t.clientX,t.clientY);e&&e!==this.currentTarget&&(this.currentTarget=e,this.showHighlight(e))},this.handleClick=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return;t.preventDefault(),t.stopPropagation();const e=this.getElementAt(t.clientX,t.clientY);if(e){const t=e.getBoundingClientRect();this.onClick?.(e,t)}},this.handleKeyBlock=t=>{if(!this.enabled||!this.blocking)return;const e=t.target;e&&(e===this.root.host||this.root.host.contains(e))||(t.preventDefault(),t.stopPropagation())},this.el=document.createElement("div"),this.el.className="refiner-overlay",this.el.setAttribute("data-blocking","true"),this.highlight=document.createElement("div"),this.highlight.className="refiner-highlight",this.highlight.style.display="none",t.appendChild(this.highlight),t.appendChild(this.el),this.el.addEventListener("mousemove",this.handleMouseMove),this.el.addEventListener("click",this.handleClick),this.el.addEventListener("mouseleave",()=>this.hideHighlight()),document.addEventListener("keydown",this.handleKeyBlock,!0)}isOverOwnUI(t,e){const n=this.root.elementFromPoint(t,e);return!!n&&(n!==this.el&&n!==this.highlight)}getElementAt(t,e){this.el.style.pointerEvents="none",this.highlight.style.pointerEvents="none";const n=document.elementFromPoint(t,e);return this.el.style.pointerEvents="",this.highlight.style.pointerEvents="",n&&n===this.root.host?null:n}showHighlight(t){const e=t.getBoundingClientRect();this.highlight.style.display="block",this.highlight.style.top=e.top-2+"px",this.highlight.style.left=e.left-2+"px",this.highlight.style.width=`${e.width+4}px`,this.highlight.style.height=`${e.height+4}px`,this.highlight.style.borderColor=this.highlightColor}hideHighlight(){this.highlight.style.display="none",this.currentTarget=null}setHighlightColor(t){this.highlightColor=t}setBlocking(t){this.blocking=t,this.el.setAttribute("data-blocking",String(t)),t||this.hideHighlight()}setEnabled(t){this.enabled=t,this.el.classList.toggle("hidden",!t),t||this.hideHighlight()}}class i{constructor(t){this.root=t,this.el=document.createElement("div"),this.el.className="refiner-dialog hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="dialog-header";const e=document.createElement("span");e.textContent="What should change?",t.appendChild(e),this.el.appendChild(t),this.textarea=document.createElement("textarea"),this.textarea.className="dialog-textarea",this.textarea.placeholder="Describe the issue or improvement...",this.textarea.addEventListener("input",()=>{this.addBtn.disabled=0===this.textarea.value.trim().length}),this.textarea.addEventListener("keydown",t=>{"Enter"===t.key&&(t.metaKey||t.ctrlKey)&&this.textarea.value.trim()&&this.submit(),"Escape"===t.key&&(this.hide(),this.onCancel?.())}),this.el.appendChild(this.textarea);const n=document.createElement("div");n.className="dialog-actions";const i=document.createElement("button");i.className="dialog-btn dialog-btn-cancel",i.textContent="Cancel",i.addEventListener("click",()=>{this.hide(),this.onCancel?.()}),this.addBtn=document.createElement("button"),this.addBtn.className="dialog-btn dialog-btn-add",this.addBtn.textContent="Add",this.addBtn.disabled=!0,this.addBtn.addEventListener("click",()=>this.submit()),n.appendChild(i),n.appendChild(this.addBtn),this.el.appendChild(n)}submit(){const t=this.textarea.value.trim();t&&(this.onSubmit?.(t),this.hide())}show(t,e){let n=t+12,i=e+12;n+320>window.innerWidth-16&&(n=t-320-12),i+200>window.innerHeight-16&&(i=e-200-12),this.el.style.left=`${Math.max(16,n)}px`,this.el.style.top=`${Math.max(16,i)}px`,this.el.classList.remove("hidden"),this.textarea.value="",this.addBtn.disabled=!0,requestAnimationFrame(()=>this.textarea.focus())}hide(){this.el.classList.add("hidden"),this.textarea.value=""}isVisible(){return!this.el.classList.contains("hidden")}}class s{constructor(t,e){this.root=t,this.store=e,this.markers=new Map,this.rafId=null,this.color="#7C3AED",this.container=document.createElement("div"),this.container.className="refiner-markers",t.appendChild(this.container),e.on("add",t=>this.addMarker(t)),e.on("resolve",t=>this.updateMarker(t)),e.on("remove",t=>this.removeMarker(t.id));const n=()=>this.repositionAll();window.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",n,{passive:!0})}addMarker(t){const e=document.createElement("div");e.className="refiner-marker",e.setAttribute("data-annotation-marker",t.id),e.setAttribute("data-resolved",String(t.resolved)),e.style.background=this.color;const n=this.markers.size+1;e.textContent=String(n);const i=document.createElement("div");i.className="marker-tooltip";const s=document.createElement("div");s.textContent=t.text,i.appendChild(s);const o=document.createElement("div");o.className="marker-tooltip-actions";const a=document.createElement("button");a.className="marker-tooltip-btn resolve",a.textContent="Resolve",a.addEventListener("click",e=>{e.stopPropagation(),this.store.resolve(t.id)});const r=document.createElement("button");r.className="marker-tooltip-btn delete",r.textContent="Delete",r.addEventListener("click",e=>{e.stopPropagation(),this.store.remove(t.id)}),o.appendChild(a),o.appendChild(r),i.appendChild(o),e.appendChild(i),this.positionMarker(e,t),this.container.appendChild(e),this.markers.set(t.id,{el:e,annotation:t})}updateMarker(t){const e=this.markers.get(t.id);e&&(e.annotation=t,e.el.setAttribute("data-resolved",String(t.resolved)))}removeMarker(t){const e=this.markers.get(t);e&&(e.el.remove(),this.markers.delete(t),this.renumber())}renumber(){let t=1;for(const[,e]of this.markers){const n=e.el.childNodes[0];n&&n.nodeType===Node.TEXT_NODE&&(n.textContent=String(t)),t++}}positionMarker(t,e){const n=this.queryTarget(e.targetSelector);if(n){const e=n.getBoundingClientRect();t.style.top=e.top-8+"px",t.style.left=e.right-8+"px"}else t.style.top=e.targetRect.y-8+"px",t.style.left=e.targetRect.x+e.targetRect.width-8+"px"}queryTarget(t){try{return document.querySelector(t)}catch{return null}}setColor(t){this.color=t;for(const[,e]of this.markers)e.el.style.background=t}clearAll(){for(const[t]of this.markers)this.removeMarker(t)}repositionAll(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null;for(const[,t]of this.markers)this.positionMarker(t.el,t.annotation)}))}}const o=[{id:"purple",color:"#7C3AED"},{id:"blue",color:"#2563EB"},{id:"green",color:"#059669"},{id:"yellow",color:"#D97706"},{id:"orange",color:"#EA580C"},{id:"red",color:"#DC2626"},{id:"pink",color:"#DB2777"}];class a{constructor(t){this.root=t,this.visible=!1,this.settings={clearOnCopy:!1,blockInteractions:!0,markerColor:"#7C3AED"},this.el=document.createElement("div"),this.el.className="settings-panel hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="settings-header";const e=document.createElement("span");e.className="settings-title",e.textContent="reFiner";const n=document.createElement("span");n.className="settings-version",n.textContent="v0.1.0",t.appendChild(e),t.appendChild(n),this.el.appendChild(t),this.el.appendChild(this.createDivider());const i=document.createElement("div");i.className="settings-section";const s=document.createElement("span");s.className="settings-label",s.textContent="Marker Colour",i.appendChild(s);const a=document.createElement("div");a.className="settings-color-row";for(const t of o){const e=document.createElement("button");e.className="settings-swatch",e.style.background=t.color,e.setAttribute("data-color",t.color),t.color===this.settings.markerColor&&e.classList.add("selected"),e.addEventListener("click",()=>{a.querySelectorAll(".settings-swatch").forEach(t=>t.classList.remove("selected")),e.classList.add("selected"),this.settings.markerColor=t.color,this.emitChange()}),a.appendChild(e)}i.appendChild(a),this.el.appendChild(i),this.el.appendChild(this.createDivider()),this.el.appendChild(this.createCheckbox("Clear on copy",this.settings.clearOnCopy,t=>{this.settings.clearOnCopy=t,this.emitChange()})),this.el.appendChild(this.createCheckbox("Block page interactions",this.settings.blockInteractions,t=>{this.settings.blockInteractions=t,this.emitChange()})),this.el.appendChild(this.createDivider());const r=document.createElement("div");r.className="settings-mcp-row",this.mcpDot=document.createElement("span"),this.mcpDot.className="settings-mcp-dot disconnected",this.mcpLabel=document.createElement("span"),this.mcpLabel.className="settings-check-label",this.mcpLabel.textContent="MCP Disconnected",r.appendChild(this.mcpDot),r.appendChild(this.mcpLabel),this.el.appendChild(r)}createCheckbox(t,e,n){const i=document.createElement("label");i.className="settings-check-row";const s=document.createElement("input");s.type="checkbox",s.className="settings-checkbox",s.checked=e,s.addEventListener("change",()=>n(s.checked));const o=document.createElement("span");return o.className="settings-check-label",o.textContent=t,i.appendChild(s),i.appendChild(o),i}createDivider(){const t=document.createElement("div");return t.className="settings-divider",t}emitChange(){this.onChange?.({...this.settings})}toggle(){this.visible=!this.visible,this.el.classList.toggle("hidden",!this.visible)}hide(){this.visible=!1,this.el.classList.add("hidden")}isVisible(){return this.visible}setMcpStatus(t){this.mcpDot.className="settings-mcp-dot "+(t?"connected":"disconnected"),this.mcpLabel.textContent=t?"MCP Connected":"MCP Disconnected"}getSettings(){return{...this.settings}}}class r{constructor(t,e=4848){this.store=t,this.sessionId=null,this.connected=!1,this.retryTimer=null,this.baseUrl=`http://localhost:${e}`,this.discover(),this.store.on("add",t=>this.postAnnotation(t)),this.store.on("resolve",t=>this.patchAnnotation(t))}async discover(){try{const t=await fetch(`${this.baseUrl}/health`),e=await t.json();e&&"object"==typeof e&&"status"in e&&"ok"===e.status&&(this.connected=!0,this.onChange?.(!0),await this.createSession(),this.stopRetry())}catch{this.connected=!1,this.onChange?.(!1),this.startRetry()}}startRetry(){this.retryTimer||(this.retryTimer=setInterval(()=>this.discover(),5e3))}stopRetry(){this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null)}async createSession(){try{const t=await fetch(`${this.baseUrl}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:window.location.href,title:document.title||window.location.pathname})}),e=await t.json();this.sessionId=e.id}catch{}}async postAnnotation(t){if(this.connected&&this.sessionId)try{await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetSelector:t.targetSelector,targetRect:t.targetRect,text:t.text})})}catch{}}async patchAnnotation(t){if(this.connected)try{await fetch(`${this.baseUrl}/annotations/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({resolved:!0,summary:"Resolved from browser"})})}catch{}}isConnected(){return this.connected}destroy(){this.stopRetry()}}class l{constructor(o={}){this.mcpBridge=null,this.currentTarget=null,this.currentRect=null,this.clearOnCopy=!1,this.host=document.createElement("div"),this.host.id="refiner-host",this.shadow=this.host.attachShadow({mode:"open"});const l=document.createElement("style");l.textContent='\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: \'\';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: \'\';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking="true"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking="false"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved="true"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n',this.shadow.appendChild(l),this.store=new t,this.toolbar=new e(this.shadow),this.settings=new a(this.shadow),this.overlay=new n(this.shadow),this.dialog=new i(this.shadow),this.markers=new s(this.shadow,this.store),this.toolbar.onCopy=()=>this.copyAnnotations(),this.toolbar.onClear=()=>this.clearAnnotations(),this.toolbar.onSettings=()=>{this.settings.toggle(),this.toolbar.setSettingsOpen(this.settings.isVisible())},this.toolbar.onCollapse=()=>{this.settings.hide(),this.toolbar.setSettingsOpen(!1),this.overlay.setEnabled(!1),this.host.style.pointerEvents="none"},this.toolbar.onExpand=()=>{this.overlay.setEnabled(!0),this.host.style.pointerEvents=""},this.settings.onChange=t=>{this.clearOnCopy=t.clearOnCopy,this.overlay.setBlocking(t.blockInteractions),this.markers.setColor(t.markerColor),this.overlay.setHighlightColor(t.markerColor)},this.overlay.onClick=(t,e)=>{if(this.settings.isVisible())return void this.settings.hide();if(this.dialog.isVisible())return void this.dialog.hide();this.currentTarget=t,this.currentRect=e;const n=e.left+e.width/2,i=e.top+e.height/2;this.dialog.show(n,i)},this.dialog.onSubmit=t=>{if(this.currentTarget&&this.currentRect){const e=function(t){if(t.id)return`#${CSS.escape(t.id)}`;if(t.classList.length>0){const e=`${t.tagName.toLowerCase()}.${Array.from(t.classList).map(CSS.escape).join(".")}`;if(1===document.querySelectorAll(e).length)return e}const e=[];let n=t;for(;n&&n!==document.documentElement;){const t=n.tagName.toLowerCase(),i=n.parentElement;if(n.id){e.unshift(`#${CSS.escape(n.id)}`);break}if(i){const s=Array.from(i.children).filter(t=>t.tagName===n.tagName);if(1===s.length)e.unshift(t);else{const i=s.indexOf(n)+1;e.unshift(`${t}:nth-child(${i})`)}}else e.unshift(t);n=i}return e.join(" > ")}(this.currentTarget);this.store.add(e,this.currentRect,t),this.toolbar.updateCount(this.store.getCount())}this.currentTarget=null,this.currentRect=null},this.dialog.onCancel=()=>{this.currentTarget=null,this.currentRect=null},this.store.on("resolve",()=>this.toolbar.updateCount(this.store.getCount())),this.store.on("remove",()=>this.toolbar.updateCount(this.store.getCount())),!1!==o.mcpEnabled&&(this.mcpBridge=new r(this.store,o.mcpPort),this.mcpBridge.onChange=t=>{this.settings.setMcpStatus(t)}),document.body.appendChild(this.host),!1===o.enabled&&this.disable()}enable(){this.host.style.display="",this.overlay.setEnabled(!0)}disable(){this.host.style.display="none",this.overlay.setEnabled(!1)}destroy(){this.mcpBridge?.destroy(),this.host.remove()}getAnnotations(){return this.store.getAll()}getAnnotationCount(){return this.store.getCount()}formatForAgent(){const t=this.store.getAll();if(0===t.length)return"No annotations.";const e=document.title||window.location.pathname,n=window.location.pathname,i=[`# Design Annotations — ${e}`,`**File:** \`${n.substring(n.lastIndexOf("/")+1)||"index.html"}\``,""];for(let e=0;e<t.length;e++){const n=t[e],s=n.resolved?" (resolved)":"";i.push(`## ${e+1}.${s}`),i.push(`**Element:** \`${n.targetSelector}\``),i.push(`**Issue:** ${n.text}`),i.push("")}return i.join("\n")}clearAnnotations(){const t=this.store.getAll();for(const e of t)this.store.remove(e.id);this.toolbar.updateCount(0)}copyAnnotations(){const t=this.formatForAgent();navigator.clipboard.writeText(t),this.clearOnCopy&&this.clearAnnotations()}}if("undefined"!=typeof window&&"undefined"!=typeof document){const t=()=>{if(window.__refiner)return;const t=document.currentScript,e=t?.dataset.refinerPosition??"right",n="false"!==t?.dataset.refinerEnabled,i=t?.dataset.refinerMcpPort?parseInt(t.dataset.refinerMcpPort,10):void 0,s="false"!==t?.dataset.refinerMcpEnabled,o=new l({position:e,enabled:n,mcpPort:i,mcpEnabled:s});window.__refiner=o};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}export{l as Refiner};
1
+ class t{constructor(){this.annotations=new Map,this.listeners=new Map}add(t,e,n){const i={id:crypto.randomUUID(),targetSelector:t,targetRect:{x:e.x,y:e.y,width:e.width,height:e.height},text:n,timestamp:Date.now(),resolved:!1};return this.annotations.set(i.id,i),this.emit("add",i),i}resolve(t){const e=this.annotations.get(t);e&&(e.resolved=!0,this.emit("resolve",e))}remove(t){const e=this.annotations.get(t);e&&(this.annotations.delete(t),this.emit("remove",e))}get(t){return this.annotations.get(t)}getAll(){return Array.from(this.annotations.values())}getPending(){return this.getAll().filter(t=>!t.resolved)}getCount(){return this.annotations.size}exportJSON(){return JSON.stringify(this.getAll(),null,2)}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){this.listeners.get(t)?.delete(e)}emit(t,e){this.listeners.get(t)?.forEach(t=>t(e))}}class e{constructor(t){this.root=t,this.collapsed=!0,this.settingsOpen=!1,this.el=document.createElement("div"),this.el.className="refiner-toolbar",this.el.setAttribute("data-refiner-toolbar",""),this.el.setAttribute("data-collapsed","true"),this.render(),t.appendChild(this.el),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.collapsed=!1,this.el.setAttribute("data-collapsed","false"),this.updateBadgeVisibility()})})}render(){const t=document.createElement("div");t.className="toolbar-pill",this.innerEl=document.createElement("div"),this.innerEl.className="toolbar-inner",this.countBadge=document.createElement("span"),this.countBadge.className="toolbar-count",this.countBadge.textContent="0",this.innerEl.appendChild(this.createBtn(this.countBadge,"Annotations",null));const e='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';this.copyBtn=this.createBtn(e,"Copy annotations",()=>{this.copyBtn.classList.contains("disabled")||(this.onCopy?.(),this.copyBtn.querySelector(".toolbar-icon").innerHTML='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg>',setTimeout(()=>{this.copyBtn.querySelector(".toolbar-icon").innerHTML=e},1500))}),this.copyBtn.classList.add("disabled"),this.innerEl.appendChild(this.copyBtn),this.clearBtn=this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>',"Clear all",()=>{this.clearBtn.classList.contains("disabled")||this.onClear?.()}),this.clearBtn.classList.add("disabled"),this.innerEl.appendChild(this.clearBtn),this.innerEl.appendChild(this.createBtn('<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.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-4 0v-.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-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.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 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.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 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',"Settings",()=>this.onSettings?.()));const n=document.createElement("div");n.className="toolbar-divider",this.innerEl.appendChild(n),t.appendChild(this.innerEl);const i='<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>';this.toggleBtn=this.createBtn(i,"",()=>this.toggleCollapse()),this.toggleBtn.classList.add("toolbar-toggle-btn"),t.appendChild(this.toggleBtn),this.expandBadge=document.createElement("span"),this.expandBadge.className="toolbar-expand-badge hidden",this.expandBadge.textContent="0",t.appendChild(this.expandBadge),this.el.appendChild(t),this.el.addEventListener("transitionend",()=>{this.toggleBtn.querySelector(".toolbar-icon").innerHTML=this.collapsed?i:'<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>'})}createBtn(t,e,n){const i=document.createElement("button");i.className="toolbar-btn";const s=document.createElement("span");if(s.className="toolbar-icon","string"==typeof t?s.innerHTML=t:s.appendChild(t),i.appendChild(s),e){const t=document.createElement("span");t.className="toolbar-tooltip",t.textContent=e,i.appendChild(t)}return n&&i.addEventListener("click",n),i}toggleCollapse(){this.collapsed=!this.collapsed,this.el.setAttribute("data-collapsed",String(this.collapsed)),this.updateBadgeVisibility(),this.collapsed?this.onCollapse?.():this.onExpand?.()}setSettingsOpen(t){this.settingsOpen=t,this.el.classList.toggle("tooltips-hidden",t)}updateCount(t){this.countBadge.textContent=String(t),this.expandBadge.textContent=String(t),this.updateBadgeVisibility(t);const e=0===t;this.copyBtn.classList.toggle("disabled",e),this.clearBtn.classList.toggle("disabled",e)}updateBadgeVisibility(t){const e=t??parseInt(this.expandBadge.textContent||"0",10);this.expandBadge.classList.toggle("hidden",0===e||!this.collapsed)}}class n{constructor(t){this.root=t,this.enabled=!0,this.blocking=!0,this.currentTarget=null,this.highlightColor="#7C3AED",this.handleMouseMove=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return void this.hideHighlight();const e=this.getElementAt(t.clientX,t.clientY);e&&e!==this.currentTarget&&(this.currentTarget=e,this.showHighlight(e))},this.handleClick=t=>{if(!this.enabled)return;if(this.isOverOwnUI(t.clientX,t.clientY))return;t.preventDefault(),t.stopPropagation();const e=this.getElementAt(t.clientX,t.clientY);if(e){const t=e.getBoundingClientRect();this.onClick?.(e,t)}},this.handleKeyBlock=t=>{if(!this.enabled||!this.blocking)return;const e=t.target;e&&(e===this.root.host||this.root.host.contains(e))||(t.preventDefault(),t.stopPropagation())},this.el=document.createElement("div"),this.el.className="refiner-overlay",this.el.setAttribute("data-blocking","true"),this.highlight=document.createElement("div"),this.highlight.className="refiner-highlight",this.highlight.style.display="none",t.appendChild(this.highlight),t.appendChild(this.el),this.el.addEventListener("mousemove",this.handleMouseMove),this.el.addEventListener("click",this.handleClick),this.el.addEventListener("mouseleave",()=>this.hideHighlight()),document.addEventListener("keydown",this.handleKeyBlock,!0)}isOverOwnUI(t,e){const n=this.root.elementFromPoint(t,e);return!!n&&(n!==this.el&&n!==this.highlight)}getElementAt(t,e){this.el.style.pointerEvents="none",this.highlight.style.pointerEvents="none";const n=document.elementFromPoint(t,e);return this.el.style.pointerEvents="",this.highlight.style.pointerEvents="",n&&n===this.root.host?null:n}showHighlight(t){const e=t.getBoundingClientRect();this.highlight.style.display="block",this.highlight.style.top=e.top-2+"px",this.highlight.style.left=e.left-2+"px",this.highlight.style.width=`${e.width+4}px`,this.highlight.style.height=`${e.height+4}px`,this.highlight.style.borderColor=this.highlightColor}hideHighlight(){this.highlight.style.display="none",this.currentTarget=null}setHighlightColor(t){this.highlightColor=t}setBlocking(t){this.blocking=t,this.el.setAttribute("data-blocking",String(t)),t||this.hideHighlight()}setEnabled(t){this.enabled=t,this.el.classList.toggle("hidden",!t),t||this.hideHighlight()}}class i{constructor(t){this.root=t,this.el=document.createElement("div"),this.el.className="refiner-dialog hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="dialog-header";const e=document.createElement("span");e.textContent="What should change?",t.appendChild(e),this.el.appendChild(t),this.textarea=document.createElement("textarea"),this.textarea.className="dialog-textarea",this.textarea.placeholder="Describe the issue or improvement...",this.textarea.addEventListener("input",()=>{this.addBtn.disabled=0===this.textarea.value.trim().length}),this.textarea.addEventListener("keydown",t=>{"Enter"===t.key&&(t.metaKey||t.ctrlKey)&&this.textarea.value.trim()&&this.submit(),"Escape"===t.key&&(this.hide(),this.onCancel?.())}),this.el.appendChild(this.textarea);const n=document.createElement("div");n.className="dialog-actions";const i=document.createElement("button");i.className="dialog-btn dialog-btn-cancel",i.textContent="Cancel",i.addEventListener("click",()=>{this.hide(),this.onCancel?.()}),this.addBtn=document.createElement("button"),this.addBtn.className="dialog-btn dialog-btn-add",this.addBtn.textContent="Add",this.addBtn.disabled=!0,this.addBtn.addEventListener("click",()=>this.submit()),n.appendChild(i),n.appendChild(this.addBtn),this.el.appendChild(n)}submit(){const t=this.textarea.value.trim();t&&(this.onSubmit?.(t),this.hide())}show(t,e){let n=t+12,i=e+12;n+320>window.innerWidth-16&&(n=t-320-12),i+200>window.innerHeight-16&&(i=e-200-12),this.el.style.left=`${Math.max(16,n)}px`,this.el.style.top=`${Math.max(16,i)}px`,this.el.classList.remove("hidden"),this.textarea.value="",this.addBtn.disabled=!0,requestAnimationFrame(()=>this.textarea.focus())}hide(){this.el.classList.add("hidden"),this.textarea.value=""}isVisible(){return!this.el.classList.contains("hidden")}}class s{constructor(t,e){this.root=t,this.store=e,this.markers=new Map,this.rafId=null,this.color="#7C3AED",this.container=document.createElement("div"),this.container.className="refiner-markers",t.appendChild(this.container),e.on("add",t=>this.addMarker(t)),e.on("resolve",t=>this.updateMarker(t)),e.on("remove",t=>this.removeMarker(t.id));const n=()=>this.repositionAll();window.addEventListener("scroll",n,{passive:!0}),window.addEventListener("resize",n,{passive:!0})}addMarker(t){const e=document.createElement("div");e.className="refiner-marker",e.setAttribute("data-annotation-marker",t.id),e.setAttribute("data-resolved",String(t.resolved)),e.style.background=this.color;const n=this.markers.size+1;e.textContent=String(n);const i=document.createElement("div");i.className="marker-tooltip";const s=document.createElement("div");s.textContent=t.text,i.appendChild(s);const o=document.createElement("div");o.className="marker-tooltip-actions";const a=document.createElement("button");a.className="marker-tooltip-btn resolve",a.textContent="Resolve",a.addEventListener("click",e=>{e.stopPropagation(),this.store.resolve(t.id)});const r=document.createElement("button");r.className="marker-tooltip-btn delete",r.textContent="Delete",r.addEventListener("click",e=>{e.stopPropagation(),this.store.remove(t.id)}),o.appendChild(a),o.appendChild(r),i.appendChild(o),e.appendChild(i),this.positionMarker(e,t),this.container.appendChild(e),this.markers.set(t.id,{el:e,annotation:t})}updateMarker(t){const e=this.markers.get(t.id);e&&(e.annotation=t,e.el.setAttribute("data-resolved",String(t.resolved)))}removeMarker(t){const e=this.markers.get(t);e&&(e.el.remove(),this.markers.delete(t),this.renumber())}renumber(){let t=1;for(const[,e]of this.markers){const n=e.el.childNodes[0];n&&n.nodeType===Node.TEXT_NODE&&(n.textContent=String(t)),t++}}positionMarker(t,e){const n=this.queryTarget(e.targetSelector);if(n){const e=n.getBoundingClientRect();t.style.top=e.top-8+"px",t.style.left=e.right-8+"px"}else t.style.top=e.targetRect.y-8+"px",t.style.left=e.targetRect.x+e.targetRect.width-8+"px"}queryTarget(t){try{return document.querySelector(t)}catch{return null}}setColor(t){this.color=t;for(const[,e]of this.markers)e.el.style.background=t}clearAll(){for(const[t]of this.markers)this.removeMarker(t)}repositionAll(){null===this.rafId&&(this.rafId=requestAnimationFrame(()=>{this.rafId=null;for(const[,t]of this.markers)this.positionMarker(t.el,t.annotation)}))}}const o=[{id:"purple",color:"#7C3AED"},{id:"blue",color:"#2563EB"},{id:"green",color:"#059669"},{id:"yellow",color:"#D97706"},{id:"orange",color:"#EA580C"},{id:"red",color:"#DC2626"},{id:"pink",color:"#DB2777"}];class a{constructor(t){this.root=t,this.visible=!1,this.settings={clearOnCopy:!1,blockInteractions:!0,markerColor:"#7C3AED"},this.el=document.createElement("div"),this.el.className="settings-panel hidden",this.render(),t.appendChild(this.el)}render(){const t=document.createElement("div");t.className="settings-header";const e=document.createElement("span");e.className="settings-title",e.textContent="reFiner";const n=document.createElement("span");n.className="settings-version",n.textContent="v0.1.0",t.appendChild(e),t.appendChild(n),this.el.appendChild(t),this.el.appendChild(this.createDivider());const i=document.createElement("div");i.className="settings-section";const s=document.createElement("span");s.className="settings-label",s.textContent="Marker Colour",i.appendChild(s);const a=document.createElement("div");a.className="settings-color-row";for(const t of o){const e=document.createElement("button");e.className="settings-swatch",e.style.background=t.color,e.setAttribute("data-color",t.color),t.color===this.settings.markerColor&&e.classList.add("selected"),e.addEventListener("click",()=>{a.querySelectorAll(".settings-swatch").forEach(t=>t.classList.remove("selected")),e.classList.add("selected"),this.settings.markerColor=t.color,this.emitChange()}),a.appendChild(e)}i.appendChild(a),this.el.appendChild(i),this.el.appendChild(this.createDivider()),this.el.appendChild(this.createCheckbox("Clear on copy",this.settings.clearOnCopy,t=>{this.settings.clearOnCopy=t,this.emitChange()})),this.el.appendChild(this.createCheckbox("Block page interactions",this.settings.blockInteractions,t=>{this.settings.blockInteractions=t,this.emitChange()})),this.el.appendChild(this.createDivider());const r=document.createElement("div");r.className="settings-mcp-row",this.mcpDot=document.createElement("span"),this.mcpDot.className="settings-mcp-dot disconnected",this.mcpLabel=document.createElement("span"),this.mcpLabel.className="settings-check-label",this.mcpLabel.textContent="MCP Disconnected",r.appendChild(this.mcpDot),r.appendChild(this.mcpLabel),this.el.appendChild(r)}createCheckbox(t,e,n){const i=document.createElement("label");i.className="settings-check-row";const s=document.createElement("input");s.type="checkbox",s.className="settings-checkbox",s.checked=e,s.addEventListener("change",()=>n(s.checked));const o=document.createElement("span");return o.className="settings-check-label",o.textContent=t,i.appendChild(s),i.appendChild(o),i}createDivider(){const t=document.createElement("div");return t.className="settings-divider",t}emitChange(){this.onChange?.({...this.settings})}toggle(){this.visible=!this.visible,this.el.classList.toggle("hidden",!this.visible)}hide(){this.visible=!1,this.el.classList.add("hidden")}isVisible(){return this.visible}setMcpStatus(t){this.mcpDot.className="settings-mcp-dot "+(t?"connected":"disconnected"),this.mcpLabel.textContent=t?"MCP Connected":"MCP Disconnected"}getSettings(){return{...this.settings}}}class r{constructor(t,e=4848){this.store=t,this.sessionId=null,this.connected=!1,this.retryTimer=null,this.baseUrl=`http://localhost:${e}`,this.discover(),this.store.on("add",t=>this.postAnnotation(t)),this.store.on("resolve",t=>this.patchAnnotation(t))}async discover(){try{const t=await fetch(`${this.baseUrl}/health`),e=await t.json();e&&"object"==typeof e&&"status"in e&&"ok"===e.status&&(this.connected=!0,this.onChange?.(!0),await this.createSession(),this.stopRetry())}catch{this.connected=!1,this.onChange?.(!1),this.startRetry()}}startRetry(){this.retryTimer||(this.retryTimer=setInterval(()=>this.discover(),5e3))}stopRetry(){this.retryTimer&&(clearInterval(this.retryTimer),this.retryTimer=null)}async createSession(){try{const t=await fetch(`${this.baseUrl}/sessions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:window.location.href,title:document.title||window.location.pathname})}),e=await t.json();this.sessionId=e.id}catch{}}async postAnnotation(t){if(this.connected&&this.sessionId)try{await fetch(`${this.baseUrl}/sessions/${this.sessionId}/annotations`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetSelector:t.targetSelector,targetRect:t.targetRect,text:t.text})})}catch{}}async patchAnnotation(t){if(this.connected)try{await fetch(`${this.baseUrl}/annotations/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({resolved:!0,summary:"Resolved from browser"})})}catch{}}isConnected(){return this.connected}destroy(){this.stopRetry()}}class l{constructor(o={}){this.mcpBridge=null,this.currentTarget=null,this.currentRect=null,this.clearOnCopy=!1,this.host=document.createElement("div"),this.host.id="refiner-host",this.shadow=this.host.attachShadow({mode:"open"});const l=document.createElement("style");l.textContent='\n :host {\n all: initial;\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', system-ui, sans-serif;\n font-size: 13px;\n line-height: 1.4;\n color: #1a1a2e;\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ── Toolbar ── */\n\n .refiner-toolbar {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 10;\n user-select: none;\n }\n\n .toolbar-pill {\n display: flex;\n align-items: center;\n position: relative;\n background: #1a1a2e;\n border-radius: 100px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15);\n padding: 6px;\n transform: scale(1);\n transform-origin: right center;\n transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-pill {\n transform: scale(0.92);\n }\n\n .toolbar-inner {\n display: flex;\n align-items: center;\n gap: 2px;\n overflow: hidden;\n clip-path: inset(0);\n max-width: 300px;\n opacity: 1;\n padding-right: 2px;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s ease 0.1s,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .refiner-toolbar[data-collapsed="true"] .toolbar-inner {\n max-width: 0;\n opacity: 0;\n padding-right: 0;\n transition: max-width 0.35s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.15s ease,\n padding 0.35s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .toolbar-btn {\n position: relative;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: transparent;\n color: #a0a0b8;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: color 0.15s, background 0.15s;\n }\n\n .toolbar-btn:hover {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.1);\n }\n\n .toolbar-btn.active {\n color: #ffffff;\n background: rgba(255, 255, 255, 0.15);\n }\n\n .toolbar-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .toolbar-count {\n font-size: 14px;\n font-weight: 700;\n min-width: 18px;\n text-align: center;\n }\n\n .toolbar-divider {\n width: 1px;\n height: 20px;\n background: rgba(255, 255, 255, 0.15);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Tooltip */\n .toolbar-tooltip {\n position: absolute;\n bottom: calc(100% + 10px);\n left: 50%;\n transform: translateX(-50%);\n padding: 6px 10px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n\n .toolbar-tooltip::after {\n content: \'\';\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: #1a1a2e;\n }\n\n .toolbar-btn:hover .toolbar-tooltip {\n opacity: 1;\n }\n\n .tooltips-hidden .toolbar-tooltip {\n display: none;\n }\n\n .toolbar-btn.disabled {\n opacity: 0.3;\n cursor: default;\n }\n\n .toolbar-btn.disabled:hover {\n color: #a0a0b8;\n background: transparent;\n }\n\n /* Toggle button (always visible) */\n .toolbar-toggle-btn {\n flex-shrink: 0;\n }\n\n /* Badge for collapsed state */\n .toolbar-expand-badge {\n position: absolute;\n top: -6px;\n right: -6px;\n min-width: 20px;\n height: 20px;\n padding: 0 5px;\n border-radius: 10px;\n background: #DC2626;\n color: #ffffff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);\n }\n\n .toolbar-expand-badge.hidden {\n display: none;\n }\n\n /* ── Settings Panel ── */\n\n .settings-panel {\n position: fixed;\n bottom: 80px;\n right: 24px;\n width: 300px;\n z-index: 12;\n background: #1a1a2e;\n border-radius: 16px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 20px;\n color: #e8e8f0;\n transform-origin: bottom right;\n transition: transform 0.25s ease, opacity 0.1s ease;\n transform: scale(1);\n opacity: 1;\n }\n\n .settings-panel.hidden {\n transform: scale(0.4);\n opacity: 0;\n pointer-events: none;\n }\n\n .settings-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .settings-title {\n font-size: 16px;\n font-weight: 700;\n font-style: normal;\n color: #ffffff;\n }\n\n .settings-version {\n font-size: 12px;\n color: #6b6b80;\n font-weight: 500;\n }\n\n .settings-divider {\n height: 1px;\n background: rgba(255, 255, 255, 0.08);\n margin: 16px 0;\n }\n\n .settings-section {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .settings-label {\n font-size: 14px;\n font-weight: 500;\n color: #c0c0d0;\n }\n\n .settings-color-row {\n display: flex;\n gap: 8px;\n }\n\n .settings-swatch {\n width: 24px;\n height: 24px;\n border-radius: 4px;\n border: 2px solid transparent;\n cursor: pointer;\n transition: transform 0.15s, border-color 0.15s;\n outline: none;\n }\n\n .settings-swatch:hover {\n transform: scale(1.1);\n }\n\n .settings-swatch.selected {\n border-color: #ffffff;\n transform: scale(1.1);\n }\n\n .settings-check-row {\n display: flex;\n align-items: center;\n gap: 10px;\n cursor: pointer;\n padding: 2px 0;\n }\n\n .settings-checkbox {\n appearance: none;\n -webkit-appearance: none;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n border: 2px solid #4a4a60;\n background: transparent;\n cursor: pointer;\n position: relative;\n flex-shrink: 0;\n transition: background 0.15s, border-color 0.15s;\n }\n\n .settings-checkbox:checked {\n background: #2563EB;\n border-color: #2563EB;\n }\n\n .settings-checkbox:checked::after {\n content: \'\';\n position: absolute;\n top: 2px;\n left: 5px;\n width: 5px;\n height: 9px;\n border: solid #ffffff;\n border-width: 0 2px 2px 0;\n transform: rotate(45deg);\n }\n\n .settings-check-label {\n font-size: 14px;\n font-weight: 500;\n color: #e8e8f0;\n }\n\n /* ── Overlay ── */\n\n .refiner-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n cursor: crosshair;\n z-index: 1;\n }\n\n .refiner-overlay[data-blocking="true"] {\n pointer-events: all;\n }\n\n .refiner-overlay[data-blocking="false"] {\n pointer-events: none;\n }\n\n .refiner-overlay.hidden {\n display: none;\n }\n\n /* ── Highlight ── */\n\n .refiner-highlight {\n position: fixed;\n pointer-events: none;\n border: 2px dashed;\n border-radius: 3px;\n z-index: 2;\n transition: all 0.1s ease;\n }\n\n /* ── Dialog ── */\n\n .refiner-dialog {\n position: fixed;\n width: 320px;\n background: #1a1a2e;\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 14px;\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.2);\n padding: 16px;\n z-index: 11;\n color: #e8e8f0;\n animation: dialog-in 0.2s ease;\n }\n\n @keyframes dialog-in {\n from { opacity: 0; transform: translateY(4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .refiner-dialog.hidden {\n display: none;\n }\n\n .dialog-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n }\n\n .dialog-header span {\n font-size: 12px;\n font-weight: 600;\n color: #c0c0d0;\n }\n\n .dialog-textarea {\n width: 100%;\n min-height: 72px;\n padding: 10px 12px;\n border: 1px solid rgba(255, 255, 255, 0.1);\n border-radius: 10px;\n font-family: inherit;\n font-size: 13px;\n line-height: 1.5;\n color: #e8e8f0;\n background: rgba(255, 255, 255, 0.06);\n resize: vertical;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .dialog-textarea:focus {\n border-color: rgba(255, 255, 255, 0.25);\n }\n\n .dialog-textarea::placeholder {\n color: #6b6b80;\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 12px;\n }\n\n .dialog-btn {\n height: 32px;\n padding: 0 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .dialog-btn-cancel {\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.12);\n color: #a0a0b8;\n }\n\n .dialog-btn-cancel:hover {\n background: rgba(255, 255, 255, 0.08);\n color: #e8e8f0;\n }\n\n .dialog-btn-add {\n background: #2563EB;\n border: none;\n color: #ffffff;\n }\n\n .dialog-btn-add:hover {\n background: #3B82F6;\n }\n\n .dialog-btn-add:disabled {\n opacity: 0.3;\n cursor: not-allowed;\n }\n\n /* ── Markers ── */\n\n .refiner-marker {\n position: fixed;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n color: #ffffff;\n cursor: pointer;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s;\n pointer-events: all;\n }\n\n .refiner-marker:hover {\n transform: scale(1.2);\n }\n\n .refiner-marker[data-resolved="true"] {\n opacity: 0.4;\n }\n\n .marker-tooltip {\n position: absolute;\n bottom: calc(100% + 8px);\n left: 50%;\n transform: translateX(-50%);\n width: 220px;\n padding: 10px 12px;\n background: #1a1a2e;\n color: #e8e8f0;\n font-size: 12px;\n line-height: 1.4;\n border-radius: 10px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .refiner-marker:hover .marker-tooltip {\n opacity: 1;\n }\n\n .marker-tooltip-actions {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n border-top: 1px solid rgba(255,255,255,0.1);\n padding-top: 8px;\n }\n\n .marker-tooltip-btn {\n height: 22px;\n padding: 0 8px;\n border-radius: 5px;\n border: none;\n font-size: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: background 0.15s;\n }\n\n .marker-tooltip-btn.resolve {\n background: #34D399;\n color: #0a2e1f;\n }\n\n .marker-tooltip-btn.resolve:hover {\n background: #4ade80;\n }\n\n .marker-tooltip-btn.delete {\n background: rgba(255,255,255,0.1);\n color: #e8e8f0;\n }\n\n .marker-tooltip-btn.delete:hover {\n background: #FF6B6B;\n color: #fff;\n }\n\n /* MCP status */\n .settings-mcp-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n }\n\n .settings-mcp-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .settings-mcp-dot.connected {\n background: #34D399;\n box-shadow: 0 0 6px #34D39980;\n }\n\n .settings-mcp-dot.disconnected {\n background: #6B7280;\n }\n',this.shadow.appendChild(l),this.store=new t,this.toolbar=new e(this.shadow),this.settings=new a(this.shadow),this.overlay=new n(this.shadow),this.dialog=new i(this.shadow),this.markers=new s(this.shadow,this.store),this.toolbar.onCopy=()=>this.copyAnnotations(),this.toolbar.onClear=()=>this.clearAnnotations(),this.toolbar.onSettings=()=>{this.settings.toggle(),this.toolbar.setSettingsOpen(this.settings.isVisible())},this.toolbar.onCollapse=()=>{this.settings.hide(),this.toolbar.setSettingsOpen(!1),this.overlay.setEnabled(!1)},this.toolbar.onExpand=()=>{this.overlay.setEnabled(!0)},this.settings.onChange=t=>{this.clearOnCopy=t.clearOnCopy,this.overlay.setBlocking(t.blockInteractions),this.markers.setColor(t.markerColor),this.overlay.setHighlightColor(t.markerColor)},this.overlay.onClick=(t,e)=>{if(this.settings.isVisible())return void this.settings.hide();if(this.dialog.isVisible())return void this.dialog.hide();this.currentTarget=t,this.currentRect=e;const n=e.left+e.width/2,i=e.top+e.height/2;this.dialog.show(n,i)},this.dialog.onSubmit=t=>{if(this.currentTarget&&this.currentRect){const e=function(t){if(t.id)return`#${CSS.escape(t.id)}`;if(t.classList.length>0){const e=`${t.tagName.toLowerCase()}.${Array.from(t.classList).map(CSS.escape).join(".")}`;if(1===document.querySelectorAll(e).length)return e}const e=[];let n=t;for(;n&&n!==document.documentElement;){const t=n.tagName.toLowerCase(),i=n.parentElement;if(n.id){e.unshift(`#${CSS.escape(n.id)}`);break}if(i){const s=Array.from(i.children).filter(t=>t.tagName===n.tagName);if(1===s.length)e.unshift(t);else{const i=s.indexOf(n)+1;e.unshift(`${t}:nth-child(${i})`)}}else e.unshift(t);n=i}return e.join(" > ")}(this.currentTarget);this.store.add(e,this.currentRect,t),this.toolbar.updateCount(this.store.getCount())}this.currentTarget=null,this.currentRect=null},this.dialog.onCancel=()=>{this.currentTarget=null,this.currentRect=null},this.store.on("resolve",()=>this.toolbar.updateCount(this.store.getCount())),this.store.on("remove",()=>this.toolbar.updateCount(this.store.getCount())),!1!==o.mcpEnabled&&(this.mcpBridge=new r(this.store,o.mcpPort),this.mcpBridge.onChange=t=>{this.settings.setMcpStatus(t)}),document.body.appendChild(this.host),!1===o.enabled&&this.disable()}enable(){this.host.style.display="",this.overlay.setEnabled(!0)}disable(){this.host.style.display="none",this.overlay.setEnabled(!1)}destroy(){this.mcpBridge?.destroy(),this.host.remove()}getAnnotations(){return this.store.getAll()}getAnnotationCount(){return this.store.getCount()}formatForAgent(){const t=this.store.getAll();if(0===t.length)return"No annotations.";const e=document.title||window.location.pathname,n=window.location.pathname,i=[`# Design Annotations — ${e}`,`**File:** \`${n.substring(n.lastIndexOf("/")+1)||"index.html"}\``,""];for(let e=0;e<t.length;e++){const n=t[e],s=n.resolved?" (resolved)":"";i.push(`## ${e+1}.${s}`),i.push(`**Element:** \`${n.targetSelector}\``),i.push(`**Issue:** ${n.text}`),i.push("")}return i.join("\n")}clearAnnotations(){const t=this.store.getAll();for(const e of t)this.store.remove(e.id);this.toolbar.updateCount(0)}copyAnnotations(){const t=this.formatForAgent();navigator.clipboard.writeText(t),this.clearOnCopy&&this.clearAnnotations()}}if("undefined"!=typeof window&&"undefined"!=typeof document){const t=()=>{if(window.__refiner)return;const t=document.currentScript,e=t?.dataset.refinerPosition??"right",n="false"!==t?.dataset.refinerEnabled,i=t?.dataset.refinerMcpPort?parseInt(t.dataset.refinerMcpPort,10):void 0,s="false"!==t?.dataset.refinerMcpEnabled,o=new l({position:e,enabled:n,mcpPort:i,mcpEnabled:s});window.__refiner=o};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}export{l as Refiner};
2
2
  //# sourceMappingURL=refiner.mjs.map