bugstash 0.1.11 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/breadcrumbs.ts","../src/redact.ts","../src/logger.ts","../src/network.ts","../src/errors.ts","../src/performance.ts","../src/screenshot.ts","../src/api.ts","../src/themes.ts","../src/layouts.ts","../src/realtime.ts","../src/livepins.ts","../src/panel.ts","../src/annotation.ts","../src/index.ts"],"sourcesContent":["import type { Breadcrumb } from '@bugstash/shared';\n\nlet crumbs: Breadcrumb[] = [];\nlet maxCrumbs = 50;\nlet clickHandler: ((e: MouseEvent) => void) | null = null;\nlet inputHandler: ((e: Event) => void) | null = null;\nlet popstateHandler: (() => void) | null = null;\nlet hashHandler: (() => void) | null = null;\n\nfunction getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const tag = el.tagName.toLowerCase();\n const cls = el.className && typeof el.className === 'string'\n ? '.' + el.className.trim().split(/\\s+/).slice(0, 2).join('.')\n : '';\n const text = (el.textContent || '').trim().slice(0, 30);\n const label = text ? ` \"${text}\"` : '';\n return `${tag}${cls}${label}`;\n}\n\nexport function addBreadcrumb(crumb: Breadcrumb) {\n crumbs.push(crumb);\n if (crumbs.length > maxCrumbs) crumbs.shift();\n}\n\nexport function initBreadcrumbs(max?: number) {\n if (max) maxCrumbs = max;\n\n // Track clicks\n clickHandler = (e: MouseEvent) => {\n const target = e.target as Element;\n if (!target || !target.tagName) return;\n addBreadcrumb({\n type: 'click',\n category: 'ui',\n message: `Clicked ${getSelector(target)}`,\n timestamp: Date.now(),\n data: { x: e.clientX, y: e.clientY, selector: getSelector(target) },\n });\n };\n document.addEventListener('click', clickHandler, true);\n\n // Track input changes (debounced per element)\n const inputTimers = new WeakMap<Element, number>();\n inputHandler = (e: Event) => {\n const target = e.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n if (!target || !target.tagName) return;\n const tag = target.tagName.toLowerCase();\n if (tag !== 'input' && tag !== 'textarea' && tag !== 'select') return;\n\n // Debounce per element\n const existing = inputTimers.get(target);\n if (existing) clearTimeout(existing);\n inputTimers.set(\n target,\n window.setTimeout(() => {\n const isPassword = target instanceof HTMLInputElement && target.type === 'password';\n addBreadcrumb({\n type: 'input',\n category: 'ui',\n message: `Input ${getSelector(target)}`,\n timestamp: Date.now(),\n data: {\n selector: getSelector(target),\n value: isPassword ? '[redacted]' : undefined,\n },\n });\n }, 300),\n );\n };\n document.addEventListener('input', inputHandler, true);\n\n // Track navigation\n popstateHandler = () => {\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${window.location.pathname}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n };\n window.addEventListener('popstate', popstateHandler);\n\n hashHandler = () => {\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Hash changed to ${window.location.hash}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n };\n window.addEventListener('hashchange', hashHandler);\n\n // Initial breadcrumb\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Page loaded: ${window.location.pathname}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...crumbs];\n}\n\nexport function clearBreadcrumbs() {\n crumbs = [];\n}\n\nexport function restoreBreadcrumbs() {\n if (clickHandler) document.removeEventListener('click', clickHandler, true);\n if (inputHandler) document.removeEventListener('input', inputHandler, true);\n if (popstateHandler) window.removeEventListener('popstate', popstateHandler);\n if (hashHandler) window.removeEventListener('hashchange', hashHandler);\n clickHandler = null;\n inputHandler = null;\n popstateHandler = null;\n hashHandler = null;\n}\n","/**\n * PII/sensitive data redaction for captured data.\n * Masks passwords, tokens, credit cards, SSNs, emails in captured logs and network data.\n */\n\nconst REDACT_PLACEHOLDER = '[REDACTED]';\n\n// Patterns for common sensitive data\nconst PATTERNS: [RegExp, string | ((match: string) => string)][] = [\n // Credit card numbers (Visa, MC, Amex, etc.)\n [/\\b(?:\\d[ -]*?){13,19}\\b/g, '[CC_REDACTED]'],\n // SSN\n [/\\b\\d{3}-\\d{2}-\\d{4}\\b/g, '[SSN_REDACTED]'],\n // Email addresses (in log strings, not for user context)\n // Intentionally NOT redacting emails since they're often needed for debugging\n // Bearer tokens\n [/Bearer\\s+[A-Za-z0-9\\-._~+/]+=*/g, 'Bearer [TOKEN_REDACTED]'],\n // JWT tokens (xxx.yyy.zzz pattern)\n [/eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g, '[JWT_REDACTED]'],\n // API keys (long hex/base64 strings that look like keys)\n [/(?:api[_-]?key|apikey|secret|token|password|passwd|authorization)['\":\\s=]+['\"]?([A-Za-z0-9\\-._~+/]{20,})['\"]?/gi, (match) => {\n const eqIdx = match.search(/[=:]/);\n return match.slice(0, eqIdx + 1) + ' ' + REDACT_PLACEHOLDER;\n }],\n // AWS access keys\n [/AKIA[0-9A-Z]{16}/g, '[AWS_KEY_REDACTED]'],\n // Generic password fields in JSON\n [/\"(?:password|passwd|secret|token|access_token|refresh_token|api_key|apiKey|private_key)\":\\s*\"[^\"]*\"/gi, (match) => {\n const colonIdx = match.indexOf(':');\n return match.slice(0, colonIdx + 1) + ' \"' + REDACT_PLACEHOLDER + '\"';\n }],\n];\n\n// Header names that should be redacted\nconst SENSITIVE_HEADERS = new Set([\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-auth-token',\n 'x-csrf-token',\n 'proxy-authorization',\n]);\n\n/** Redact sensitive data from a string. */\nexport function redactString(input: string): string {\n let result = input;\n for (const [pattern, replacement] of PATTERNS) {\n if (typeof replacement === 'function') {\n result = result.replace(pattern, replacement as any);\n } else {\n result = result.replace(pattern, replacement);\n }\n }\n return result;\n}\n\n/** Redact sensitive headers from a headers object. */\nexport function redactHeaders(headers: Record<string, string> | undefined): Record<string, string> | undefined {\n if (!headers) return headers;\n const redacted: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (SENSITIVE_HEADERS.has(key.toLowerCase())) {\n redacted[key] = REDACT_PLACEHOLDER;\n } else {\n redacted[key] = redactString(value);\n }\n }\n return redacted;\n}\n\n/** Redact an array of log argument strings. */\nexport function redactLogArgs(args: string[]): string[] {\n return args.map(redactString);\n}\n\n/** Redact sensitive data from serialized objects. */\nexport function redactObject(obj: any): any {\n if (typeof obj === 'string') return redactString(obj);\n if (Array.isArray(obj)) return obj.map(redactObject);\n if (obj && typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n const lk = key.toLowerCase();\n if (lk.includes('password') || lk.includes('secret') || lk.includes('token') ||\n lk.includes('apikey') || lk.includes('api_key') || lk.includes('private')) {\n result[key] = REDACT_PLACEHOLDER;\n } else {\n result[key] = redactObject(value);\n }\n }\n return result;\n }\n return obj;\n}\n","import type { LogEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\nimport { redactLogArgs } from './redact';\n\nconst originals = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n info: console.info,\n};\n\nlet logs: LogEntry[] = [];\nlet maxLogs = 50;\n\nfunction serialize(args: any[]): string[] {\n return args.map((a) => {\n if (a instanceof Error) return `${a.name}: ${a.message}\\n${a.stack ?? ''}`;\n if (typeof a === 'object') {\n try {\n return JSON.stringify(a, null, 2);\n } catch {\n return String(a);\n }\n }\n return String(a);\n });\n}\n\nfunction capture(level: LogEntry['level'], args: any[]) {\n const entry: LogEntry = {\n level,\n args: redactLogArgs(serialize(args)),\n timestamp: Date.now(),\n };\n if (level === 'error') {\n entry.stack = new Error().stack?.split('\\n').slice(2).join('\\n');\n }\n logs.push(entry);\n if (logs.length > maxLogs) logs.shift();\n\n addBreadcrumb({\n type: 'console',\n category: `console.${level}`,\n message: entry.args.join(' ').slice(0, 200),\n timestamp: entry.timestamp,\n });\n}\n\nexport function initLogger(max?: number) {\n if (max) maxLogs = max;\n\n for (const level of Object.keys(originals) as LogEntry['level'][]) {\n console[level] = function (...args: any[]) {\n capture(level, args);\n originals[level].apply(console, args);\n };\n }\n}\n\nexport function getLogs(): LogEntry[] {\n return [...logs];\n}\n\nexport function clearLogs() {\n logs = [];\n}\n\nexport function restoreConsole() {\n for (const level of Object.keys(originals) as LogEntry['level'][]) {\n console[level] = originals[level];\n }\n}\n","import type { NetworkEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\nimport { redactString } from './redact';\n\nlet captures: NetworkEntry[] = [];\nlet maxCaptures = 50;\nlet originalFetch: typeof window.fetch;\nlet originalXHROpen: typeof XMLHttpRequest.prototype.open;\nlet originalXHRSend: typeof XMLHttpRequest.prototype.send;\n\nfunction record(entry: NetworkEntry) {\n captures.push(entry);\n if (captures.length > maxCaptures) captures.shift();\n\n addBreadcrumb({\n type: 'network',\n category: entry.failed ? 'network.error' : 'network.ok',\n message: `${entry.method} ${entry.url} → ${entry.status} (${entry.duration}ms)`,\n timestamp: entry.timestamp,\n data: { status: entry.status, duration: entry.duration },\n });\n}\n\nfunction shortenUrl(url: string): string {\n try {\n const u = new URL(url, window.location.origin);\n // Redact sensitive query params (tokens, keys, etc.)\n const params = new URLSearchParams(u.search);\n for (const key of params.keys()) {\n const lk = key.toLowerCase();\n if (lk.includes('token') || lk.includes('key') || lk.includes('secret') || lk.includes('password') || lk.includes('auth')) {\n params.set(key, '[REDACTED]');\n }\n }\n const qs = params.toString();\n return u.pathname + (qs ? '?' + qs : '');\n } catch {\n return redactString(url);\n }\n}\n\nfunction patchFetch() {\n originalFetch = window.fetch;\n\n window.fetch = async function (input: any, init?: any) {\n const method = init?.method?.toUpperCase() ?? 'GET';\n const rawUrl = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n const url = shortenUrl(rawUrl);\n const start = Date.now();\n\n try {\n const response = await originalFetch.call(window, input, init);\n record({\n method,\n url,\n status: response.status,\n statusText: response.statusText,\n duration: Date.now() - start,\n responseType: response.headers.get('content-type') ?? undefined,\n timestamp: start,\n failed: response.status >= 400,\n });\n return response;\n } catch (err) {\n record({\n method,\n url,\n status: 0,\n statusText: 'Network Error',\n duration: Date.now() - start,\n timestamp: start,\n failed: true,\n });\n throw err;\n }\n };\n}\n\nfunction patchXHR() {\n originalXHROpen = XMLHttpRequest.prototype.open;\n originalXHRSend = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string | URL, ...rest: any[]) {\n (this as any).__bs_method = method.toUpperCase();\n (this as any).__bs_url = shortenUrl(typeof url === 'string' ? url : url.href);\n return originalXHROpen.apply(this, [method, url, ...rest] as any);\n };\n\n XMLHttpRequest.prototype.send = function (body?: any) {\n const start = Date.now();\n\n this.addEventListener('loadend', function () {\n record({\n method: (this as any).__bs_method ?? 'GET',\n url: (this as any).__bs_url ?? '',\n status: this.status,\n statusText: this.statusText,\n duration: Date.now() - start,\n responseType: this.getResponseHeader('content-type') ?? undefined,\n timestamp: start,\n failed: this.status >= 400 || this.status === 0,\n });\n });\n\n return originalXHRSend.call(this, body);\n };\n}\n\nexport function initNetwork(max?: number) {\n if (max) maxCaptures = max;\n patchFetch();\n patchXHR();\n}\n\nexport function getNetworkCaptures(): NetworkEntry[] {\n return [...captures];\n}\n\nexport function getFailedNetworkCaptures(): NetworkEntry[] {\n return captures.filter((c) => c.failed);\n}\n\nexport function clearNetworkCaptures() {\n captures = [];\n}\n\nexport function restoreNetwork() {\n if (originalFetch) window.fetch = originalFetch;\n if (originalXHROpen) XMLHttpRequest.prototype.open = originalXHROpen;\n if (originalXHRSend) XMLHttpRequest.prototype.send = originalXHRSend;\n}\n","import type { ErrorEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\n\nlet errors: ErrorEntry[] = [];\nlet onErrorHandler: ((e: ErrorEvent) => void) | null = null;\nlet onRejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null;\n\nexport function initErrors() {\n onErrorHandler = (event: ErrorEvent) => {\n const entry: ErrorEntry = {\n message: event.message || 'Unknown error',\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n stack: event.error?.stack,\n type: 'error',\n timestamp: Date.now(),\n };\n errors.push(entry);\n addBreadcrumb({\n type: 'error',\n category: 'exception',\n message: entry.message,\n timestamp: entry.timestamp,\n data: { source: entry.source, lineno: entry.lineno },\n });\n };\n\n onRejectionHandler = (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n const message =\n reason instanceof Error ? reason.message : typeof reason === 'string' ? reason : 'Unhandled promise rejection';\n const entry: ErrorEntry = {\n message,\n stack: reason instanceof Error ? reason.stack : undefined,\n type: 'unhandledrejection',\n timestamp: Date.now(),\n };\n errors.push(entry);\n addBreadcrumb({\n type: 'error',\n category: 'promise',\n message,\n timestamp: entry.timestamp,\n });\n };\n\n window.addEventListener('error', onErrorHandler);\n window.addEventListener('unhandledrejection', onRejectionHandler);\n}\n\nexport function getErrors(): ErrorEntry[] {\n return [...errors];\n}\n\nexport function clearErrors() {\n errors = [];\n}\n\nexport function restoreErrors() {\n if (onErrorHandler) window.removeEventListener('error', onErrorHandler);\n if (onRejectionHandler) window.removeEventListener('unhandledrejection', onRejectionHandler);\n onErrorHandler = null;\n onRejectionHandler = null;\n}\n","import type { PerformanceMetrics } from '@bugstash/shared';\n\nlet metrics: PerformanceMetrics | null = null;\nlet lcpObserver: PerformanceObserver | null = null;\nlet clsObserver: PerformanceObserver | null = null;\nlet fidObserver: PerformanceObserver | null = null;\n\nexport function initPerformance() {\n metrics = { timestamp: Date.now() };\n\n // Navigation timing\n if (performance.getEntriesByType) {\n const onLoad = () => {\n const [nav] = performance.getEntriesByType('navigation') as PerformanceNavigationTiming[];\n if (nav && metrics) {\n metrics.pageLoadTime = Math.round(nav.loadEventEnd - nav.startTime);\n metrics.domContentLoaded = Math.round(nav.domContentLoadedEventEnd - nav.startTime);\n }\n\n // Paint timing\n const paints = performance.getEntriesByType('paint');\n for (const p of paints) {\n if (p.name === 'first-paint' && metrics) metrics.firstPaint = Math.round(p.startTime);\n if (p.name === 'first-contentful-paint' && metrics) metrics.firstContentfulPaint = Math.round(p.startTime);\n }\n\n // Resource count\n if (metrics) {\n metrics.resourceCount = performance.getEntriesByType('resource').length;\n }\n\n // Memory (Chrome only)\n const mem = (performance as any).memory;\n if (mem && metrics) {\n metrics.memoryUsage = {\n usedJSHeapSize: mem.usedJSHeapSize,\n totalJSHeapSize: mem.totalJSHeapSize,\n };\n }\n };\n\n if (document.readyState === 'complete') {\n setTimeout(onLoad, 0);\n } else {\n window.addEventListener('load', () => setTimeout(onLoad, 100));\n }\n }\n\n // LCP\n if (typeof PerformanceObserver !== 'undefined') {\n try {\n lcpObserver = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1];\n if (last && metrics) metrics.largestContentfulPaint = Math.round(last.startTime);\n });\n lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch {}\n\n // CLS\n try {\n let clsValue = 0;\n clsObserver = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (!(entry as any).hadRecentInput) {\n clsValue += (entry as any).value;\n }\n }\n if (metrics) metrics.cumulativeLayoutShift = Math.round(clsValue * 1000) / 1000;\n });\n clsObserver.observe({ type: 'layout-shift', buffered: true });\n } catch {}\n\n // FID\n try {\n fidObserver = new PerformanceObserver((list) => {\n const [entry] = list.getEntries();\n if (entry && metrics) metrics.firstInputDelay = Math.round((entry as any).processingStart - entry.startTime);\n });\n fidObserver.observe({ type: 'first-input', buffered: true });\n } catch {}\n }\n}\n\nexport function getPerformanceMetrics(): PerformanceMetrics | null {\n if (metrics) metrics.timestamp = Date.now();\n return metrics ? { ...metrics } : null;\n}\n\nexport function restorePerformance() {\n lcpObserver?.disconnect();\n clsObserver?.disconnect();\n fidObserver?.disconnect();\n lcpObserver = null;\n clsObserver = null;\n fidObserver = null;\n metrics = null;\n}\n","/**\n * Zero-dependency silent screenshot capture.\n * Serializes the DOM into an SVG foreignObject and renders it to a canvas.\n * No browser permission popup — fully silent capture.\n */\n\n/** Show a camera shutter flash animation */\nfunction showFlashAnimation(): void {\n const flash = document.createElement('div');\n flash.style.cssText = `\n position: fixed; inset: 0; z-index: 2147483647;\n background: white; opacity: 0;\n pointer-events: none;\n animation: bs-flash 0.4s ease-out forwards;\n `;\n\n // Inject keyframe if not already present\n if (!document.getElementById('bs-flash-style')) {\n const style = document.createElement('style');\n style.id = 'bs-flash-style';\n style.textContent = `\n @keyframes bs-flash {\n 0% { opacity: 0; }\n 15% { opacity: 0.7; }\n 100% { opacity: 0; }\n }\n `;\n document.head.appendChild(style);\n }\n\n document.body.appendChild(flash);\n flash.addEventListener('animationend', () => flash.remove());\n}\n\nexport async function captureScreenshot(): Promise<string | null> {\n // Show flash immediately for visual feedback\n showFlashAnimation();\n\n try {\n const result = await captureSvgForeignObject();\n if (result) return result;\n } catch { /* fall through */ }\n\n return null;\n}\n\n/** Capture via SVG foreignObject — works without user permission */\nasync function captureSvgForeignObject(): Promise<string | null> {\n const w = window.innerWidth;\n const h = window.innerHeight;\n\n // Clone the document element with computed styles inlined\n const clone = document.documentElement.cloneNode(true) as HTMLElement;\n\n // Inline computed styles on every element so the SVG renders correctly\n const sourceElements = document.documentElement.querySelectorAll('*');\n const cloneElements = clone.querySelectorAll('*');\n\n for (let i = 0; i < sourceElements.length && i < cloneElements.length; i++) {\n const computed = window.getComputedStyle(sourceElements[i]);\n const el = cloneElements[i] as HTMLElement;\n if (el.style) {\n const props = [\n 'background', 'background-color', 'background-image',\n 'color', 'font', 'font-size', 'font-family', 'font-weight',\n 'border', 'border-radius', 'padding', 'margin',\n 'display', 'flex-direction', 'align-items', 'justify-content',\n 'gap', 'width', 'height', 'max-width', 'max-height',\n 'overflow', 'position', 'top', 'left', 'right', 'bottom',\n 'box-shadow', 'text-shadow', 'opacity', 'transform',\n 'text-align', 'line-height', 'letter-spacing',\n 'text-decoration', 'visibility', 'z-index',\n 'grid-template-columns', 'grid-template-rows',\n 'box-sizing',\n ];\n for (const prop of props) {\n try { el.style.setProperty(prop, computed.getPropertyValue(prop)); } catch {}\n }\n }\n }\n\n // Remove scripts and BugStash elements from the clone\n clone.querySelectorAll('script, [data-bugstash], .bs-fab, .bs-toolbar, .bs-modal, .bs-backdrop').forEach(el => el.remove());\n\n // Remove the flash overlay from clone\n clone.querySelectorAll('[style*=\"bs-flash\"]').forEach(el => el.remove());\n\n // Remove cross-origin images to avoid tainted canvas\n clone.querySelectorAll('img').forEach(img => {\n try {\n const src = img.getAttribute('src') || '';\n if (src && !src.startsWith('data:') && !src.startsWith(window.location.origin)) {\n img.removeAttribute('src');\n img.style.backgroundColor = '#e5e7eb';\n }\n } catch {}\n });\n\n const serializer = new XMLSerializer();\n const html = serializer.serializeToString(clone);\n\n const svg = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\">\n <foreignObject width=\"100%\" height=\"100%\">\n ${html}\n </foreignObject>\n </svg>\n `;\n\n const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<string | null>((resolve) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => {\n const canvas = document.createElement('canvas');\n canvas.width = w * 0.5;\n canvas.height = h * 0.5;\n const ctx = canvas.getContext('2d');\n if (!ctx) { URL.revokeObjectURL(url); resolve(null); return; }\n ctx.scale(0.5, 0.5);\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/jpeg', 0.6));\n } catch {\n resolve(null);\n }\n };\n img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };\n img.src = url;\n });\n}\n","import type { BugReport, APIResponse, AuthUser, AuthTokens, LivePin, PinComment, Member } from '@bugstash/shared';\n\n// Primary cloud backend. Falls back to Azure if custom domain is unreachable.\n// Self-hosted users can override via BugStash.init({ endpoint: '...' }).\nconst PRIMARY_ENDPOINT = 'https://bugstash-backend.vercel.app';\nconst FALLBACK_ENDPOINT = 'https://bugstash-backend.vercel.app';\n\nlet endpoint = PRIMARY_ENDPOINT;\nlet _usingFallback = false;\n\nexport function setEndpoint(url: string) {\n endpoint = url.replace(/\\/$/, '');\n _usingFallback = false;\n}\n\nexport function getEndpoint() {\n return endpoint;\n}\n\n/**\n * Tries the current endpoint. On network failure (ERR_CONNECTION_REFUSED, etc.),\n * transparently falls back to the Azure backend so SDK login/reports always work\n * — even if a developer passes a bad endpoint or localhost isn't running.\n */\nasync function fetchWithFallback(url: string, init?: RequestInit): Promise<Response> {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n // Already on the final fallback — nothing left to try\n if (_usingFallback) throw err;\n\n // Fall back to Azure regardless of what the current endpoint is\n _usingFallback = true;\n const previousEndpoint = endpoint;\n endpoint = FALLBACK_ENDPOINT;\n const fallbackUrl = url.replace(previousEndpoint, FALLBACK_ENDPOINT);\n return fetch(fallbackUrl, init);\n }\n}\n\n// ─── Token Management ────────────────────────────────────\n\nconst STORAGE_KEY = 'bugstash_auth';\n\ninterface StoredAuth {\n user: AuthUser;\n tokens: AuthTokens;\n}\n\nfunction getStoredAuth(): StoredAuth | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const auth = JSON.parse(raw) as StoredAuth;\n // Check if access token expired\n if (auth.tokens.expiresAt < Date.now()) {\n // Try to refresh\n return auth; // Will be refreshed on next request\n }\n return auth;\n } catch {\n return null;\n }\n}\n\nfunction setStoredAuth(auth: StoredAuth) {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(auth));\n}\n\nexport function clearStoredAuth() {\n localStorage.removeItem(STORAGE_KEY);\n}\n\nexport function getCurrentUser(): AuthUser | null {\n return getStoredAuth()?.user || null;\n}\n\nexport function getAccessToken(): string | null {\n return getStoredAuth()?.tokens.accessToken || null;\n}\n\nasync function authHeaders(): Promise<Record<string, string>> {\n const auth = getStoredAuth();\n if (!auth) return { 'Content-Type': 'application/json' };\n\n // Refresh if expired\n if (auth.tokens.expiresAt < Date.now() + 60000) {\n try {\n const res = await fetchWithFallback(`${endpoint}/api/auth/refresh`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: auth.tokens.refreshToken }),\n });\n if (res.ok) {\n const data = await res.json();\n if (data.success) {\n auth.tokens = data.data;\n setStoredAuth(auth);\n }\n }\n } catch { /* Use existing token */ }\n }\n\n return {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${auth.tokens.accessToken}`,\n };\n}\n\n// ─── Auth API ────────────────────────────────────────────\n\nexport async function login(email: string, password: string, projectId: string): Promise<APIResponse<{ user: AuthUser; tokens: AuthTokens }>> {\n try {\n const res = await fetchWithFallback(`${endpoint}/api/auth/login`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password, projectId }),\n });\n const data = await res.json();\n if (data.success) {\n setStoredAuth({ user: data.data.user, tokens: data.data.tokens });\n }\n return data;\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function logout() {\n clearStoredAuth();\n}\n\nexport async function fetchMe(): Promise<APIResponse<AuthUser>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/auth/me`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Reports API ─────────────────────────────────────────\n\nexport async function submitReport(report: BugReport): Promise<APIResponse<{ id: string }>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/reports`, {\n method: 'POST',\n headers,\n body: JSON.stringify(report),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error - could not reach BugStash' };\n }\n}\n\n// ─── Pins API ────────────────────────────────────────────\n\nexport async function fetchPagePins(projectId: string, pathname: string): Promise<APIResponse<LivePin[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/by-page?projectId=${projectId}&pathname=${encodeURIComponent(pathname)}`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function createPin(pin: Partial<LivePin>): Promise<APIResponse<LivePin>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins`, {\n method: 'POST',\n headers,\n body: JSON.stringify(pin),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function updatePin(pinId: string, updates: Partial<LivePin>): Promise<APIResponse<LivePin>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(updates),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function deletePin(pinId: string): Promise<APIResponse<void>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}`, {\n method: 'DELETE',\n headers,\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Comments API ────────────────────────────────────────\n\nexport async function fetchComments(pinId: string): Promise<APIResponse<PinComment[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}/comments`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function createComment(pinId: string, body: string, mentions: string[] = []): Promise<APIResponse<PinComment>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}/comments`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ body, mentions }),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Members API ─────────────────────────────────────────\n\nexport async function fetchProjectMembers(projectId: string): Promise<APIResponse<Member[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/members/for-project/${projectId}`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Offline Queue ───────────────────────────────────────\n\nconst QUEUE_KEY = 'bugstash_offline_queue';\n\ninterface QueuedAction {\n id: string;\n type: 'create_pin' | 'create_comment' | 'update_pin' | 'submit_report';\n data: any;\n timestamp: number;\n}\n\nexport function queueOfflineAction(action: Omit<QueuedAction, 'id' | 'timestamp'>) {\n const queue = getOfflineQueue();\n queue.push({\n ...action,\n id: Math.random().toString(36).slice(2),\n timestamp: Date.now(),\n });\n localStorage.setItem(QUEUE_KEY, JSON.stringify(queue));\n}\n\nexport function getOfflineQueue(): QueuedAction[] {\n try {\n return JSON.parse(localStorage.getItem(QUEUE_KEY) || '[]');\n } catch {\n return [];\n }\n}\n\nexport async function flushOfflineQueue(): Promise<number> {\n const queue = getOfflineQueue();\n if (queue.length === 0) return 0;\n\n let flushed = 0;\n const remaining: QueuedAction[] = [];\n\n for (const action of queue) {\n try {\n let result: APIResponse<any>;\n switch (action.type) {\n case 'create_pin':\n result = await createPin(action.data);\n break;\n case 'create_comment':\n result = await createComment(action.data.pinId, action.data.body, action.data.mentions);\n break;\n case 'update_pin':\n result = await updatePin(action.data.pinId, action.data.updates);\n break;\n case 'submit_report':\n result = await submitReport(action.data);\n break;\n default:\n result = { success: false, error: 'Unknown action' };\n }\n if (result.success) {\n flushed++;\n } else {\n remaining.push(action);\n }\n } catch {\n remaining.push(action);\n }\n }\n\n localStorage.setItem(QUEUE_KEY, JSON.stringify(remaining));\n return flushed;\n}\n\n// Auto-flush when back online\nif (typeof window !== 'undefined') {\n window.addEventListener('online', () => {\n flushOfflineQueue().catch(() => {});\n });\n}\n","export interface BsTheme {\n id: string;\n name: string;\n preview: [string, string]; // [bg, accent] for switcher preview\n vars: Record<string, string>;\n}\n\nconst THEMES: BsTheme[] = [\n // ─── Slate (default — blue-gray) ──────────────────\n {\n id: 'slate',\n name: 'Slate',\n preview: ['#0f1117', '#6E9ED0'],\n vars: {\n '--bs-bg': '#0f1117',\n '--bs-bg2': '#1a1d27',\n '--bs-bg3': '#2a2d37',\n '--bs-text': '#e8eaed',\n '--bs-muted': '#9ca3af',\n '--bs-border': '#2a2d37',\n '--bs-accent': '#6E9ED0',\n '--bs-accent2': '#C3CAD6',\n '--bs-fab1': '#6E9ED0',\n '--bs-fab2': '#4a7ba8',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── Pure Black ────────────────────────────────────\n {\n id: 'black',\n name: 'Dark',\n preview: ['#0a0a0a', '#ffffff'],\n vars: {\n '--bs-bg': '#0a0a0a',\n '--bs-bg2': '#141414',\n '--bs-bg3': '#1e1e1e',\n '--bs-text': '#f5f5f5',\n '--bs-muted': '#737373',\n '--bs-border': '#262626',\n '--bs-accent': '#f5f5f5',\n '--bs-accent2': '#d4d4d4',\n '--bs-fab1': '#262626',\n '--bs-fab2': '#171717',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── Pure White ────────────────────────────────────\n {\n id: 'white',\n name: 'Light',\n preview: ['#ffffff', '#0a0a0a'],\n vars: {\n '--bs-bg': '#ffffff',\n '--bs-bg2': '#f5f5f5',\n '--bs-bg3': '#e5e5e5',\n '--bs-text': '#0a0a0a',\n '--bs-muted': '#737373',\n '--bs-border': '#e5e5e5',\n '--bs-accent': '#0a0a0a',\n '--bs-accent2': '#404040',\n '--bs-fab1': '#0a0a0a',\n '--bs-fab2': '#262626',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#dc2626',\n '--bs-green': '#16a34a',\n '--bs-orange': '#ea580c',\n '--bs-yellow': '#ca8a04',\n },\n },\n];\n\nexport function getThemes(): BsTheme[] {\n return THEMES;\n}\n\nexport function getThemeById(id: string): BsTheme | undefined {\n return THEMES.find((t) => t.id === id);\n}\n\nexport function getDefaultTheme(): BsTheme {\n return THEMES[0];\n}\n","export interface BsLayout {\n id: string;\n name: string;\n description: string;\n tabPosition: 'top' | 'left' | 'bottom';\n}\n\nconst LAYOUTS: BsLayout[] = [\n { id: 'classic', name: 'Center', description: 'Centered modal', tabPosition: 'top' },\n { id: 'drawer-right', name: 'Right Drawer', description: 'Slides from right', tabPosition: 'top' },\n { id: 'bottom-sheet', name: 'Bottom Sheet', description: 'Slides from bottom', tabPosition: 'top' },\n { id: 'sidebar-tabs', name: 'Sidebar', description: 'Side navigation', tabPosition: 'left' },\n];\n\nexport function getLayouts(): BsLayout[] {\n return LAYOUTS;\n}\n\nexport function getLayoutById(id: string): BsLayout | undefined {\n return LAYOUTS.find((l) => l.id === id);\n}\n\nexport function getDefaultLayout(): BsLayout {\n return LAYOUTS[0];\n}\n\n// ─── Layout CSS ──────────────────────────────────────────\n\nexport const LAYOUT_CSS = `\n/* ── 1. Classic (default — no overrides) ── */\n\n/* ── 2. Drawer Right ── */\n.bs-ly-drawer-right.bs-modal {\n top: 0; left: auto; right: 0; bottom: 0;\n width: 420px; max-width: 100vw; max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n transform: translateX(100%);\n transition: transform 0.4s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-drawer-right.bs-modal.bs-in {\n transform: translateX(0);\n opacity: 1;\n}\n\n/* ── 3. Bottom Sheet ── */\n.bs-ly-bottom-sheet.bs-modal {\n top: auto; left: 50%; right: auto; bottom: 0;\n width: 600px; max-width: 100vw;\n max-height: 80vh;\n border-radius: var(--bs-radius) var(--bs-radius) 0 0;\n transform: translate(-50%, 100%);\n transition: transform 0.45s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-bottom-sheet.bs-modal.bs-in {\n transform: translate(-50%, 0);\n opacity: 1;\n}\n\n/* ── 4. Sidebar Tabs ── */\n.bs-ly-sidebar-tabs.bs-modal {\n width: 620px;\n}\n.bs-ly-sidebar-tabs .bs-body-wrap {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n.bs-ly-sidebar-tabs .bs-tabs {\n flex-direction: column;\n padding: 12px 0 12px 12px;\n gap: 4px;\n min-width: 140px;\n border-right: 1px solid var(--bs-border);\n overflow-y: auto;\n}\n.bs-ly-sidebar-tabs .bs-tab {\n border-radius: var(--bs-radius-sm);\n padding: 10px 12px;\n width: 100%;\n}\n.bs-ly-sidebar-tabs .bs-tab.bs-active::after {\n top: 8px; bottom: 8px; left: 0; right: auto;\n width: 2px; height: auto;\n border-radius: 0 2px 2px 0;\n}\n.bs-ly-sidebar-tabs .bs-tab-divider { display: none; }\n.bs-ly-sidebar-tabs .bs-scroll { flex: 1; }\n`;\n\nexport default LAYOUTS;\n","import { getEndpoint, getAccessToken } from './api';\nimport type { WSEvent } from '@bugstash/shared';\n\ntype EventHandler = (event: WSEvent) => void;\n\nlet pollTimer: ReturnType<typeof setInterval> | null = null;\nlet lastPollTime = 0;\nconst POLL_INTERVAL = 5000; // 5 seconds\nconst handlers = new Map<string, Set<EventHandler>>();\nlet currentProjectId: string | null = null;\nlet knownPinIds = new Set<string>();\n\nexport function connectRealtime(projectId: string) {\n currentProjectId = projectId;\n lastPollTime = Date.now();\n startPolling();\n}\n\nfunction startPolling() {\n if (pollTimer) return;\n pollTimer = setInterval(poll, POLL_INTERVAL);\n}\n\nasync function poll() {\n if (!currentProjectId) return;\n const token = getAccessToken();\n if (!token) return;\n\n try {\n const endpoint = getEndpoint();\n const pathname = window.location.pathname;\n const res = await fetch(\n `${endpoint}/api/pins/poll?projectId=${currentProjectId}&pathname=${encodeURIComponent(pathname)}&since=${lastPollTime}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n\n if (!res.ok) return;\n const data = await res.json();\n if (!data.success) return;\n\n const { pins, serverTime } = data.data;\n lastPollTime = serverTime;\n\n for (const pin of pins) {\n if (knownPinIds.has(pin.id)) {\n emit('pin:updated', {\n type: 'pin:updated',\n projectId: currentProjectId,\n data: pin,\n userId: '',\n timestamp: Date.now(),\n });\n } else {\n knownPinIds.add(pin.id);\n emit('pin:created', {\n type: 'pin:created',\n projectId: currentProjectId,\n data: pin,\n userId: '',\n timestamp: Date.now(),\n });\n }\n }\n } catch {\n // Silently fail — will retry next interval\n }\n}\n\nexport function disconnectRealtime() {\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n currentProjectId = null;\n knownPinIds.clear();\n lastPollTime = 0;\n}\n\nexport function onRealtimeEvent(type: string, handler: EventHandler) {\n if (!handlers.has(type)) handlers.set(type, new Set());\n handlers.get(type)!.add(handler);\n return () => {\n handlers.get(type)?.delete(handler);\n };\n}\n\nfunction emit(type: string, event: WSEvent) {\n handlers.get(type)?.forEach((h) => h(event));\n handlers.get('*')?.forEach((h) => h(event));\n}\n\n/** Register known pin IDs so polling can detect new vs updated */\nexport function registerKnownPins(pinIds: string[]) {\n knownPinIds = new Set(pinIds);\n}\n\n// Cursor and navigation are no-ops in polling mode\nexport function sendCursorPosition(_x: number, _y: number, _pageUrl: string) {}\nexport function sendPageNavigate(_pageUrl: string) {}\n\nexport function isConnected(): boolean {\n return pollTimer !== null;\n}\n","import type { LivePin, Member } from '@bugstash/shared';\nimport { fetchPagePins, createPin, updatePin, deletePin, fetchComments, createComment, fetchProjectMembers, getCurrentUser, queueOfflineAction } from './api';\nimport { onRealtimeEvent, sendPageNavigate, registerKnownPins } from './realtime';\nimport { captureScreenshot } from './screenshot';\nimport { getLogs } from './logger';\nimport { getErrors } from './errors';\nimport { getFailedNetworkCaptures } from './network';\n\nlet projectId: string;\nlet container: HTMLDivElement | null = null;\nlet pins: LivePin[] = [];\nlet members: Member[] = [];\nlet pinMode = false;\nlet activePopup: HTMLDivElement | null = null;\nlet currentPathname = '';\n\nconst PIN_COLORS: Record<string, string> = {\n open: '#f97316',\n in_progress: '#3b82f6',\n resolved: '#22c55e',\n closed: '#6b7280',\n};\n\nexport function initLivePins(projId: string) {\n projectId = projId;\n currentPathname = window.location.pathname;\n\n createOverlay();\n loadPins();\n loadMembers();\n setupRealtimeListeners();\n watchNavigation();\n}\n\nexport function destroyLivePins() {\n if (container) {\n container.remove();\n container = null;\n }\n pins = [];\n}\n\nexport function togglePinMode(enabled?: boolean) {\n pinMode = enabled !== undefined ? enabled : !pinMode;\n if (container) {\n container.classList.toggle('bs-pin-mode', pinMode);\n }\n return pinMode;\n}\n\nexport function isPinModeActive() {\n return pinMode;\n}\n\n// ─── Overlay ─────────────────────────────────────────────\n\nfunction createOverlay() {\n if (container) return;\n\n container = document.createElement('div');\n container.id = 'bugstash-live-pins';\n\n const style = document.createElement('style');\n style.textContent = `\n #bugstash-live-pins {\n position: fixed;\n inset: 0;\n z-index: 2147483640;\n pointer-events: none;\n }\n #bugstash-live-pins.bs-pin-mode {\n pointer-events: auto;\n cursor: crosshair;\n }\n .bs-lp {\n position: absolute;\n pointer-events: auto;\n cursor: pointer;\n transition: transform 0.15s ease;\n }\n .bs-lp:hover { transform: scale(1.15); }\n .bs-lp-dot {\n width: 28px;\n height: 28px;\n border-radius: 50% 50% 50% 0;\n transform: rotate(-45deg);\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n border: 2px solid #fff;\n font-size: 11px;\n font-weight: 700;\n color: #fff;\n }\n .bs-lp-dot span {\n transform: rotate(45deg);\n display: block;\n }\n .bs-lp-popup {\n position: absolute;\n left: 36px;\n top: -8px;\n width: 320px;\n background: #1a1d2e;\n border: 1px solid #333754;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n z-index: 10;\n pointer-events: auto;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n color: #e2e5ed;\n overflow: hidden;\n }\n .bs-lp-popup-header {\n padding: 12px 14px;\n border-bottom: 1px solid #333754;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .bs-lp-popup-title {\n font-size: 14px;\n font-weight: 600;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .bs-lp-popup-status {\n font-size: 10px;\n padding: 2px 8px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n }\n .bs-lp-popup-body {\n padding: 12px 14px;\n font-size: 13px;\n line-height: 1.5;\n color: #a0a4b8;\n max-height: 120px;\n overflow-y: auto;\n }\n .bs-lp-popup-meta {\n padding: 8px 14px;\n font-size: 11px;\n color: #7c82a0;\n border-top: 1px solid #2a2e42;\n display: flex;\n justify-content: space-between;\n }\n .bs-lp-comments {\n max-height: 200px;\n overflow-y: auto;\n border-top: 1px solid #2a2e42;\n }\n .bs-lp-comment {\n padding: 8px 14px;\n border-bottom: 1px solid #222639;\n font-size: 12px;\n }\n .bs-lp-comment-author {\n font-weight: 600;\n color: #e2e5ed;\n margin-bottom: 2px;\n }\n .bs-lp-comment-body {\n color: #a0a4b8;\n line-height: 1.4;\n }\n .bs-lp-comment-time {\n font-size: 10px;\n color: #7c82a0;\n margin-top: 2px;\n }\n .bs-lp-input-row {\n display: flex;\n border-top: 1px solid #333754;\n }\n .bs-lp-input-row input {\n flex: 1;\n background: transparent;\n border: none;\n padding: 10px 14px;\n color: #e2e5ed;\n font-size: 13px;\n outline: none;\n }\n .bs-lp-input-row input::placeholder { color: #555; }\n .bs-lp-input-row button {\n background: linear-gradient(135deg, #6E9ED0, #8FAFD6);\n border: none;\n color: #fff;\n padding: 0 16px;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n }\n .bs-lp-input-row button:hover { opacity: 0.9; }\n .bs-lp-actions {\n padding: 8px 14px;\n display: flex;\n gap: 6px;\n border-top: 1px solid #2a2e42;\n }\n .bs-lp-btn {\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid #333754;\n background: #222639;\n color: #a0a4b8;\n font-size: 11px;\n cursor: pointer;\n }\n .bs-lp-btn:hover { background: #2a2e42; color: #e2e5ed; }\n .bs-lp-btn.resolve { border-color: #22c55e44; color: #4ade80; }\n .bs-lp-btn.resolve:hover { background: #22c55e22; }\n .bs-lp-btn.delete { border-color: #ef444444; color: #f87171; }\n .bs-lp-btn.delete:hover { background: #ef444422; }\n .bs-lp-close {\n background: none;\n border: none;\n color: #7c82a0;\n font-size: 18px;\n cursor: pointer;\n padding: 0 4px;\n line-height: 1;\n }\n .bs-lp-close:hover { color: #e2e5ed; }\n\n /* New pin form */\n .bs-lp-newform {\n position: absolute;\n width: 320px;\n background: #1a1d2e;\n border: 1px solid #333754;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n z-index: 2147483645;\n pointer-events: auto;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n color: #e2e5ed;\n padding: 14px;\n }\n .bs-lp-newform label {\n display: block;\n font-size: 11px;\n color: #7c82a0;\n margin-bottom: 4px;\n margin-top: 10px;\n font-weight: 600;\n }\n .bs-lp-newform label:first-child { margin-top: 0; }\n .bs-lp-newform input, .bs-lp-newform textarea, .bs-lp-newform select {\n width: 100%;\n background: #222639;\n border: 1px solid #333754;\n border-radius: 8px;\n padding: 8px 10px;\n color: #e2e5ed;\n font-size: 13px;\n outline: none;\n font-family: inherit;\n box-sizing: border-box;\n }\n .bs-lp-newform textarea { resize: vertical; min-height: 60px; }\n .bs-lp-newform input:focus, .bs-lp-newform textarea:focus, .bs-lp-newform select:focus {\n border-color: #6E9ED0;\n }\n .bs-lp-newform-actions {\n display: flex;\n gap: 8px;\n margin-top: 12px;\n }\n .bs-lp-newform-actions button {\n flex: 1;\n padding: 8px;\n border-radius: 8px;\n border: none;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n }\n .bs-lp-newform-submit {\n background: linear-gradient(135deg, #6E9ED0, #8FAFD6);\n color: #fff;\n }\n .bs-lp-newform-cancel {\n background: #333754;\n color: #a0a4b8;\n }\n `;\n\n container.appendChild(style);\n document.body.appendChild(container);\n\n // Click to place new pin\n container.addEventListener('click', (e) => {\n if (!pinMode) return;\n if ((e.target as HTMLElement).closest('.bs-lp, .bs-lp-popup, .bs-lp-newform')) return;\n\n const x = e.clientX + window.scrollX;\n const y = e.clientY + window.scrollY;\n\n // Find the element under the pin (peek through overlay)\n container!.style.pointerEvents = 'none';\n const el = document.elementFromPoint(e.clientX, e.clientY);\n container!.style.pointerEvents = '';\n\n showNewPinForm(x, y, el);\n });\n}\n\n// ─── Load Data ───────────────────────────────────────────\n\nasync function loadPins() {\n const result = await fetchPagePins(projectId, window.location.pathname);\n if (result.success && result.data) {\n pins = result.data;\n registerKnownPins(pins.map(p => p.id));\n renderPins();\n }\n}\n\nasync function loadMembers() {\n const result = await fetchProjectMembers(projectId);\n if (result.success && result.data) {\n members = result.data as any[];\n }\n}\n\n// ─── Render Pins ─────────────────────────────────────────\n\nfunction renderPins() {\n if (!container) return;\n\n // Remove existing pin dots (keep style element)\n container.querySelectorAll('.bs-lp').forEach((el) => el.remove());\n\n pins.forEach((pin, i) => {\n const dot = document.createElement('div');\n dot.className = 'bs-lp';\n dot.style.left = `${pin.pageX}px`;\n dot.style.top = `${pin.pageY}px`;\n dot.dataset.pinId = pin.id;\n\n const color = PIN_COLORS[pin.status] || PIN_COLORS.open;\n\n dot.innerHTML = `\n <div class=\"bs-lp-dot\" style=\"background:${color}\">\n <span>${i + 1}</span>\n </div>\n `;\n\n dot.addEventListener('click', (e) => {\n e.stopPropagation();\n showPinPopup(pin, dot);\n });\n\n container!.appendChild(dot);\n });\n}\n\n// ─── Pin Popup ───────────────────────────────────────────\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return `${hrs}h ago`;\n return `${Math.floor(hrs / 24)}d ago`;\n}\n\nfunction statusColor(status: string): string {\n const colors: Record<string, string> = {\n open: '#f97316',\n in_progress: '#3b82f6',\n resolved: '#22c55e',\n closed: '#6b7280',\n };\n return colors[status] || '#6b7280';\n}\n\nasync function showPinPopup(pin: LivePin, dotEl: HTMLDivElement) {\n closePopup();\n\n const popup = document.createElement('div');\n popup.className = 'bs-lp-popup';\n\n const commentsRes = await fetchComments(pin.id);\n const comments = commentsRes.success && commentsRes.data ? commentsRes.data : [];\n\n const user = getCurrentUser();\n const canManage = user && (user.role === 'owner' || user.role === 'admin' || user.id === pin.createdBy);\n\n popup.innerHTML = `\n <div class=\"bs-lp-popup-header\">\n <div class=\"bs-lp-popup-title\">${escapeHtml(pin.title)}</div>\n <span class=\"bs-lp-popup-status\" style=\"background:${statusColor(pin.status)}22;color:${statusColor(pin.status)}\">${pin.status.replace('_', ' ')}</span>\n <button class=\"bs-lp-close\">&times;</button>\n </div>\n ${pin.description ? `<div class=\"bs-lp-popup-body\">${escapeHtml(pin.description)}</div>` : ''}\n <div class=\"bs-lp-popup-meta\">\n <span>${pin.creatorName || 'Unknown'} &middot; ${timeAgo(pin.createdAt)}</span>\n <span>${pin.assigneeName ? `Assigned: ${pin.assigneeName}` : 'Unassigned'}</span>\n </div>\n <div class=\"bs-lp-comments\" id=\"bs-lp-comments\">\n ${comments.map((c: any) => `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(c.author?.name || c.authorName || 'Unknown')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(c.body)}</div>\n <div class=\"bs-lp-comment-time\">${timeAgo(new Date(c.createdAt).getTime())}</div>\n </div>\n `).join('')}\n </div>\n <div class=\"bs-lp-input-row\">\n <input type=\"text\" placeholder=\"Add a comment...\" id=\"bs-lp-comment-input\" />\n <button id=\"bs-lp-comment-send\">Send</button>\n </div>\n <div class=\"bs-lp-actions\">\n ${pin.status !== 'resolved'\n ? `<button class=\"bs-lp-btn resolve\" id=\"bs-lp-resolve\">Resolve</button>`\n : `<button class=\"bs-lp-btn\" id=\"bs-lp-reopen\">Reopen</button>`\n }\n ${canManage ? `<button class=\"bs-lp-btn delete\" id=\"bs-lp-delete\">Delete</button>` : ''}\n </div>\n `;\n\n dotEl.appendChild(popup);\n activePopup = popup;\n\n // Bind events\n popup.querySelector('.bs-lp-close')!.addEventListener('click', (e) => {\n e.stopPropagation();\n closePopup();\n });\n\n popup.querySelector('#bs-lp-comment-send')?.addEventListener('click', async () => {\n const input = popup.querySelector('#bs-lp-comment-input') as HTMLInputElement;\n const body = input.value.trim();\n if (!body) return;\n input.value = '';\n\n if (navigator.onLine) {\n const res = await createComment(pin.id, body);\n if (res.success && res.data) {\n const commentsEl = popup.querySelector('#bs-lp-comments')!;\n const c = res.data;\n commentsEl.innerHTML += `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(c.authorName || user?.name || 'You')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(c.body)}</div>\n <div class=\"bs-lp-comment-time\">just now</div>\n </div>\n `;\n commentsEl.scrollTop = commentsEl.scrollHeight;\n }\n } else {\n queueOfflineAction({ type: 'create_comment', data: { pinId: pin.id, body } });\n }\n });\n\n const commentInput = popup.querySelector('#bs-lp-comment-input') as HTMLInputElement;\n commentInput?.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n popup.querySelector('#bs-lp-comment-send')?.dispatchEvent(new Event('click'));\n }\n });\n\n popup.querySelector('#bs-lp-resolve')?.addEventListener('click', async () => {\n await updatePin(pin.id, { status: 'resolved' as any });\n pin.status = 'resolved';\n closePopup();\n renderPins();\n });\n\n popup.querySelector('#bs-lp-reopen')?.addEventListener('click', async () => {\n await updatePin(pin.id, { status: 'open' as any });\n pin.status = 'open';\n closePopup();\n renderPins();\n });\n\n popup.querySelector('#bs-lp-delete')?.addEventListener('click', async () => {\n if (!confirm('Delete this pin?')) return;\n await deletePin(pin.id);\n pins = pins.filter((p) => p.id !== pin.id);\n closePopup();\n renderPins();\n });\n\n // Prevent clicks inside popup from creating new pins\n popup.addEventListener('click', (e) => e.stopPropagation());\n}\n\nfunction closePopup() {\n activePopup?.remove();\n activePopup = null;\n}\n\n// ─── New Pin Form ────────────────────────────────────────\n\nfunction getSelector(el: Element | null): string {\n if (!el || el === document.body || el === document.documentElement) return 'body';\n if (el.id) return `#${el.id}`;\n let selector = el.tagName.toLowerCase();\n if (el.className && typeof el.className === 'string') {\n const classes = el.className.trim().split(/\\s+/).filter(c => !c.startsWith('bs-')).slice(0, 3);\n if (classes.length) selector += '.' + classes.join('.');\n }\n const parent = el.parentElement;\n if (parent && parent !== document.body) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === el.tagName);\n if (siblings.length > 1) {\n const idx = siblings.indexOf(el);\n selector += `:nth-child(${idx + 1})`;\n }\n return getSelector(parent) + ' > ' + selector;\n }\n return selector;\n}\n\nfunction getXPath(el: Element | null): string {\n if (!el) return '';\n const parts: string[] = [];\n let current: Element | null = el;\n while (current && current !== document.body) {\n let idx = 1;\n let sib = current.previousElementSibling;\n while (sib) {\n if (sib.tagName === current.tagName) idx++;\n sib = sib.previousElementSibling;\n }\n parts.unshift(`${current.tagName.toLowerCase()}[${idx}]`);\n current = current.parentElement;\n }\n return '/body/' + parts.join('/');\n}\n\nfunction showNewPinForm(pageX: number, pageY: number, targetEl: Element | null) {\n closePopup();\n container?.querySelectorAll('.bs-lp-newform').forEach(e => e.remove());\n\n const form = document.createElement('div');\n form.className = 'bs-lp-newform';\n form.style.left = `${pageX + 16}px`;\n form.style.top = `${pageY - 8}px`;\n\n // Ensure form stays in viewport\n requestAnimationFrame(() => {\n const rect = form.getBoundingClientRect();\n if (rect.right > window.innerWidth - 16) {\n form.style.left = `${pageX - 336}px`;\n }\n if (rect.bottom > window.innerHeight - 16) {\n form.style.top = `${pageY - rect.height}px`;\n }\n });\n\n const memberOptions = members\n .filter(m => (m as any).userId !== getCurrentUser()?.id)\n .map(m => `<option value=\"${(m as any).userId}\">${escapeHtml((m as any).name)}</option>`)\n .join('');\n\n form.innerHTML = `\n <label>Title *</label>\n <input type=\"text\" id=\"bs-np-title\" placeholder=\"What's the issue?\" autofocus />\n <label>Description</label>\n <textarea id=\"bs-np-desc\" placeholder=\"Describe the problem...\"></textarea>\n <label>Priority</label>\n <select id=\"bs-np-priority\">\n <option value=\"low\">Low</option>\n <option value=\"medium\" selected>Medium</option>\n <option value=\"high\">High</option>\n <option value=\"critical\">Critical</option>\n </select>\n <label>Category</label>\n <select id=\"bs-np-category\">\n <option value=\"ui\">UI</option>\n <option value=\"functionality\">Functionality</option>\n <option value=\"performance\">Performance</option>\n <option value=\"content\">Content</option>\n <option value=\"other\" selected>Other</option>\n </select>\n ${memberOptions ? `\n <label>Assign to</label>\n <select id=\"bs-np-assignee\">\n <option value=\"\">Unassigned</option>\n ${memberOptions}\n </select>\n ` : ''}\n <div class=\"bs-lp-newform-actions\">\n <button class=\"bs-lp-newform-cancel\" id=\"bs-np-cancel\">Cancel</button>\n <button class=\"bs-lp-newform-submit\" id=\"bs-np-submit\">Create Pin</button>\n </div>\n `;\n\n container!.appendChild(form);\n\n form.addEventListener('click', (e) => e.stopPropagation());\n\n form.querySelector('#bs-np-cancel')!.addEventListener('click', () => form.remove());\n\n form.querySelector('#bs-np-submit')!.addEventListener('click', async () => {\n const title = (form.querySelector('#bs-np-title') as HTMLInputElement).value.trim();\n if (!title) {\n (form.querySelector('#bs-np-title') as HTMLInputElement).style.borderColor = '#ef4444';\n return;\n }\n\n const desc = (form.querySelector('#bs-np-desc') as HTMLTextAreaElement).value.trim();\n const priority = (form.querySelector('#bs-np-priority') as HTMLSelectElement).value;\n const category = (form.querySelector('#bs-np-category') as HTMLSelectElement).value;\n const assigneeEl = form.querySelector('#bs-np-assignee') as HTMLSelectElement;\n const assigneeId = assigneeEl?.value || undefined;\n\n const selector = getSelector(targetEl);\n const xpath = getXPath(targetEl);\n\n // Capture context\n const logs = getLogs().slice(-20).map(l => `[${l.level}] ${l.args.join(' ')}`);\n const errors = getErrors().slice(-10).map(e => `${e.message} at ${e.source}:${e.lineno}`);\n const netErrors = getFailedNetworkCaptures().slice(-10).map(n => `${n.method} ${n.url} → ${n.status}`);\n\n // Take screenshot\n let screenshot: string | undefined;\n try {\n form.style.display = 'none';\n container!.style.display = 'none';\n screenshot = await captureScreenshot() ?? undefined;\n container!.style.display = '';\n form.style.display = '';\n } catch { /* no screenshot */ }\n\n const pinData = {\n projectId,\n pageUrl: window.location.href,\n pathname: window.location.pathname,\n elementSelector: selector,\n elementXPath: xpath,\n xPercent: 0,\n yPercent: 0,\n pageX,\n pageY,\n title,\n description: desc,\n screenshot,\n priority: priority as 'low' | 'medium' | 'high' | 'critical',\n category: category as 'ui' | 'functionality' | 'performance' | 'content' | 'other',\n assigneeId,\n browserInfo: navigator.userAgent,\n screenSize: `${screen.width}x${screen.height}`,\n viewportSize: `${window.innerWidth}x${window.innerHeight}`,\n devicePixelRatio: window.devicePixelRatio,\n consoleLogs: logs,\n networkErrors: netErrors,\n jsErrors: errors,\n };\n\n form.remove();\n\n if (navigator.onLine) {\n const res = await createPin(pinData);\n if (res.success && res.data) {\n pins.push(res.data);\n renderPins();\n }\n } else {\n // Queue for later\n queueOfflineAction({ type: 'create_pin', data: pinData });\n // Optimistic local pin\n pins.push({\n ...pinData,\n id: 'local-' + Date.now(),\n orgId: '',\n status: 'open',\n tags: [],\n createdById: getCurrentUser()?.id || '',\n creatorName: getCurrentUser()?.name || '',\n commentCount: 0,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n } as any);\n renderPins();\n }\n });\n\n // Focus title input\n setTimeout(() => (form.querySelector('#bs-np-title') as HTMLInputElement)?.focus(), 50);\n}\n\n// ─── Real-time Updates ───────────────────────────────────\n\nfunction setupRealtimeListeners() {\n onRealtimeEvent('pin:created', (event) => {\n const pin = event.data as LivePin;\n if (pin.pathname === window.location.pathname) {\n // Don't duplicate if we created it\n if (!pins.find(p => p.id === pin.id)) {\n pins.push(pin);\n renderPins();\n }\n }\n });\n\n onRealtimeEvent('pin:updated', (event) => {\n const updated = event.data as LivePin;\n const idx = pins.findIndex(p => p.id === updated.id);\n if (idx >= 0) {\n pins[idx] = { ...pins[idx], ...updated };\n renderPins();\n }\n });\n\n onRealtimeEvent('pin:deleted', (event) => {\n const { id } = event.data;\n pins = pins.filter(p => p.id !== id);\n closePopup();\n renderPins();\n });\n\n onRealtimeEvent('comment:created', (event) => {\n // If popup is open for this pin, add the comment\n const comment = event.data;\n if (activePopup) {\n const commentsEl = activePopup.querySelector('#bs-lp-comments');\n if (commentsEl) {\n commentsEl.innerHTML += `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(comment.author?.name || 'Someone')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(comment.body)}</div>\n <div class=\"bs-lp-comment-time\">just now</div>\n </div>\n `;\n commentsEl.scrollTop = commentsEl.scrollHeight;\n }\n }\n });\n}\n\n// ─── Navigation Watch ────────────────────────────────────\n\nfunction watchNavigation() {\n // Watch for SPA navigation\n let lastPath = window.location.pathname;\n\n const check = () => {\n if (window.location.pathname !== lastPath) {\n lastPath = window.location.pathname;\n sendPageNavigate(window.location.href);\n loadPins(); // Reload pins for new page\n }\n };\n\n // Intercept pushState/replaceState\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n\n history.pushState = function (...args) {\n origPush.apply(this, args);\n check();\n };\n\n history.replaceState = function (...args) {\n origReplace.apply(this, args);\n check();\n };\n\n window.addEventListener('popstate', check);\n}\n\n// ─── Util ────────────────────────────────────────────────\n\nfunction escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n","import type { BugStashConfig, BugReport, ReportContext } from '@bugstash/shared';\nimport { getLogs } from './logger';\nimport { getNetworkCaptures, getFailedNetworkCaptures } from './network';\nimport { getErrors } from './errors';\nimport { getBreadcrumbs } from './breadcrumbs';\nimport { getPerformanceMetrics } from './performance';\nimport { captureScreenshot } from './screenshot';\nimport { submitReport, login as apiLogin, getCurrentUser, logout as apiLogout } from './api';\nimport { getDefaultTheme, getThemeById, getThemes, type BsTheme } from './themes';\nimport { getDefaultLayout, getLayoutById, getLayouts, LAYOUT_CSS, type BsLayout } from './layouts';\nimport { initLivePins, togglePinMode, isPinModeActive } from './livepins';\nimport { connectRealtime } from './realtime';\n\nlet config: BugStashConfig;\nlet fab: HTMLButtonElement | null = null;\nlet toolbar: HTMLDivElement | null = null;\nlet modal: HTMLDivElement | null = null;\nlet backdrop: HTMLDivElement | null = null;\nlet styleEl: HTMLStyleElement | null = null;\nlet keyHandler: ((e: KeyboardEvent) => void) | null = null;\nlet isOpen = false;\nlet toolbarVisible = false;\nlet activeTab: 'report' | 'console' | 'network' | 'context' | 'history' | 'settings' = 'report';\nlet editingReportId: number | null = null;\nlet currentTheme: BsTheme = getDefaultTheme();\nlet currentLayout: BsLayout = getDefaultLayout();\n\n// ─── Icons ───────────────────────────────────────────────\n\nconst I = {\n bug: `<svg width=\"28\" height=\"28\" viewBox=\"55 38 60 105\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M95.8 44h-29c-3 0-5.4 2.4-5.4 5.4v29c0 3 2.4 5.4 5.4 5.4h19.5c13 0 23.5-10.5 23.5-23.5v-2.8c0-7.5-6-13.5-13.5-13.5h-.5zm-6.2 28.2H74.8V57.4h14.8c5.8 0 10.4 4.7 10.4 10.4s-4.7 10.4-10.4 10.4z\" fill=\"rgba(255,255,255,0.85)\"/><path d=\"M100.4 96h-33.6c-3 0-5.4 2.4-5.4 5.4v33.6c0 3 2.4 5.4 5.4 5.4h22c15 0 27-12 27-27v-3.9c0-7.5-6-13.5-13.5-13.5h-1.9zm-7.8 32.2H74.8v-20h17.8c6.7 0 12.2 5.5 12.2 12.2 0 4.3-3.5 7.8-7.8 7.8h-4.6z\" fill=\"rgba(255,255,255,1)\"/></svg>`,\n x: `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n cam: `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\"/><circle cx=\"12\" cy=\"13\" r=\"4\"/></svg>`,\n check: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n report: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/></svg>`,\n console: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"4 17 10 11 4 5\"/><line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\"/></svg>`,\n network: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"/><path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"/></svg>`,\n ctx: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"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 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n settings: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"21\" x2=\"4\" y2=\"14\"/><line x1=\"4\" y1=\"10\" x2=\"4\" y2=\"3\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"3\"/><line x1=\"20\" y1=\"21\" x2=\"20\" y2=\"16\"/><line x1=\"20\" y1=\"12\" x2=\"20\" y2=\"3\"/><line x1=\"1\" y1=\"14\" x2=\"7\" y2=\"14\"/><line x1=\"9\" y1=\"8\" x2=\"15\" y2=\"8\"/><line x1=\"17\" y1=\"16\" x2=\"23\" y2=\"16\"/></svg>`,\n history: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/></svg>`,\n pin: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>`,\n sun: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><circle cx=\"12\" cy=\"12\" r=\"5\"/><line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\"/><line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\"/><line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\"/><line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\"/><line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\"/><line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\"/></svg>`,\n moon: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/></svg>`,\n keyboard: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/><line x1=\"6\" y1=\"8\" x2=\"6\" y2=\"8\"/><line x1=\"10\" y1=\"8\" x2=\"10\" y2=\"8\"/><line x1=\"14\" y1=\"8\" x2=\"14\" y2=\"8\"/><line x1=\"18\" y1=\"8\" x2=\"18\" y2=\"8\"/><line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\"/><line x1=\"6\" y1=\"16\" x2=\"18\" y2=\"16\"/></svg>`,\n};\n\n// ─── Styles (CSS custom properties) ──────────────────────\n\nconst STYLES = `\n @import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@400;600;700&family=Inter:wght@300;400;500;600;700&display=swap');\n\n /* ── FAB ── */\n .bs-fab {\n all: unset;\n position: fixed;\n bottom: 24px;\n z-index: 2147483647;\n width: 56px;\n height: 56px;\n border-radius: var(--bs-radius);\n background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff;\n cursor: pointer;\n box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 0 rgba(0,0,0,0.15);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.35s cubic-bezier(0.34,1.56,0.64,1);\n animation: bs-pulse 3s ease-in-out infinite;\n }\n .bs-fab:hover {\n transform: scale(1.08) translateY(-2px);\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: none;\n }\n .bs-fab:active { transform: scale(0.95); }\n .bs-fab.bs-open {\n animation: none;\n transform: rotate(45deg) scale(0.9);\n box-shadow: 0 2px 12px rgba(0,0,0,0.3);\n }\n .bs-fab.bs-open:hover { transform: rotate(45deg) scale(1); }\n @keyframes bs-pulse {\n 0%, 100% { box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 0 rgba(0,0,0,0.15); }\n 50% { box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 10px rgba(0,0,0,0); }\n }\n .bs-fab-label {\n position: absolute;\n right: calc(100% + 12px);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-family: 'Inter', sans-serif;\n font-size: 13px;\n font-weight: 500;\n padding: 8px 14px;\n border-radius: var(--bs-radius-sm);\n white-space: nowrap;\n box-shadow: 0 4px 20px rgba(0,0,0,0.3);\n opacity: 0;\n transform: translateX(8px);\n transition: all 0.25s ease;\n pointer-events: none;\n }\n .bs-fab:hover .bs-fab-label { opacity: 1; transform: translateX(0); }\n .bs-fab-label::after {\n content: '';\n position: absolute;\n right: -6px;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-left-color: var(--bs-bg2);\n border-right: none;\n }\n\n /* ── Quick Action Toolbar ── */\n .bs-toolbar {\n position: fixed;\n z-index: 2147483646;\n display: flex;\n flex-direction: column;\n gap: 6px;\n bottom: 88px;\n opacity: 0;\n transform: translateY(10px);\n transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1);\n pointer-events: none;\n }\n .bs-toolbar.bs-show {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n }\n .bs-toolbar-btn {\n all: unset;\n width: 40px;\n height: 40px;\n border-radius: var(--bs-radius-sm);\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n color: var(--bs-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n position: relative;\n box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n }\n .bs-toolbar-btn:hover { color: var(--bs-text); border-color: var(--bs-accent); background: var(--bs-bg3); }\n .bs-toolbar-btn.bs-active { color: var(--bs-accent); border-color: var(--bs-accent); }\n .bs-toolbar-tip {\n position: absolute;\n right: calc(100% + 8px);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-family: 'Inter', sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 4px 8px;\n border-radius: 6px;\n white-space: nowrap;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n .bs-toolbar-btn:hover .bs-toolbar-tip { opacity: 1; }\n .bs-toolbar-kbd {\n font-size: 9px;\n color: var(--bs-muted);\n margin-left: 4px;\n }\n\n /* ── Backdrop ── */\n .bs-backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483644;\n background: rgba(0,0,0,0);\n backdrop-filter: blur(0px);\n transition: all 0.4s ease;\n pointer-events: none;\n }\n .bs-backdrop.bs-in {\n background: rgba(10,12,20,0.55);\n backdrop-filter: blur(6px);\n pointer-events: all;\n }\n\n /* ── Modal ── */\n .bs-modal {\n position: fixed;\n z-index: 2147483645;\n top: 50%;\n left: 50%;\n width: 620px;\n height: 680px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 48px);\n background: var(--bs-bg);\n border: 1px solid var(--bs-border);\n border-radius: var(--bs-radius);\n box-shadow: 0 32px 80px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.03) inset;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: 'Inter', -apple-system, sans-serif;\n transform: translate(-50%, -50%) scale(0.88);\n opacity: 0;\n transition: transform 0.4s cubic-bezier(0.34,1.56,0.64,1),\n opacity 0.3s ease,\n width 0.35s cubic-bezier(0.25,1,0.5,1),\n height 0.35s cubic-bezier(0.25,1,0.5,1);\n }\n .bs-modal.bs-in {\n transform: translate(-50%, -50%) scale(1);\n opacity: 1;\n }\n .bs-modal.bs-out {\n transform: translate(-50%, -50%) scale(0.85);\n opacity: 0;\n transition: transform 0.3s cubic-bezier(0.4,0,1,1), opacity 0.25s ease;\n }\n\n /* ── Header ── */\n .bs-hdr {\n padding: 18px 22px 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n }\n .bs-logo {\n font-family: 'Comfortaa', cursive;\n font-weight: 700;\n font-size: 18px;\n background: linear-gradient(135deg, var(--bs-accent), #fff);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n }\n .bs-hdr-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .bs-pin-toggle {\n all: unset;\n cursor: pointer;\n padding: 5px 10px;\n border-radius: var(--bs-radius-sm);\n font-size: 11px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n color: var(--bs-muted);\n border: 1px solid var(--bs-border);\n transition: all 0.2s;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n .bs-pin-toggle:hover { color: var(--bs-text); border-color: var(--bs-accent); }\n .bs-pin-toggle.active {\n background: var(--bs-accent);\n color: #fff;\n border-color: var(--bs-accent);\n -webkit-text-fill-color: #fff;\n }\n .bs-user-badge {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--bs-muted);\n font-family: 'Inter', sans-serif;\n }\n .bs-user-avatar {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--bs-accent), var(--bs-accent2));\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n color: #fff;\n }\n .bs-login-form {\n padding: 32px 24px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n }\n .bs-login-logo {\n font-family: 'Comfortaa', cursive;\n font-weight: 700;\n font-size: 28px;\n background: linear-gradient(135deg, var(--bs-accent), #fff);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 4px;\n }\n .bs-login-subtitle {\n font-size: 13px;\n color: var(--bs-muted);\n margin-bottom: 8px;\n }\n .bs-login-input {\n width: 100%;\n max-width: 300px;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm);\n border: 1px solid var(--bs-border);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-size: 13px;\n font-family: 'Inter', sans-serif;\n outline: none;\n transition: border-color 0.2s;\n box-sizing: border-box;\n }\n .bs-login-input:focus { border-color: var(--bs-accent); }\n .bs-login-input::placeholder { color: var(--bs-muted); opacity: 0.6; }\n .bs-login-btn {\n width: 100%;\n max-width: 300px;\n padding: 10px;\n border-radius: var(--bs-radius-sm);\n border: none;\n background: linear-gradient(135deg, var(--bs-accent), var(--bs-accent2));\n color: #fff;\n font-size: 14px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: opacity 0.2s;\n }\n .bs-login-btn:hover { opacity: 0.9; }\n .bs-login-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n .bs-login-error {\n font-size: 12px;\n color: var(--bs-red);\n max-width: 300px;\n text-align: center;\n }\n .bs-login-logout {\n all: unset;\n cursor: pointer;\n font-size: 11px;\n color: var(--bs-muted);\n font-family: 'Inter', sans-serif;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s;\n }\n .bs-login-logout:hover { color: var(--bs-red); }\n .bs-close-btn {\n all: unset;\n cursor: pointer;\n color: var(--bs-muted);\n padding: 6px;\n border-radius: var(--bs-radius-sm);\n display: flex;\n transition: all 0.2s;\n }\n .bs-close-btn:hover { color: var(--bs-text); background: var(--bs-bg3); }\n\n /* ── Tabs ── */\n .bs-tabs {\n display: flex;\n gap: 2px;\n padding: 12px 22px 0;\n position: relative;\n flex-shrink: 0;\n }\n .bs-tab {\n all: unset;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm) var(--bs-radius-sm) 0 0;\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n font-weight: 600;\n color: var(--bs-muted);\n transition: all 0.25s ease;\n position: relative;\n }\n .bs-tab:hover { color: var(--bs-text); background: var(--bs-bg2); }\n .bs-tab.bs-active {\n color: var(--bs-accent);\n background: var(--bs-bg2);\n }\n .bs-tab.bs-active::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--bs-accent);\n border-radius: 2px 2px 0 0;\n animation: bs-tabIn 0.25s ease;\n }\n @keyframes bs-tabIn { from { transform: scaleX(0); } to { transform: scaleX(1); } }\n .bs-tab-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 1px 6px;\n border-radius: 10px;\n background: var(--bs-bg3);\n color: var(--bs-muted);\n line-height: 1.4;\n }\n .bs-tab.bs-active .bs-tab-badge { background: var(--bs-accent); color: #fff; }\n .bs-tab-badge.bs-warn { background: var(--bs-red); color: #fff; }\n .bs-tab-divider {\n height: 1px;\n background: var(--bs-border);\n flex-shrink: 0;\n }\n\n /* ── Scrollable Body ── */\n .bs-scroll {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px 22px 22px;\n overscroll-behavior: contain;\n }\n .bs-scroll::-webkit-scrollbar { width: 5px; }\n .bs-scroll::-webkit-scrollbar-track { background: transparent; }\n .bs-scroll::-webkit-scrollbar-thumb { background: var(--bs-border); border-radius: 4px; }\n\n /* ── View slide animation ── */\n .bs-view { animation: bs-slideUp 0.3s cubic-bezier(0.22,1,0.36,1); }\n @keyframes bs-slideUp {\n from { opacity: 0; transform: translateY(12px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* ── Form ── */\n .bs-field { margin-bottom: 16px; }\n .bs-field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--bs-text);\n margin-bottom: 7px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .bs-field-hint { font-size: 11px; font-weight: 400; color: var(--bs-muted); }\n .bs-input, .bs-textarea {\n width: 100%;\n padding: 11px 14px;\n border: 1.5px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n font-size: 14px;\n font-family: 'Inter', sans-serif;\n background: var(--bs-bg2);\n color: var(--bs-text);\n box-sizing: border-box;\n transition: all 0.2s ease;\n -webkit-appearance: none;\n }\n .bs-input::placeholder, .bs-textarea::placeholder { color: var(--bs-muted); opacity: 0.5; }\n .bs-input:focus, .bs-textarea:focus {\n outline: none;\n border-color: var(--bs-accent);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-accent) 15%, transparent);\n }\n .bs-textarea { resize: vertical; min-height: 76px; line-height: 1.5; }\n /* ── Severity ── */\n .bs-sev-row { display: flex; gap: 8px; }\n .bs-sev-btn {\n all: unset;\n flex: 1;\n padding: 10px 0;\n border-radius: var(--bs-radius-sm);\n text-align: center;\n font-size: 12px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n }\n .bs-sev-btn.bs-sev-low { background: color-mix(in srgb, var(--bs-green) 8%, transparent); color: var(--bs-green); border: 1.5px solid color-mix(in srgb, var(--bs-green) 15%, transparent); }\n .bs-sev-btn.bs-sev-medium { background: color-mix(in srgb, var(--bs-yellow) 8%, transparent); color: var(--bs-yellow); border: 1.5px solid color-mix(in srgb, var(--bs-yellow) 15%, transparent); }\n .bs-sev-btn.bs-sev-high { background: color-mix(in srgb, var(--bs-orange) 8%, transparent); color: var(--bs-orange); border: 1.5px solid color-mix(in srgb, var(--bs-orange) 15%, transparent); }\n .bs-sev-btn.bs-sev-critical { background: color-mix(in srgb, var(--bs-red) 8%, transparent); color: var(--bs-red); border: 1.5px solid color-mix(in srgb, var(--bs-red) 15%, transparent); }\n .bs-sev-btn:hover { transform: translateY(-1px); }\n .bs-sev-btn:active { transform: scale(0.96); }\n .bs-sev-btn.bs-picked { box-shadow: 0 0 0 2px currentColor; transform: translateY(-1px); }\n .bs-sev-btn.bs-picked::after {\n content: '';\n position: absolute;\n top: 4px;\n right: 6px;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n animation: bs-pop 0.3s cubic-bezier(0.34,1.56,0.64,1);\n }\n @keyframes bs-pop { from { transform: scale(0); } to { transform: scale(1); } }\n\n /* ── Screenshot ── */\n .bs-shot-area {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n background: var(--bs-bg2);\n border: 1.5px dashed var(--bs-border);\n border-radius: var(--bs-radius-sm);\n margin-bottom: 16px;\n cursor: pointer;\n transition: all 0.25s ease;\n }\n .bs-shot-area:hover { border-color: var(--bs-accent); border-style: solid; background: var(--bs-bg3); }\n .bs-shot-area:active { transform: scale(0.98); }\n .bs-shot-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--bs-radius-sm);\n background: color-mix(in srgb, var(--bs-accent) 12%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bs-accent);\n flex-shrink: 0;\n }\n .bs-shot-text { flex: 1; }\n .bs-shot-title { font-size: 13px; font-weight: 600; color: var(--bs-text); }\n .bs-shot-sub { font-size: 11px; color: var(--bs-muted); margin-top: 2px; }\n .bs-shot-area.bs-captured { border-style: solid; border-color: var(--bs-green); }\n .bs-shot-area.bs-captured .bs-shot-icon { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n\n /* ── Category Chips ── */\n .bs-cat-row { display: flex; flex-wrap: wrap; gap: 6px; }\n .bs-cat-btn {\n all: unset;\n padding: 7px 14px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--bs-bg2);\n color: var(--bs-muted);\n border: 1.5px solid var(--bs-border);\n }\n .bs-cat-btn:hover { color: var(--bs-text); border-color: var(--bs-accent); }\n .bs-cat-btn.bs-picked {\n background: color-mix(in srgb, var(--bs-accent) 12%, transparent);\n color: var(--bs-accent);\n border-color: var(--bs-accent);\n }\n\n /* ── Context Bar ── */\n .bs-ctx-bar {\n display: flex;\n gap: 2px;\n margin-bottom: 16px;\n background: var(--bs-bg2);\n border-radius: var(--bs-radius-sm);\n padding: 3px;\n border: 1px solid var(--bs-border);\n }\n .bs-ctx-chip {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n padding: 8px 4px;\n border-radius: calc(var(--bs-radius-sm) - 2px);\n transition: background 0.2s;\n }\n .bs-ctx-chip.bs-has { background: var(--bs-bg3); }\n .bs-ctx-chip.bs-alert { background: color-mix(in srgb, var(--bs-red) 8%, transparent); }\n .bs-ctx-n {\n font-size: 15px;\n font-weight: 700;\n color: var(--bs-text);\n line-height: 1;\n }\n .bs-ctx-chip.bs-alert .bs-ctx-n { color: var(--bs-red); }\n .bs-ctx-l {\n font-size: 9px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n color: var(--bs-muted);\n }\n\n /* ── Report Summary Bar ── */\n .bs-report-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm);\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n margin-bottom: 16px;\n font-size: 12px;\n color: var(--bs-muted);\n }\n .bs-report-summary.bs-alert {\n background: color-mix(in srgb, var(--bs-red) 6%, transparent);\n border-color: color-mix(in srgb, var(--bs-red) 15%, transparent);\n color: var(--bs-red);\n }\n .bs-report-summary.bs-has { color: var(--bs-text); }\n .bs-report-summary-left { display: flex; align-items: center; gap: 8px; }\n .bs-report-summary-icon {\n width: 22px; height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--bs-green) 12%, transparent);\n color: var(--bs-green);\n display: flex; align-items: center; justify-content: center;\n font-size: 10px; flex-shrink: 0;\n }\n .bs-report-summary-icon.bs-warn {\n background: color-mix(in srgb, var(--bs-red) 12%, transparent);\n color: var(--bs-red);\n font-weight: 800; font-size: 12px;\n }\n .bs-input-title {\n font-size: 16px !important;\n font-weight: 600;\n padding: 14px !important;\n }\n .bs-report-row {\n display: flex;\n gap: 16px;\n margin-bottom: 16px;\n }\n .bs-report-col { flex: 1; }\n .bs-cat-icon { margin-right: 2px; }\n\n .bs-auto-step-n {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--bs-accent) 15%, transparent);\n color: var(--bs-accent);\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n .bs-auto-muted {\n font-size: 12px;\n color: var(--bs-muted);\n padding: 6px 0;\n }\n\n /* ── Submit ── */\n .bs-submit-btn {\n all: unset;\n width: 100%;\n padding: 14px;\n background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff;\n border-radius: var(--bs-radius-sm);\n font-size: 15px;\n font-weight: 700;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n text-align: center;\n box-sizing: border-box;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n .bs-submit-btn:hover { box-shadow: 0 8px 28px rgba(0,0,0,0.3); transform: translateY(-1px); }\n .bs-submit-btn:active { transform: translateY(0) scale(0.98); }\n .bs-submit-btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none !important; box-shadow: none !important; }\n\n .bs-msg {\n text-align: center;\n padding: 12px;\n border-radius: var(--bs-radius-sm);\n font-size: 13px;\n font-weight: 600;\n margin-top: 12px;\n animation: bs-slideUp 0.3s ease;\n }\n .bs-msg-ok { background: color-mix(in srgb, var(--bs-green) 10%, transparent); color: var(--bs-green); border: 1px solid color-mix(in srgb, var(--bs-green) 15%, transparent); }\n .bs-msg-err { background: color-mix(in srgb, var(--bs-red) 10%, transparent); color: var(--bs-red); border: 1px solid color-mix(in srgb, var(--bs-red) 15%, transparent); }\n\n /* ── Console ── */\n .bs-log {\n padding: 8px 10px;\n border-radius: var(--bs-radius-sm);\n margin-bottom: 4px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11.5px;\n line-height: 1.5;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n transition: background 0.15s;\n }\n .bs-log:hover { background: var(--bs-bg2); }\n .bs-log-lv {\n font-weight: 700;\n text-transform: uppercase;\n font-size: 9px;\n padding: 3px 6px;\n border-radius: 5px;\n flex-shrink: 0;\n margin-top: 2px;\n letter-spacing: 0.4px;\n }\n .bs-log-lv.bs-le { background: color-mix(in srgb, var(--bs-red) 12%, transparent); color: var(--bs-red); }\n .bs-log-lv.bs-lw { background: color-mix(in srgb, var(--bs-orange) 10%, transparent); color: var(--bs-orange); }\n .bs-log-lv.bs-ll { background: var(--bs-bg3); color: var(--bs-muted); }\n .bs-log-lv.bs-li { background: color-mix(in srgb, var(--bs-accent) 10%, transparent); color: var(--bs-accent); }\n .bs-log-lv.bs-ld { background: var(--bs-bg2); color: var(--bs-muted); }\n .bs-log-m { color: var(--bs-text); word-break: break-word; flex: 1; white-space: pre-wrap; }\n .bs-log-t { color: var(--bs-muted); opacity: 0.5; flex-shrink: 0; font-size: 10px; margin-top: 3px; }\n\n /* ── Network ── */\n .bs-net {\n padding: 9px 10px;\n border-radius: var(--bs-radius-sm);\n margin-bottom: 4px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11.5px;\n display: flex;\n gap: 8px;\n align-items: center;\n transition: background 0.15s;\n }\n .bs-net:hover { background: var(--bs-bg2); }\n .bs-net-m { font-weight: 700; font-size: 10px; color: var(--bs-accent); flex-shrink: 0; width: 34px; }\n .bs-net-s { font-weight: 700; font-size: 10px; padding: 3px 7px; border-radius: 5px; flex-shrink: 0; }\n .bs-net-s.bs-ok { background: color-mix(in srgb, var(--bs-green) 10%, transparent); color: var(--bs-green); }\n .bs-net-s.bs-fail { background: color-mix(in srgb, var(--bs-red) 10%, transparent); color: var(--bs-red); }\n .bs-net-u { color: var(--bs-text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .bs-net-d { color: var(--bs-muted); opacity: 0.5; flex-shrink: 0; font-size: 10px; }\n\n /* ── Context: Errors ── */\n .bs-err-card {\n padding: 12px 14px;\n margin-bottom: 8px;\n background: color-mix(in srgb, var(--bs-red) 6%, transparent);\n border: 1px solid color-mix(in srgb, var(--bs-red) 10%, transparent);\n border-radius: var(--bs-radius-sm);\n transition: border-color 0.2s;\n }\n .bs-err-card:hover { border-color: color-mix(in srgb, var(--bs-red) 20%, transparent); }\n .bs-err-m { color: var(--bs-red); font-weight: 600; font-size: 13px; margin-bottom: 6px; line-height: 1.4; }\n .bs-err-stack {\n font-family: 'SF Mono', monospace;\n font-size: 10px;\n color: var(--bs-muted);\n white-space: pre-wrap;\n max-height: 72px;\n overflow-y: auto;\n line-height: 1.5;\n }\n .bs-err-meta { font-size: 10px; color: var(--bs-muted); margin-top: 6px; }\n\n /* ── Context: Section Title ── */\n .bs-sec {\n font-size: 10px;\n font-weight: 700;\n color: var(--bs-accent);\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin: 20px 0 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--bs-border);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .bs-sec:first-child { margin-top: 0; }\n .bs-sec-n {\n background: var(--bs-bg3);\n color: var(--bs-muted);\n font-size: 9px;\n padding: 2px 6px;\n border-radius: 5px;\n }\n\n /* ── KV Grid ── */\n .bs-kv {\n display: grid;\n grid-template-columns: 100px 1fr;\n gap: 7px 12px;\n font-size: 12px;\n }\n .bs-kv-k { color: var(--bs-muted); font-size: 11px; }\n .bs-kv-v { color: var(--bs-text); word-break: break-all; font-size: 11px; }\n\n /* ── Breadcrumbs ── */\n .bs-bc {\n padding: 7px 10px;\n border-radius: 8px;\n margin-bottom: 3px;\n font-size: 11px;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n transition: background 0.15s;\n }\n .bs-bc:hover { background: var(--bs-bg2); }\n .bs-bc-t {\n font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;\n padding: 3px 6px; border-radius: 5px; flex-shrink: 0;\n background: var(--bs-bg3); color: var(--bs-muted);\n }\n .bs-bc-t.bs-t-click { color: var(--bs-accent); background: color-mix(in srgb, var(--bs-accent) 10%, transparent); }\n .bs-bc-t.bs-t-input { color: var(--bs-green); background: color-mix(in srgb, var(--bs-green) 10%, transparent); }\n .bs-bc-t.bs-t-navigation { color: var(--bs-accent2); background: color-mix(in srgb, var(--bs-accent2) 10%, transparent); }\n .bs-bc-t.bs-t-error { color: var(--bs-red); background: color-mix(in srgb, var(--bs-red) 10%, transparent); }\n .bs-bc-t.bs-t-network { color: var(--bs-orange); background: color-mix(in srgb, var(--bs-orange) 10%, transparent); }\n .bs-bc-t.bs-t-console { color: var(--bs-yellow); background: color-mix(in srgb, var(--bs-yellow) 10%, transparent); }\n .bs-bc-t.bs-t-custom { color: var(--bs-accent); background: color-mix(in srgb, var(--bs-accent) 10%, transparent); }\n .bs-bc-m { color: var(--bs-text); flex: 1; line-height: 1.4; }\n .bs-bc-time { color: var(--bs-muted); opacity: 0.5; font-size: 10px; flex-shrink: 0; }\n\n /* ── Performance ── */\n .bs-pf { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }\n .bs-pf-l { font-size: 11px; color: var(--bs-muted); width: 85px; flex-shrink: 0; }\n .bs-pf-tr { flex: 1; height: 6px; background: var(--bs-bg3); border-radius: 4px; overflow: hidden; }\n .bs-pf-fl { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--bs-accent), var(--bs-accent2)); transition: width 0.6s cubic-bezier(0.34,1.56,0.64,1); }\n .bs-pf-fl.bs-slow { background: linear-gradient(90deg, var(--bs-orange), var(--bs-red)); }\n .bs-pf-v { font-size: 11px; font-weight: 600; color: var(--bs-text); width: 55px; text-align: right; flex-shrink: 0; }\n\n /* ── Annotation ── */\n .bs-ann-wrap { position: relative; margin-bottom: 16px; border-radius: var(--bs-radius-sm); overflow: hidden; border: 1.5px solid var(--bs-border); animation: bs-slideUp 0.3s ease; }\n .bs-ann-viewport { overflow: hidden; position: relative; }\n .bs-ann-canvas { display: block; width: 100%; transform-origin: 0 0; transition: transform 0.15s ease; }\n .bs-ann-canvas.bs-select { cursor: default; }\n .bs-ann-canvas.bs-draw { cursor: crosshair; }\n .bs-ann-canvas.bs-arrow { cursor: crosshair; }\n .bs-ann-canvas.bs-rect { cursor: crosshair; }\n .bs-ann-canvas.bs-circle { cursor: crosshair; }\n .bs-ann-canvas.bs-text { cursor: text; }\n .bs-ann-canvas.bs-highlight { cursor: crosshair; }\n .bs-ann-canvas.bs-grab { cursor: grab; }\n .bs-ann-canvas.bs-grabbing { cursor: grabbing; }\n .bs-ann-toolbar { display: flex; gap: 2px; padding: 6px 8px; background: var(--bs-bg2); border-top: 1px solid var(--bs-border); align-items: center; flex-wrap: wrap; }\n .bs-ann-sep { width: 1px; height: 20px; background: var(--bs-border); margin: 0 4px; flex-shrink: 0; }\n .bs-ann-btn {\n all: unset; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;\n border-radius: 6px; cursor: pointer; color: var(--bs-muted); transition: all 0.15s; font-size: 14px;\n }\n .bs-ann-btn:hover { background: var(--bs-bg3); color: var(--bs-text); }\n .bs-ann-btn.bs-sel { background: color-mix(in srgb, var(--bs-accent) 15%, transparent); color: var(--bs-accent); }\n .bs-ann-btn[title]::after { content: none; }\n .bs-ann-dot {\n width: 20px; height: 20px; border-radius: 50%; border: 2.5px solid transparent; cursor: pointer;\n transition: all 0.15s; flex-shrink: 0;\n }\n .bs-ann-dot:hover { transform: scale(1.15); }\n .bs-ann-dot.bs-sel { border-color: var(--bs-text); transform: scale(1.15); box-shadow: 0 0 8px rgba(255,255,255,0.15); }\n .bs-ann-size {\n width: 60px; height: 4px; -webkit-appearance: none; appearance: none; background: var(--bs-border);\n border-radius: 2px; outline: none; cursor: pointer;\n }\n .bs-ann-size::-webkit-slider-thumb {\n -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;\n background: var(--bs-accent); cursor: pointer; border: 2px solid var(--bs-bg);\n }\n .bs-ann-zoom-label { font-size: 10px; font-weight: 600; color: var(--bs-muted); min-width: 32px; text-align: center; }\n .bs-ann-right { margin-left: auto; display: flex; gap: 2px; align-items: center; }\n .bs-ann-clr-btn {\n all: unset; padding: 3px 10px; border: 1px solid var(--bs-border); border-radius: 6px;\n color: var(--bs-muted); font-size: 10px; cursor: pointer; font-family: 'Inter', sans-serif; transition: all 0.15s;\n }\n .bs-ann-clr-btn:hover { color: var(--bs-red); border-color: color-mix(in srgb, var(--bs-red) 30%, transparent); }\n\n /* ── Pin Tool ── */\n .bs-ann-canvas.bs-pin { cursor: crosshair; }\n .bs-ann-pins { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }\n .bs-ann-pin {\n position: absolute;\n width: 26px; height: 26px;\n border-radius: 50% 50% 50% 0;\n transform: translate(-50%, -100%) rotate(-45deg);\n display: flex; align-items: center; justify-content: center;\n font-size: 11px; font-weight: 700; font-family: 'Inter', sans-serif;\n color: #fff;\n pointer-events: all;\n cursor: grab;\n transition: transform 0.15s, box-shadow 0.15s;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n z-index: 1;\n }\n .bs-ann-pin:hover { transform: translate(-50%, -100%) rotate(-45deg) scale(1.15); box-shadow: 0 4px 16px rgba(0,0,0,0.4); z-index: 2; }\n .bs-ann-pin.bs-dragging { cursor: grabbing; transform: translate(-50%, -100%) rotate(-45deg) scale(1.2); z-index: 3; }\n .bs-ann-pin-n { transform: rotate(45deg); line-height: 1; }\n .bs-ann-pin-pulse {\n position: absolute; inset: -4px; border-radius: 50% 50% 50% 0;\n border: 2px solid currentColor; opacity: 0;\n animation: bs-pin-ring 1.5s ease-out forwards;\n }\n @keyframes bs-pin-ring { 0% { opacity: 0.6; inset: -4px; } 100% { opacity: 0; inset: -14px; } }\n\n /* ── Pin List (below canvas) ── */\n .bs-ann-pin-list {\n max-height: 140px;\n overflow-y: auto;\n border-top: 1px solid var(--bs-border);\n background: var(--bs-bg2);\n }\n .bs-ann-pin-item {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 8px 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--bs-border) 50%, transparent);\n font-size: 12px;\n color: var(--bs-text);\n }\n .bs-ann-pin-item:last-child { border-bottom: none; }\n .bs-ann-pin-num {\n width: 22px; height: 22px;\n border-radius: 50%;\n display: flex; align-items: center; justify-content: center;\n font-size: 11px; font-weight: 700; color: #fff;\n flex-shrink: 0;\n }\n .bs-ann-pin-body { flex: 1; min-width: 0; }\n .bs-ann-pin-note { word-break: break-word; line-height: 1.4; }\n .bs-ann-pin-loc { font-size: 10px; color: var(--bs-muted); margin-top: 2px; }\n .bs-ann-pin-del {\n all: unset; cursor: pointer; color: var(--bs-muted); font-size: 14px;\n padding: 2px 4px; border-radius: 4px; transition: color 0.15s;\n flex-shrink: 0;\n }\n .bs-ann-pin-del:hover { color: var(--bs-red); }\n\n /* ── History ── */\n .bs-hist-card {\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n padding: 14px;\n margin-bottom: 10px;\n transition: border-color 0.2s;\n }\n .bs-hist-card:hover { border-color: var(--bs-accent); }\n .bs-hist-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; margin-bottom: 8px; }\n .bs-hist-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--bs-text);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .bs-hist-actions { display: flex; gap: 4px; flex-shrink: 0; }\n .bs-hist-btn {\n all: unset;\n width: 26px; height: 26px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 6px;\n cursor: pointer;\n color: var(--bs-muted);\n transition: all 0.15s;\n font-size: 12px;\n }\n .bs-hist-btn:hover { background: var(--bs-bg3); color: var(--bs-text); }\n .bs-hist-btn.bs-del:hover { color: var(--bs-red); }\n .bs-hist-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 6px; }\n .bs-hist-badge {\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n .bs-hist-badge.bs-sev-low { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n .bs-hist-badge.bs-sev-medium { background: color-mix(in srgb, var(--bs-yellow) 12%, transparent); color: var(--bs-yellow); }\n .bs-hist-badge.bs-sev-high { background: color-mix(in srgb, var(--bs-orange) 12%, transparent); color: var(--bs-orange); }\n .bs-hist-badge.bs-sev-critical { background: color-mix(in srgb, var(--bs-red) 12%, transparent); color: var(--bs-red); }\n .bs-hist-badge.bs-cat { background: color-mix(in srgb, var(--bs-accent) 12%, transparent); color: var(--bs-accent); }\n .bs-hist-badge.bs-status-sent { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n .bs-hist-badge.bs-status-draft { background: color-mix(in srgb, var(--bs-yellow) 12%, transparent); color: var(--bs-yellow); }\n .bs-hist-desc { font-size: 12px; color: var(--bs-muted); line-height: 1.5; margin-bottom: 6px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }\n .bs-hist-foot { display: flex; justify-content: space-between; align-items: center; font-size: 10px; color: var(--bs-muted); }\n .bs-hist-pins { display: flex; gap: 4px; }\n .bs-hist-pin-dot { width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 9px; font-weight: 700; color: #fff; }\n .bs-hist-thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; border: 1px solid var(--bs-border); flex-shrink: 0; }\n .bs-hist-confirm {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 14px;\n background: color-mix(in srgb, var(--bs-red) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--bs-red) 20%, transparent);\n border-radius: var(--bs-radius-sm);\n margin-bottom: 10px;\n font-size: 12px; color: var(--bs-text);\n animation: bs-slideUp 0.2s ease;\n }\n .bs-hist-confirm-yes {\n all: unset; padding: 4px 12px; background: var(--bs-red); color: #fff; border-radius: 6px;\n font-size: 11px; font-weight: 600; cursor: pointer; font-family: 'Inter', sans-serif;\n }\n .bs-hist-confirm-no {\n all: unset; padding: 4px 12px; border: 1px solid var(--bs-border); border-radius: 6px;\n font-size: 11px; font-weight: 600; cursor: pointer; color: var(--bs-muted); font-family: 'Inter', sans-serif;\n }\n .bs-hist-edit-wrap { margin-bottom: 10px; animation: bs-slideUp 0.2s ease; }\n .bs-hist-edit-row { display: flex; gap: 6px; margin-top: 8px; }\n .bs-hist-save {\n all: unset; padding: 6px 16px; background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; font-family: 'Inter', sans-serif;\n }\n .bs-hist-cancel {\n all: unset; padding: 6px 16px; border: 1px solid var(--bs-border); border-radius: 6px;\n font-size: 12px; font-weight: 600; cursor: pointer; color: var(--bs-muted); font-family: 'Inter', sans-serif;\n }\n\n /* ── Empty ── */\n .bs-empty { text-align: center; padding: 36px 16px; color: var(--bs-muted); font-size: 13px; line-height: 1.6; }\n .bs-empty svg { opacity: 0.12; margin-bottom: 10px; }\n\n /* ── Settings ── */\n .bs-set-sec {\n font-size: 11px;\n font-weight: 700;\n color: var(--bs-accent);\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin: 0 0 12px;\n }\n .bs-set-sec + .bs-set-sec { margin-top: 24px; }\n .bs-set-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 8px;\n }\n .bs-set-card {\n all: unset;\n cursor: pointer;\n border: 2px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n overflow: hidden;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n .bs-set-card:hover { border-color: var(--bs-accent); transform: translateY(-1px); }\n .bs-set-card.bs-picked { border-color: var(--bs-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bs-accent) 25%, transparent); }\n .bs-set-preview {\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n }\n .bs-set-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n border: 1px solid rgba(255,255,255,0.1);\n }\n .bs-set-name {\n padding: 6px 8px;\n font-family: 'Inter', sans-serif;\n font-size: 10px;\n font-weight: 600;\n text-align: center;\n color: var(--bs-text);\n background: var(--bs-bg2);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .bs-set-ly-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));\n gap: 8px;\n }\n .bs-set-ly {\n all: unset;\n cursor: pointer;\n border: 2px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n padding: 10px 12px;\n transition: all 0.2s ease;\n font-family: 'Inter', sans-serif;\n }\n .bs-set-ly:hover { border-color: var(--bs-accent); transform: translateY(-1px); }\n .bs-set-ly.bs-picked { border-color: var(--bs-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bs-accent) 25%, transparent); }\n .bs-set-ly-name { font-size: 12px; font-weight: 600; color: var(--bs-text); margin-bottom: 2px; }\n .bs-set-ly-desc { font-size: 10px; color: var(--bs-muted); }\n`;\n\n// ─── Login Tab ───────────────────────────────────────────\n\nfunction tabLogin(): string {\n return `\n <div class=\"bs-login-form\">\n <div class=\"bs-login-logo\">BugStash</div>\n <div class=\"bs-login-subtitle\">Sign in to report bugs & collaborate</div>\n <input class=\"bs-login-input\" type=\"email\" id=\"bs-login-email\" placeholder=\"Email\" autocomplete=\"email\" />\n <input class=\"bs-login-input\" type=\"password\" id=\"bs-login-pass\" placeholder=\"Password\" autocomplete=\"current-password\" />\n <div class=\"bs-login-error\" id=\"bs-login-error\" style=\"display:none\"></div>\n <button class=\"bs-login-btn\" id=\"bs-login-submit\">Sign In</button>\n <div style=\"font-size:11px;color:var(--bs-muted);margin-top:4px\">Contact your admin for an account</div>\n </div>\n `;\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\nfunction timeAgo(ts: number): string {\n const s = Math.floor((Date.now() - ts) / 1000);\n if (s < 5) return 'now';\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n return new Date(ts).toLocaleTimeString();\n}\nfunction fmtTime(ts: number): string {\n return new Date(ts).toLocaleTimeString('en', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n}\n\n// ─── Report History (localStorage) ───────────────────────\n\nconst HISTORY_KEY = 'bugstash_history';\n\ninterface HistoryEntry {\n id: number;\n title: string;\n description: string;\n category: string;\n severity: string;\n tags?: string[];\n screenshot?: string;\n pins?: { number: number; x: number; y: number; note: string }[];\n url: string;\n createdAt: number;\n status: 'sent' | 'draft';\n}\n\nfunction getReportHistory(): HistoryEntry[] {\n try {\n return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]');\n } catch { return []; }\n}\n\nfunction saveReportHistory(entries: HistoryEntry[]) {\n try {\n localStorage.setItem(HISTORY_KEY, JSON.stringify(entries));\n } catch { /* quota exceeded */ }\n}\n\nfunction addToHistory(entry: Omit<HistoryEntry, 'id'>) {\n const entries = getReportHistory();\n const id = Date.now();\n entries.unshift({ ...entry, id });\n // Keep last 50\n if (entries.length > 50) entries.length = 50;\n saveReportHistory(entries);\n}\n\nfunction deleteFromHistory(id: number) {\n const entries = getReportHistory().filter(e => e.id !== id);\n saveReportHistory(entries);\n}\n\nfunction updateInHistory(id: number, updates: Partial<HistoryEntry>) {\n const entries = getReportHistory();\n const idx = entries.findIndex(e => e.id === id);\n if (idx >= 0) {\n entries[idx] = { ...entries[idx], ...updates };\n saveReportHistory(entries);\n }\n}\n\n// ─── Build Context ───────────────────────────────────────\n\nfunction buildContext(): ReportContext {\n return {\n url: window.location.href,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n language: navigator.language,\n cookiesEnabled: navigator.cookieEnabled,\n online: navigator.onLine,\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n timestamp: Date.now(),\n environment: config.environment ?? 'development',\n commitHash: config.commitHash,\n user: config.user,\n };\n}\n\n// ─── Tab Content ─────────────────────────────────────────\n\nfunction autoDetect() {\n const errors = getErrors();\n const logs = getLogs();\n const net = getNetworkCaptures();\n const failedNet = getFailedNetworkCaptures();\n const crumbs = getBreadcrumbs();\n const perf = getPerformanceMetrics();\n const consoleErrors = logs.filter(l => l.level === 'error');\n\n // Auto-detect severity\n let severity: BugReport['severity'] = 'low';\n if (errors.length >= 3 || failedNet.length >= 3) severity = 'critical';\n else if (errors.length >= 1 || failedNet.length >= 2) severity = 'high';\n else if (consoleErrors.length > 0 || failedNet.length >= 1) severity = 'medium';\n\n // Auto-generate tags\n const tags: string[] = [];\n if (errors.length) tags.push('has-errors');\n if (failedNet.length) tags.push('network-failures');\n if (consoleErrors.length) tags.push('console-errors');\n if (perf?.pageLoadTime && perf.pageLoadTime > 3000) tags.push('slow-load');\n if (perf?.cumulativeLayoutShift && perf.cumulativeLayoutShift > 0.25) tags.push('layout-shift');\n if (!navigator.onLine) tags.push('offline');\n if (window.innerWidth < 768) tags.push('mobile');\n\n return { severity, tags,\n counts: { logs: logs.length, network: net.length, failedNet: failedNet.length, errors: errors.length, crumbs: crumbs.length } };\n}\n\nfunction tabReport(): string {\n const d = autoDetect();\n const categories: { id: BugReport['category']; label: string; icon: string }[] = [\n { id: 'ui', label: 'UI', icon: '🎨' },\n { id: 'functionality', label: 'Feature', icon: '⚙️' },\n { id: 'performance', label: 'Speed', icon: '⚡' },\n { id: 'crash', label: 'Crash', icon: '💥' },\n { id: 'security', label: 'Security', icon: '🔒' },\n { id: 'other', label: 'Other', icon: '📌' },\n ];\n\n const hasIssues = d.counts.errors > 0 || d.counts.failedNet > 0;\n const summaryClass = hasIssues ? ' bs-alert' : d.counts.logs > 0 ? ' bs-has' : '';\n\n return `<div class=\"bs-view\">\n <form data-bs-form>\n <div class=\"bs-report-summary${summaryClass}\">\n <div class=\"bs-report-summary-left\">\n ${hasIssues\n ? `<div class=\"bs-report-summary-icon bs-warn\">!</div><span>${d.counts.errors} error${d.counts.errors !== 1 ? 's' : ''}, ${d.counts.failedNet} failed request${d.counts.failedNet !== 1 ? 's' : ''} detected</span>`\n : `<div class=\"bs-report-summary-icon\">${I.check}</div><span>Auto-collecting ${d.counts.logs} logs, ${d.counts.network} requests, ${d.counts.crumbs} actions</span>`}\n </div>\n </div>\n <div class=\"bs-field\">\n <input class=\"bs-input bs-input-title\" name=\"title\" placeholder=\"What's the bug?\" required autocomplete=\"off\" />\n </div>\n <div class=\"bs-field\">\n <textarea class=\"bs-textarea\" name=\"description\" placeholder=\"Steps to reproduce or extra details (optional)\"></textarea>\n </div>\n <div class=\"bs-report-row\">\n <div class=\"bs-report-col\">\n <div class=\"bs-field-label\">Category</div>\n <input type=\"hidden\" name=\"category\" value=\"functionality\" />\n <div class=\"bs-cat-row\">\n ${categories.map(c => `<button type=\"button\" class=\"bs-cat-btn${c.id === 'functionality' ? ' bs-picked' : ''}\" data-cat=\"${c.id}\"><span class=\"bs-cat-icon\">${c.icon}</span>${c.label}</button>`).join('')}\n </div>\n </div>\n <div class=\"bs-report-col\">\n <div class=\"bs-field-label\">Severity</div>\n <input type=\"hidden\" name=\"severity\" value=\"${d.severity}\" />\n <div class=\"bs-sev-row\">\n <button type=\"button\" class=\"bs-sev-btn bs-sev-low${d.severity === 'low' ? ' bs-picked' : ''}\" data-sev=\"low\">Low</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-medium${d.severity === 'medium' ? ' bs-picked' : ''}\" data-sev=\"medium\">Med</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-high${d.severity === 'high' ? ' bs-picked' : ''}\" data-sev=\"high\">High</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-critical${d.severity === 'critical' ? ' bs-picked' : ''}\" data-sev=\"critical\">Critical</button>\n </div>\n </div>\n </div>\n <div class=\"bs-shot-area\" data-bs-screenshot>\n <div class=\"bs-shot-icon\">${I.cam}</div>\n <div class=\"bs-shot-text\">\n <div class=\"bs-shot-title\" data-bs-shot-title>Attach screenshot</div>\n <div class=\"bs-shot-sub\" data-bs-shot-sub>Capture & annotate the current view</div>\n </div>\n </div>\n <div data-bs-annotate></div>\n <button type=\"submit\" class=\"bs-submit-btn\">Submit Report</button>\n <div data-bs-msg></div>\n </form>\n </div>`;\n}\n\nfunction tabConsole(): string {\n const logs = getLogs();\n const lvMap: Record<string, string> = { error: 'bs-le', warn: 'bs-lw', log: 'bs-ll', info: 'bs-li', debug: 'bs-ld' };\n if (!logs.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No console logs captured yet.<br>Use the app — logs will appear here automatically.</p></div></div>`;\n }\n return `<div class=\"bs-view\">${logs.slice().reverse().map(l =>\n `<div class=\"bs-log\"><span class=\"bs-log-lv ${lvMap[l.level] || 'bs-ll'}\">${l.level}</span><span class=\"bs-log-m\">${esc(l.args.join(' ')).slice(0, 500)}</span><span class=\"bs-log-t\">${fmtTime(l.timestamp)}</span></div>`\n ).join('')}</div>`;\n}\n\nfunction tabNetwork(): string {\n const caps = getNetworkCaptures();\n if (!caps.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No network requests captured yet.<br>API calls will show up here automatically.</p></div></div>`;\n }\n return `<div class=\"bs-view\">${caps.slice().reverse().map(n =>\n `<div class=\"bs-net\"><span class=\"bs-net-m\">${n.method}</span><span class=\"bs-net-s ${n.failed ? 'bs-fail' : 'bs-ok'}\">${n.status || 'ERR'}</span><span class=\"bs-net-u\" title=\"${esc(n.url)}\">${esc(n.url)}</span><span class=\"bs-net-d\">${n.duration}ms</span></div>`\n ).join('')}</div>`;\n}\n\nfunction tabContext(): string {\n let html = `<div class=\"bs-view\">`;\n\n const errs = getErrors();\n if (errs.length) {\n html += `<div class=\"bs-sec\">Errors <span class=\"bs-sec-n\">${errs.length}</span></div>`;\n html += errs.slice().reverse().map(e =>\n `<div class=\"bs-err-card\"><div class=\"bs-err-m\">${esc(e.message)}</div>${e.stack ? `<div class=\"bs-err-stack\">${esc(e.stack)}</div>` : ''}<div class=\"bs-err-meta\">${e.type} &middot; ${fmtTime(e.timestamp)}${e.source ? ` &middot; ${esc(e.source)}:${e.lineno}` : ''}</div></div>`\n ).join('');\n }\n\n const perf = getPerformanceMetrics();\n if (perf) {\n html += `<div class=\"bs-sec\">Performance</div>`;\n const bars: [string, number | undefined, number][] = [\n ['Page Load', perf.pageLoadTime, 5000], ['DOM Ready', perf.domContentLoaded, 3000],\n ['First Paint', perf.firstPaint, 2000], ['FCP', perf.firstContentfulPaint, 2500],\n ['LCP', perf.largestContentfulPaint, 4000], ['FID', perf.firstInputDelay, 300],\n ];\n for (const [label, val, max] of bars) {\n if (val === undefined) continue;\n const pct = Math.min(100, (val / max) * 100);\n html += `<div class=\"bs-pf\"><span class=\"bs-pf-l\">${label}</span><div class=\"bs-pf-tr\"><div class=\"bs-pf-fl${pct > 75 ? ' bs-slow' : ''}\" style=\"width:${pct}%\"></div></div><span class=\"bs-pf-v\">${val}ms</span></div>`;\n }\n if (perf.cumulativeLayoutShift !== undefined) {\n const p = Math.min(100, perf.cumulativeLayoutShift * 400);\n html += `<div class=\"bs-pf\"><span class=\"bs-pf-l\">CLS</span><div class=\"bs-pf-tr\"><div class=\"bs-pf-fl${p > 40 ? ' bs-slow' : ''}\" style=\"width:${p}%\"></div></div><span class=\"bs-pf-v\">${perf.cumulativeLayoutShift}</span></div>`;\n }\n }\n\n const crumbs = getBreadcrumbs();\n if (crumbs.length) {\n html += `<div class=\"bs-sec\">Your activity trail <span class=\"bs-sec-n\">${crumbs.length}</span></div>`;\n html += crumbs.slice().reverse().map(b =>\n `<div class=\"bs-bc\"><span class=\"bs-bc-t bs-t-${b.type}\">${b.type}</span><span class=\"bs-bc-m\">${esc(b.message).slice(0, 120)}</span><span class=\"bs-bc-time\">${timeAgo(b.timestamp)}</span></div>`\n ).join('');\n }\n\n const ctx = buildContext();\n html += `<div class=\"bs-sec\">Environment</div>`;\n html += `<div class=\"bs-kv\">\n <span class=\"bs-kv-k\">URL</span><span class=\"bs-kv-v\">${esc(ctx.url)}</span>\n <span class=\"bs-kv-k\">Viewport</span><span class=\"bs-kv-v\">${ctx.viewportWidth}&times;${ctx.viewportHeight} @${ctx.devicePixelRatio}x</span>\n <span class=\"bs-kv-k\">Screen</span><span class=\"bs-kv-v\">${ctx.screenWidth}&times;${ctx.screenHeight}</span>\n <span class=\"bs-kv-k\">Platform</span><span class=\"bs-kv-v\">${esc(ctx.platform)}</span>\n <span class=\"bs-kv-k\">Language</span><span class=\"bs-kv-v\">${ctx.language}</span>\n ${config.commitHash ? `<span class=\"bs-kv-k\">Commit</span><span class=\"bs-kv-v\">${esc(config.commitHash)}</span>` : ''}\n ${config.user?.email ? `<span class=\"bs-kv-k\">User</span><span class=\"bs-kv-v\">${esc(config.user.email)}</span>` : ''}\n </div>`;\n\n html += `</div>`;\n return html;\n}\n\nfunction tabHistory(): string {\n const entries = getReportHistory();\n if (!entries.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No reports yet.<br>Submitted bugs will appear here.</p></div></div>`;\n }\n\n const catLabels: Record<string, string> = { ui: 'UI', functionality: 'Feature', performance: 'Perf', crash: 'Crash', security: 'Security', other: 'Other' };\n const fmtDate = (ts: number) => {\n const d = new Date(ts);\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffH = Math.floor(diffMin / 60);\n if (diffH < 24) return `${diffH}h ago`;\n const diffD = Math.floor(diffH / 24);\n if (diffD < 7) return `${diffD}d ago`;\n return d.toLocaleDateString('en', { month: 'short', day: 'numeric' });\n };\n\n let html = `<div class=\"bs-view\">`;\n for (const e of entries) {\n const pinsHtml = e.pins?.length\n ? `<div class=\"bs-hist-pins\">${e.pins.slice(0, 5).map(p => `<div class=\"bs-hist-pin-dot\" style=\"background:${['#ef4444','#3b82f6','#f59e0b','#10b981','#8b5cf6'][p.number % 5]}\">${p.number}</div>`).join('')}${e.pins.length > 5 ? `<span>+${e.pins.length - 5}</span>` : ''}</div>`\n : '';\n html += `<div class=\"bs-hist-card\" data-hist-id=\"${e.id}\">\n <div class=\"bs-hist-top\">\n <div class=\"bs-hist-title\">${esc(e.title)}</div>\n ${e.screenshot ? `<img class=\"bs-hist-thumb\" src=\"${e.screenshot}\" alt=\"\"/>` : ''}\n <div class=\"bs-hist-actions\">\n <button class=\"bs-hist-btn\" data-hist-edit=\"${e.id}\" title=\"Edit\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg></button>\n <button class=\"bs-hist-btn bs-del\" data-hist-del=\"${e.id}\" title=\"Delete\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/></svg></button>\n </div>\n </div>\n <div class=\"bs-hist-meta\">\n <span class=\"bs-hist-badge bs-cat\">${catLabels[e.category] || e.category}</span>\n <span class=\"bs-hist-badge bs-sev-${e.severity}\">${e.severity}</span>\n <span class=\"bs-hist-badge bs-status-${e.status}\">${e.status}</span>\n </div>\n ${e.description ? `<div class=\"bs-hist-desc\">${esc(e.description)}</div>` : ''}\n <div class=\"bs-hist-foot\">\n <span>${fmtDate(e.createdAt)} &middot; ${esc(e.url.replace(/^https?:\\/\\//, '').slice(0, 40))}</span>\n ${pinsHtml}\n </div>\n </div>`;\n }\n html += `</div>`;\n return html;\n}\n\nfunction tabSettings(): string {\n const themes = getThemes();\n const layouts = getLayouts();\n\n let html = `<div class=\"bs-view\">`;\n\n html += `<div class=\"bs-set-sec\">Layout</div>`;\n html += `<div class=\"bs-set-ly-grid\">`;\n for (const l of layouts) {\n html += `<button class=\"bs-set-ly${l.id === currentLayout.id ? ' bs-picked' : ''}\" data-set-layout=\"${l.id}\"><div class=\"bs-set-ly-name\">${esc(l.name)}</div><div class=\"bs-set-ly-desc\">${esc(l.description)}</div></button>`;\n }\n html += `</div>`;\n\n html += `<div class=\"bs-set-sec\">Theme</div>`;\n html += `<div class=\"bs-set-grid\">`;\n for (const t of themes) {\n html += `<button class=\"bs-set-card${t.id === currentTheme.id ? ' bs-picked' : ''}\" data-set-theme=\"${t.id}\"><div class=\"bs-set-preview\" style=\"background:${t.preview[0]}\"><div class=\"bs-set-dot\" style=\"background:${t.preview[1]}\"></div><div class=\"bs-set-dot\" style=\"background:${t.vars['--bs-accent2'] || t.preview[1]};opacity:0.6\"></div></div><div class=\"bs-set-name\">${esc(t.name)}</div></button>`;\n }\n html += `</div>`;\n\n html += `</div>`;\n return html;\n}\n\n// ─── Annotation ──────────────────────────────────────────\n\nfunction setupAnnotation(container: HTMLElement, screenshotData: string): { getAnnotation: () => string | null; getPins: () => { number: number; x: number; y: number; note: string }[] } {\n const COLORS = ['#f87171', '#3b82f6', '#fb923c', '#4ade80', '#a78bfa', '#facc15'];\n type Tool = 'select' | 'draw' | 'arrow' | 'rect' | 'circle' | 'text' | 'highlight' | 'pin';\n\n interface AnnShape {\n type: 'draw' | 'highlight';\n color: string; size: number; alpha: number;\n points: { x: number; y: number }[];\n }\n interface AnnRect { type: 'rect'; color: string; size: number; x: number; y: number; w: number; h: number; }\n interface AnnCircle { type: 'circle'; color: string; size: number; cx: number; cy: number; rx: number; ry: number; }\n interface AnnArrow { type: 'arrow'; color: string; size: number; x1: number; y1: number; x2: number; y2: number; }\n interface AnnText { type: 'text'; color: string; size: number; x: number; y: number; text: string; }\n type AnnObj = AnnShape | AnnRect | AnnCircle | AnnArrow | AnnText;\n\n let currentColor = COLORS[0];\n interface Pin { x: number; y: number; note: string; color: string; }\n\n let currentTool: Tool = 'draw';\n let brushSize = 4;\n let zoom = 1;\n let isDark = false;\n const shapes: AnnObj[] = [];\n const pins: Pin[] = [];\n let selectedIdx = -1;\n let hoveredIdx = -1;\n let dragging = false;\n let drawing = false;\n let dragOffX = 0, dragOffY = 0;\n let startX = 0, startY = 0;\n let currentDraw: { x: number; y: number }[] = [];\n const PIN_COLORS = ['#ef4444', '#3b82f6', '#f59e0b', '#10b981', '#8b5cf6', '#ec4899'];\n\n const img = new Image();\n img.src = screenshotData;\n\n const wrap = document.createElement('div');\n wrap.className = 'bs-ann-wrap';\n const viewport = document.createElement('div');\n viewport.className = 'bs-ann-viewport';\n const canvas = document.createElement('canvas');\n canvas.className = 'bs-ann-canvas bs-draw';\n const toolbar = document.createElement('div');\n toolbar.className = 'bs-ann-toolbar';\n\n const tIcons: Record<Tool, string> = {\n select: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/></svg>`,\n draw: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M12 19l7-7 3 3-7 7-3-3z\"/><path d=\"M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z\"/><path d=\"M2 2l7.586 7.586\"/></svg>`,\n arrow: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/><polyline points=\"12 5 19 12 12 19\"/></svg>`,\n rect: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/></svg>`,\n circle: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/></svg>`,\n text: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9.5\" y1=\"20\" x2=\"14.5\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/></svg>`,\n highlight: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M9 11l-6 6v3h9l3-3\"/><path d=\"M22 12l-4.6 4.6a2 2 0 01-2.8 0l-5.2-5.2a2 2 0 010-2.8L14 4\"/></svg>`,\n pin: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>`,\n };\n const toolNames: Record<Tool, string> = { select: 'Select & Move', draw: 'Draw', arrow: 'Arrow', rect: 'Rectangle', circle: 'Circle', text: 'Text', highlight: 'Highlight', pin: 'Pin Issue' };\n\n // Tool buttons\n const toolBtns: HTMLButtonElement[] = [];\n const setTool = (t: Tool) => {\n currentTool = t;\n selectedIdx = -1;\n canvas.className = `bs-ann-canvas bs-${t}`;\n toolBtns.forEach(b => b.classList.remove('bs-sel'));\n toolBtns.find(b => b.dataset.tool === t)?.classList.add('bs-sel');\n };\n (Object.keys(tIcons) as Tool[]).forEach(t => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.dataset.tool = t;\n btn.className = `bs-ann-btn${t === currentTool ? ' bs-sel' : ''}`;\n btn.title = toolNames[t];\n btn.innerHTML = tIcons[t];\n btn.addEventListener('click', () => setTool(t));\n toolBtns.push(btn);\n toolbar.appendChild(btn);\n });\n\n // Separator\n toolbar.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n\n // Colors\n COLORS.forEach((color, i) => {\n const d = document.createElement('button');\n d.type = 'button';\n d.className = `bs-ann-dot${i === 0 ? ' bs-sel' : ''}`;\n d.style.background = color;\n d.addEventListener('click', () => {\n currentColor = color;\n toolbar.querySelectorAll('.bs-ann-dot').forEach(t => t.classList.remove('bs-sel'));\n d.classList.add('bs-sel');\n });\n toolbar.appendChild(d);\n });\n\n toolbar.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n\n // Brush size\n const sizeSlider = document.createElement('input');\n sizeSlider.type = 'range'; sizeSlider.min = '1'; sizeSlider.max = '12'; sizeSlider.value = '4';\n sizeSlider.className = 'bs-ann-size'; sizeSlider.title = 'Brush size';\n sizeSlider.addEventListener('input', () => { brushSize = parseInt(sizeSlider.value); });\n toolbar.appendChild(sizeSlider);\n\n // Right side\n const right = document.createElement('div');\n right.className = 'bs-ann-right';\n\n const mkBtn = (title: string, svg: string) => {\n const b = document.createElement('button');\n b.type = 'button'; b.className = 'bs-ann-btn'; b.title = title; b.innerHTML = svg;\n return b;\n };\n const zoomOut = mkBtn('Zoom out', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>`);\n const zoomLabel = Object.assign(document.createElement('span'), { className: 'bs-ann-zoom-label', textContent: '100%' });\n const zoomIn = mkBtn('Zoom in', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>`);\n const zoomReset = mkBtn('Fit', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>`);\n const undoBtn = mkBtn('Undo', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 105.42-8.49L1 10\"/></svg>`);\n const clearBtn = Object.assign(document.createElement('button'), { type: 'button', className: 'bs-ann-clr-btn', textContent: 'Clear' });\n\n const applyZoom = () => { canvas.style.transform = `scale(${zoom})`; zoomLabel.textContent = `${Math.round(zoom * 100)}%`; };\n zoomIn.addEventListener('click', () => { if (zoom < 3) { zoom = Math.min(3, zoom + 0.25); applyZoom(); } });\n zoomOut.addEventListener('click', () => { if (zoom > 0.5) { zoom = Math.max(0.5, zoom - 0.25); applyZoom(); } });\n zoomReset.addEventListener('click', () => { zoom = 1; applyZoom(); });\n\n right.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n [zoomOut, zoomLabel, zoomIn, zoomReset, undoBtn, clearBtn].forEach(el => right.appendChild(el));\n toolbar.appendChild(right);\n\n // Pin overlay layer (positioned over the canvas)\n const pinLayer = document.createElement('div');\n pinLayer.className = 'bs-ann-pins';\n // Pin list below toolbar\n const pinList = document.createElement('div');\n pinList.className = 'bs-ann-pin-list';\n pinList.style.display = 'none';\n\n viewport.appendChild(canvas);\n viewport.appendChild(pinLayer);\n wrap.appendChild(viewport);\n wrap.appendChild(toolbar);\n wrap.appendChild(pinList);\n container.innerHTML = '';\n container.appendChild(wrap);\n\n // ── Pin rendering ──\n const renderPins = () => {\n pinLayer.innerHTML = '';\n pinList.innerHTML = '';\n pinList.style.display = pins.length ? '' : 'none';\n\n pins.forEach((pin, i) => {\n // Pin marker on canvas\n const el = document.createElement('div');\n el.className = 'bs-ann-pin';\n el.style.background = pin.color;\n el.style.color = pin.color;\n // Position as percentage of viewport\n const pctX = (pin.x / (canvas.width || 1)) * 100;\n const pctY = (pin.y / (canvas.height || 1)) * 100;\n el.style.left = `${pctX}%`;\n el.style.top = `${pctY}%`;\n el.innerHTML = `<span class=\"bs-ann-pin-n\">${i + 1}</span><span class=\"bs-ann-pin-pulse\"></span>`;\n el.title = `#${i + 1}: ${pin.note}`;\n\n // Drag pin\n let pinDragging = false;\n el.addEventListener('mousedown', (e) => {\n e.stopPropagation();\n pinDragging = true;\n el.classList.add('bs-dragging');\n const onMove = (me: MouseEvent) => {\n if (!pinDragging) return;\n const r = viewport.getBoundingClientRect();\n pin.x = ((me.clientX - r.left) / r.width) * canvas.width;\n pin.y = ((me.clientY - r.top) / r.height) * canvas.height;\n el.style.left = `${((me.clientX - r.left) / r.width) * 100}%`;\n el.style.top = `${((me.clientY - r.top) / r.height) * 100}%`;\n };\n const onUp = () => {\n pinDragging = false;\n el.classList.remove('bs-dragging');\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n renderPins(); // refresh list coords\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n pinLayer.appendChild(el);\n\n // Pin list item\n const item = document.createElement('div');\n item.className = 'bs-ann-pin-item';\n item.innerHTML = `\n <div class=\"bs-ann-pin-num\" style=\"background:${pin.color}\">${i + 1}</div>\n <div class=\"bs-ann-pin-body\">\n <div class=\"bs-ann-pin-note\">${esc(pin.note)}</div>\n <div class=\"bs-ann-pin-loc\">${Math.round(pctX)}% × ${Math.round(pctY)}%</div>\n </div>`;\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'bs-ann-pin-del';\n del.innerHTML = '&times;';\n del.title = 'Remove pin';\n del.addEventListener('click', () => {\n pins.splice(i, 1);\n renderPins();\n });\n item.appendChild(del);\n pinList.appendChild(item);\n });\n };\n\n // ── Render engine ──\n let ctx: CanvasRenderingContext2D;\n const outlineColor = () => isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.35)';\n\n const drawOutline = (fn: () => void, lw: number) => {\n // Draw shadow outline for contrast on any background\n ctx.save();\n ctx.strokeStyle = outlineColor();\n ctx.lineWidth = lw + 3;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n ctx.globalAlpha = 0.5;\n fn();\n ctx.restore();\n };\n\n const renderShape = (s: AnnObj, preview = false) => {\n if (s.type === 'draw' || s.type === 'highlight') {\n if (s.points.length < 2) return;\n const alpha = s.type === 'highlight' ? 0.25 : 1;\n const lw = s.type === 'highlight' ? s.size * 4 + 10 : s.size;\n const stroke = () => {\n ctx.beginPath();\n ctx.moveTo(s.points[0].x, s.points[0].y);\n for (let i = 1; i < s.points.length; i++) ctx.lineTo(s.points[i].x, s.points[i].y);\n ctx.stroke();\n };\n if (s.type !== 'highlight') drawOutline(stroke, lw);\n ctx.strokeStyle = s.color; ctx.lineWidth = lw;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n ctx.globalAlpha = alpha;\n stroke();\n ctx.globalAlpha = 1;\n } else if (s.type === 'rect') {\n const stroke = () => ctx.strokeRect(s.x, s.y, s.w, s.h);\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n } else if (s.type === 'circle') {\n const stroke = () => { ctx.beginPath(); ctx.ellipse(s.cx, s.cy, Math.abs(s.rx), Math.abs(s.ry), 0, 0, Math.PI * 2); ctx.stroke(); };\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n stroke();\n } else if (s.type === 'arrow') {\n const angle = Math.atan2(s.y2 - s.y1, s.x2 - s.x1);\n const headLen = 12 + s.size * 2;\n const stroke = () => {\n ctx.beginPath(); ctx.moveTo(s.x1, s.y1); ctx.lineTo(s.x2, s.y2); ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(s.x2, s.y2);\n ctx.lineTo(s.x2 - headLen * Math.cos(angle - 0.45), s.y2 - headLen * Math.sin(angle - 0.45));\n ctx.moveTo(s.x2, s.y2);\n ctx.lineTo(s.x2 - headLen * Math.cos(angle + 0.45), s.y2 - headLen * Math.sin(angle + 0.45));\n ctx.stroke();\n };\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n } else if (s.type === 'text') {\n const fontSize = s.size * 5 + 12;\n ctx.font = `bold ${fontSize}px Inter, -apple-system, sans-serif`;\n // text shadow for contrast\n ctx.fillStyle = outlineColor();\n ctx.globalAlpha = 0.6;\n ctx.fillText(s.text, s.x + 1, s.y + 1);\n ctx.globalAlpha = 1;\n ctx.fillStyle = s.color;\n ctx.fillText(s.text, s.x, s.y);\n }\n\n // Selection / hover highlight\n const isSelected = !preview && selectedIdx >= 0 && shapes[selectedIdx] === s;\n const isHovered = !preview && !isSelected && hoveredIdx >= 0 && shapes[hoveredIdx] === s;\n if (isSelected || isHovered) {\n const b = shapeBounds(s);\n ctx.save();\n ctx.setLineDash([6, 4]);\n ctx.strokeStyle = isDark ? '#fff' : '#000';\n ctx.lineWidth = isSelected ? 1.5 : 1;\n ctx.globalAlpha = isSelected ? 0.7 : 0.45;\n ctx.strokeRect(b.x - 4, b.y - 4, b.w + 8, b.h + 8);\n\n // Corner/cardinal handles for rects and circles\n if (s.type === 'rect' || s.type === 'circle') {\n const hSize = 5;\n ctx.setLineDash([]);\n ctx.globalAlpha = isSelected ? 0.9 : 0.6;\n const handles: [number, number][] = s.type === 'rect'\n ? [[b.x, b.y], [b.x + b.w, b.y], [b.x, b.y + b.h], [b.x + b.w, b.y + b.h]]\n : [[b.x + b.w / 2, b.y], [b.x + b.w, b.y + b.h / 2], [b.x + b.w / 2, b.y + b.h], [b.x, b.y + b.h / 2]];\n for (const [hx, hy] of handles) {\n ctx.fillStyle = '#fff';\n ctx.fillRect(hx - hSize, hy - hSize, hSize * 2, hSize * 2);\n ctx.strokeStyle = isDark ? '#aaa' : '#333';\n ctx.lineWidth = 1.2;\n ctx.strokeRect(hx - hSize, hy - hSize, hSize * 2, hSize * 2);\n }\n }\n ctx.restore();\n }\n };\n\n const render = () => {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0);\n for (const s of shapes) renderShape(s);\n };\n\n // ── Hit testing & bounds ──\n const shapeBounds = (s: AnnObj): { x: number; y: number; w: number; h: number } => {\n if (s.type === 'rect') return { x: Math.min(s.x, s.x + s.w), y: Math.min(s.y, s.y + s.h), w: Math.abs(s.w), h: Math.abs(s.h) };\n if (s.type === 'circle') return { x: s.cx - Math.abs(s.rx), y: s.cy - Math.abs(s.ry), w: Math.abs(s.rx) * 2, h: Math.abs(s.ry) * 2 };\n if (s.type === 'arrow') {\n const x = Math.min(s.x1, s.x2), y = Math.min(s.y1, s.y2);\n return { x, y, w: Math.abs(s.x2 - s.x1) || 20, h: Math.abs(s.y2 - s.y1) || 20 };\n }\n if (s.type === 'text') return { x: s.x, y: s.y - (s.size * 5 + 12), w: s.text.length * (s.size * 3 + 8), h: s.size * 5 + 16 };\n // draw / highlight: bounding box of points\n if (s.points.length === 0) return { x: 0, y: 0, w: 0, h: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const p of s.points) { minX = Math.min(minX, p.x); minY = Math.min(minY, p.y); maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y); }\n return { x: minX, y: minY, w: maxX - minX || 10, h: maxY - minY || 10 };\n };\n\n const hitTest = (x: number, y: number): number => {\n for (let i = shapes.length - 1; i >= 0; i--) {\n const b = shapeBounds(shapes[i]);\n const pad = 8;\n if (x >= b.x - pad && x <= b.x + b.w + pad && y >= b.y - pad && y <= b.y + b.h + pad) return i;\n }\n return -1;\n };\n\n const moveShape = (s: AnnObj, dx: number, dy: number) => {\n if (s.type === 'draw' || s.type === 'highlight') { for (const p of s.points) { p.x += dx; p.y += dy; } }\n else if (s.type === 'rect') { s.x += dx; s.y += dy; }\n else if (s.type === 'circle') { s.cx += dx; s.cy += dy; }\n else if (s.type === 'arrow') { s.x1 += dx; s.y1 += dy; s.x2 += dx; s.y2 += dy; }\n else if (s.type === 'text') { s.x += dx; s.y += dy; }\n };\n\n img.onload = () => {\n const maxW = container.clientWidth || 450;\n const scale = maxW / img.width;\n canvas.width = img.width;\n canvas.height = img.height;\n canvas.style.height = `${img.height * scale}px`;\n ctx = canvas.getContext('2d')!;\n ctx.drawImage(img, 0, 0);\n\n // Detect brightness: sample corners + center\n const samplePoints = [[10, 10], [canvas.width - 10, 10], [10, canvas.height - 10], [canvas.width - 10, canvas.height - 10], [canvas.width / 2, canvas.height / 2]];\n let totalBrightness = 0;\n for (const [sx, sy] of samplePoints) {\n const px = ctx.getImageData(sx, sy, 1, 1).data;\n totalBrightness += (px[0] * 299 + px[1] * 587 + px[2] * 114) / 1000;\n }\n isDark = (totalBrightness / samplePoints.length) < 128;\n\n const coords = (e: MouseEvent) => {\n const r = canvas.getBoundingClientRect();\n return { x: (e.clientX - r.left) * (canvas.width / r.width), y: (e.clientY - r.top) * (canvas.height / r.height) };\n };\n\n let autoSelectDrag = false; // true when we auto-switched to drag on hover-hit\n\n canvas.addEventListener('mousedown', e => {\n const c = coords(e);\n\n // Select mode: pick or drag\n if (currentTool === 'select') {\n const hit = hitTest(c.x, c.y);\n if (hit >= 0) {\n selectedIdx = hit;\n dragging = true;\n const b = shapeBounds(shapes[hit]);\n dragOffX = c.x - b.x;\n dragOffY = c.y - b.y;\n canvas.classList.add('bs-grabbing');\n canvas.classList.remove('bs-grab');\n render();\n } else {\n selectedIdx = -1;\n render();\n }\n return;\n }\n\n // Auto-drag: if hovering a shape in any drawing tool, grab it instead\n if (currentTool !== 'pin' && currentTool !== 'text') {\n const hit = hitTest(c.x, c.y);\n if (hit >= 0) {\n selectedIdx = hit;\n dragging = true;\n autoSelectDrag = true;\n const b = shapeBounds(shapes[hit]);\n dragOffX = c.x - b.x;\n dragOffY = c.y - b.y;\n canvas.classList.add('bs-grabbing');\n render();\n return;\n }\n }\n\n drawing = true;\n startX = c.x; startY = c.y;\n\n if (currentTool === 'pin') {\n drawing = false;\n const note = prompt('Describe the issue at this spot:');\n if (note) {\n const color = PIN_COLORS[pins.length % PIN_COLORS.length];\n pins.push({ x: c.x, y: c.y, note, color });\n renderPins();\n }\n return;\n }\n\n if (currentTool === 'text') {\n drawing = false;\n const input = prompt('Enter text:');\n if (input) {\n shapes.push({ type: 'text', color: currentColor, size: brushSize, x: c.x, y: c.y, text: input });\n render();\n }\n return;\n }\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n currentDraw = [{ x: c.x, y: c.y }];\n }\n });\n\n canvas.addEventListener('mousemove', e => {\n const c = coords(e);\n\n // Active drag (select mode or auto-drag from any tool)\n if (dragging && selectedIdx >= 0) {\n const b = shapeBounds(shapes[selectedIdx]);\n const dx = c.x - dragOffX - b.x;\n const dy = c.y - dragOffY - b.y;\n moveShape(shapes[selectedIdx], dx, dy);\n render();\n return;\n }\n\n // Select mode hover\n if (currentTool === 'select') {\n const hit = hitTest(c.x, c.y);\n canvas.classList.toggle('bs-grab', hit >= 0);\n if (hoveredIdx !== hit) { hoveredIdx = hit; render(); }\n return;\n }\n\n // Any tool: show grab cursor when hovering a shape\n if (currentTool !== 'pin' && currentTool !== 'text' && !drawing) {\n const hit = hitTest(c.x, c.y);\n canvas.classList.toggle('bs-grab', hit >= 0);\n if (hoveredIdx !== hit) { hoveredIdx = hit; render(); }\n }\n\n if (!drawing) return;\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n currentDraw.push({ x: c.x, y: c.y });\n // Live preview\n render();\n const alpha = currentTool === 'highlight' ? 0.25 : 1;\n const lw = currentTool === 'highlight' ? brushSize * 4 + 10 : brushSize;\n if (currentTool !== 'highlight') {\n ctx.save();\n ctx.strokeStyle = outlineColor(); ctx.lineWidth = lw + 3;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.globalAlpha = 0.5;\n ctx.beginPath(); ctx.moveTo(currentDraw[0].x, currentDraw[0].y);\n for (let i = 1; i < currentDraw.length; i++) ctx.lineTo(currentDraw[i].x, currentDraw[i].y);\n ctx.stroke(); ctx.restore();\n }\n ctx.strokeStyle = currentColor; ctx.lineWidth = lw;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.globalAlpha = alpha;\n ctx.beginPath(); ctx.moveTo(currentDraw[0].x, currentDraw[0].y);\n for (let i = 1; i < currentDraw.length; i++) ctx.lineTo(currentDraw[i].x, currentDraw[i].y);\n ctx.stroke(); ctx.globalAlpha = 1;\n } else {\n // Shape preview\n render();\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n if (currentTool === 'rect') {\n drawOutline(() => ctx.strokeRect(startX, startY, c.x - startX, c.y - startY), brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.strokeRect(startX, startY, c.x - startX, c.y - startY);\n } else if (currentTool === 'circle') {\n const rx = Math.abs(c.x - startX) / 2, ry = Math.abs(c.y - startY) / 2;\n const cx2 = startX + (c.x - startX) / 2, cy2 = startY + (c.y - startY) / 2;\n drawOutline(() => { ctx.beginPath(); ctx.ellipse(cx2, cy2, rx, ry, 0, 0, Math.PI * 2); ctx.stroke(); }, brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.beginPath(); ctx.ellipse(cx2, cy2, rx, ry, 0, 0, Math.PI * 2); ctx.stroke();\n } else if (currentTool === 'arrow') {\n const angle = Math.atan2(c.y - startY, c.x - startX);\n const headLen = 12 + brushSize * 2;\n const stroke = () => {\n ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(c.x, c.y); ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(c.x, c.y);\n ctx.lineTo(c.x - headLen * Math.cos(angle - 0.45), c.y - headLen * Math.sin(angle - 0.45));\n ctx.moveTo(c.x, c.y);\n ctx.lineTo(c.x - headLen * Math.cos(angle + 0.45), c.y - headLen * Math.sin(angle + 0.45));\n ctx.stroke();\n };\n drawOutline(stroke, brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n }\n }\n });\n\n const endDraw = (e: MouseEvent) => {\n // Release auto-drag or select-mode drag\n if (dragging) {\n dragging = false;\n autoSelectDrag = false;\n selectedIdx = -1;\n canvas.classList.remove('bs-grabbing');\n canvas.classList.remove('bs-grab');\n render();\n if (currentTool === 'select') return;\n // For auto-drag from other tools, just stop — don't create a shape\n return;\n }\n if (!drawing) return;\n drawing = false;\n const c = coords(e);\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n if (currentDraw.length > 1) {\n shapes.push({ type: currentTool, color: currentColor, size: brushSize, alpha: currentTool === 'highlight' ? 0.25 : 1, points: [...currentDraw] });\n }\n currentDraw = [];\n } else if (currentTool === 'rect') {\n shapes.push({ type: 'rect', color: currentColor, size: brushSize, x: startX, y: startY, w: c.x - startX, h: c.y - startY });\n } else if (currentTool === 'circle') {\n const rx = Math.abs(c.x - startX) / 2, ry = Math.abs(c.y - startY) / 2;\n shapes.push({ type: 'circle', color: currentColor, size: brushSize, cx: startX + (c.x - startX) / 2, cy: startY + (c.y - startY) / 2, rx, ry });\n } else if (currentTool === 'arrow') {\n shapes.push({ type: 'arrow', color: currentColor, size: brushSize, x1: startX, y1: startY, x2: c.x, y2: c.y });\n }\n render();\n };\n\n canvas.addEventListener('mouseup', endDraw);\n canvas.addEventListener('mouseleave', (e) => {\n if (dragging) { dragging = false; autoSelectDrag = false; canvas.classList.remove('bs-grabbing'); canvas.classList.remove('bs-grab'); render(); }\n else if (drawing) endDraw(e);\n });\n\n // Delete selected with Backspace/Delete\n const keyHandler = (e: KeyboardEvent) => {\n if (selectedIdx >= 0 && (e.key === 'Delete' || e.key === 'Backspace')) {\n shapes.splice(selectedIdx, 1);\n selectedIdx = -1;\n render();\n }\n };\n document.addEventListener('keydown', keyHandler);\n\n undoBtn.addEventListener('click', () => {\n if (shapes.length) {\n shapes.pop();\n selectedIdx = -1;\n render();\n }\n });\n\n clearBtn.addEventListener('click', () => {\n shapes.length = 0;\n pins.length = 0;\n selectedIdx = -1;\n render();\n renderPins();\n });\n };\n\n // Draw pins onto canvas for final export\n const bakePins = () => {\n for (let i = 0; i < pins.length; i++) {\n const p = pins[i];\n const r = 16;\n // Pin circle\n ctx.beginPath();\n ctx.arc(p.x, p.y - r, r, 0, Math.PI * 2);\n ctx.fillStyle = p.color;\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n // Pin tail\n ctx.beginPath();\n ctx.moveTo(p.x - 8, p.y - 6);\n ctx.lineTo(p.x, p.y + 4);\n ctx.lineTo(p.x + 8, p.y - 6);\n ctx.fillStyle = p.color;\n ctx.fill();\n // Number\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 14px Inter, sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(`${i + 1}`, p.x, p.y - r);\n ctx.textAlign = 'start';\n ctx.textBaseline = 'alphabetic';\n }\n };\n\n return {\n getAnnotation: () => {\n try {\n selectedIdx = -1;\n render();\n bakePins();\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch { return null; }\n },\n getPins: () => pins.map((p, i) => ({ number: i + 1, x: Math.round(p.x), y: Math.round(p.y), note: p.note })),\n };\n}\n\n// ─── Switch Tab ──────────────────────────────────────────\n\nfunction switchTab(tab: typeof activeTab) {\n if (!modal) return;\n activeTab = tab;\n\n // Update tab buttons\n modal.querySelectorAll('.bs-tab').forEach(el => {\n el.classList.toggle('bs-active', (el as HTMLElement).dataset.tab === tab);\n });\n\n // Render content\n const scroll = modal.querySelector('.bs-scroll')!;\n const renderers: Record<typeof activeTab, () => string> = {\n report: tabReport,\n console: tabConsole,\n network: tabNetwork,\n context: tabContext,\n history: tabHistory,\n settings: tabSettings,\n };\n scroll.innerHTML = renderers[tab]();\n scroll.scrollTop = 0;\n bindTabContent();\n}\n\nfunction bindTabContent() {\n if (!modal) return;\n\n if (activeTab === 'history') {\n // Delete buttons\n modal.querySelectorAll('[data-hist-del]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = parseInt((btn as HTMLElement).dataset.histDel!);\n const card = modal!.querySelector(`[data-hist-id=\"${id}\"]`);\n if (!card) return;\n // Show confirm inline\n const existing = card.querySelector('.bs-hist-confirm');\n if (existing) { existing.remove(); return; }\n const confirm = document.createElement('div');\n confirm.className = 'bs-hist-confirm';\n confirm.innerHTML = `<span>Delete this report?</span>`;\n const yes = document.createElement('button');\n yes.type = 'button'; yes.className = 'bs-hist-confirm-yes'; yes.textContent = 'Delete';\n const no = document.createElement('button');\n no.type = 'button'; no.className = 'bs-hist-confirm-no'; no.textContent = 'Cancel';\n yes.addEventListener('click', () => {\n deleteFromHistory(id);\n switchTab('history');\n });\n no.addEventListener('click', () => confirm.remove());\n confirm.appendChild(yes);\n confirm.appendChild(no);\n card.appendChild(confirm);\n });\n });\n\n // Edit buttons\n modal.querySelectorAll('[data-hist-edit]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = parseInt((btn as HTMLElement).dataset.histEdit!);\n const card = modal!.querySelector(`[data-hist-id=\"${id}\"]`);\n if (!card) return;\n const existing = card.querySelector('.bs-hist-edit-wrap');\n if (existing) { existing.remove(); return; }\n // Remove any confirm dialogs\n card.querySelector('.bs-hist-confirm')?.remove();\n\n const entry = getReportHistory().find(e => e.id === id);\n if (!entry) return;\n\n const wrap = document.createElement('div');\n wrap.className = 'bs-hist-edit-wrap';\n wrap.innerHTML = `\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <input class=\"bs-input\" data-edit-title value=\"${esc(entry.title)}\" />\n </div>\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <textarea class=\"bs-textarea\" data-edit-desc style=\"min-height:56px\">${esc(entry.description)}</textarea>\n </div>\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <div class=\"bs-sev-row\">\n <button type=\"button\" class=\"bs-sev-btn bs-sev-low${entry.severity === 'low' ? ' bs-picked' : ''}\" data-edit-sev=\"low\">Low</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-medium${entry.severity === 'medium' ? ' bs-picked' : ''}\" data-edit-sev=\"medium\">Medium</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-high${entry.severity === 'high' ? ' bs-picked' : ''}\" data-edit-sev=\"high\">High</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-critical${entry.severity === 'critical' ? ' bs-picked' : ''}\" data-edit-sev=\"critical\">Critical</button>\n </div>\n </div>\n <div class=\"bs-hist-edit-row\"></div>`;\n\n let editSev = entry.severity;\n card.appendChild(wrap);\n\n // Severity picker in edit\n wrap.querySelectorAll('[data-edit-sev]').forEach(sb => {\n sb.addEventListener('click', () => {\n editSev = (sb as HTMLElement).dataset.editSev!;\n wrap.querySelectorAll('.bs-sev-btn').forEach(b => b.classList.remove('bs-picked'));\n sb.classList.add('bs-picked');\n });\n });\n\n const row = wrap.querySelector('.bs-hist-edit-row')!;\n const save = document.createElement('button');\n save.type = 'button'; save.className = 'bs-hist-save'; save.textContent = 'Save';\n const cancel = document.createElement('button');\n cancel.type = 'button'; cancel.className = 'bs-hist-cancel'; cancel.textContent = 'Cancel';\n\n save.addEventListener('click', () => {\n const newTitle = (wrap.querySelector('[data-edit-title]') as HTMLInputElement).value.trim();\n const newDesc = (wrap.querySelector('[data-edit-desc]') as HTMLTextAreaElement).value.trim();\n if (!newTitle) return;\n updateInHistory(id, { title: newTitle, description: newDesc, severity: editSev });\n switchTab('history');\n });\n cancel.addEventListener('click', () => wrap.remove());\n row.appendChild(save);\n row.appendChild(cancel);\n });\n });\n return;\n }\n\n if (activeTab === 'settings') {\n // Theme picker\n modal.querySelectorAll('[data-set-theme]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = (btn as HTMLElement).dataset.setTheme!;\n setTheme(id);\n // Update picked state\n modal!.querySelectorAll('[data-set-theme]').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n // Layout picker\n modal.querySelectorAll('[data-set-layout]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = (btn as HTMLElement).dataset.setLayout!;\n const layout = getLayoutById(id);\n if (!layout) return;\n currentLayout = layout;\n // Close and reopen with new layout\n close();\n setTimeout(() => {\n activeTab = 'settings';\n open();\n // After open, switch to settings tab\n setTimeout(() => switchTab('settings'), 50);\n }, 400);\n });\n });\n return;\n }\n\n if (activeTab !== 'report') return;\n\n // Category\n modal.querySelectorAll('.bs-cat-btn').forEach(btn => {\n btn.addEventListener('click', () => {\n const cat = (btn as HTMLElement).dataset.cat!;\n (modal!.querySelector('input[name=\"category\"]') as HTMLInputElement).value = cat;\n modal!.querySelectorAll('.bs-cat-btn').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n\n // Severity\n modal.querySelectorAll('.bs-sev-btn').forEach(btn => {\n btn.addEventListener('click', () => {\n const sev = (btn as HTMLElement).dataset.sev!;\n (modal!.querySelector('input[name=\"severity\"]') as HTMLInputElement).value = sev;\n modal!.querySelectorAll('.bs-sev-btn').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n\n // Screenshot\n let screenshotData: string | null = null;\n let annotator: { getAnnotation: () => string | null; getPins: () => { number: number; x: number; y: number; note: string }[] } | null = null;\n\n modal.querySelector('[data-bs-screenshot]')?.addEventListener('click', async () => {\n const titleEl = modal?.querySelector('[data-bs-shot-title]');\n const subEl = modal?.querySelector('[data-bs-shot-sub]');\n const area = modal?.querySelector('[data-bs-screenshot]');\n if (titleEl) titleEl.textContent = 'Capturing...';\n\n if (modal) modal.style.visibility = 'hidden';\n if (backdrop) backdrop.style.visibility = 'hidden';\n await new Promise(r => setTimeout(r, 200));\n screenshotData = await captureScreenshot();\n if (modal) modal.style.visibility = '';\n if (backdrop) backdrop.style.visibility = '';\n\n if (screenshotData) {\n if (titleEl) titleEl.textContent = 'Screenshot captured!';\n if (subEl) subEl.textContent = 'Draw on the image below to highlight the issue';\n area?.classList.add('bs-captured');\n const container = modal?.querySelector('[data-bs-annotate]') as HTMLElement;\n if (container) annotator = setupAnnotation(container, screenshotData);\n } else {\n if (titleEl) titleEl.textContent = 'Screenshot unavailable';\n if (subEl) subEl.textContent = 'Could not capture screenshot on this page';\n }\n });\n\n // Submit\n modal.querySelector('[data-bs-form]')?.addEventListener('submit', async (e) => {\n e.preventDefault();\n const form = e.target as HTMLFormElement;\n const btn = form.querySelector('.bs-submit-btn') as HTMLButtonElement;\n const msgEl = form.querySelector('[data-bs-msg]') as HTMLDivElement;\n\n const title = (form.elements.namedItem('title') as HTMLInputElement).value.trim();\n const description = (form.elements.namedItem('description') as HTMLTextAreaElement).value.trim();\n const severity = (form.elements.namedItem('severity') as HTMLInputElement).value as BugReport['severity'];\n const category = (form.elements.namedItem('category') as HTMLInputElement).value as BugReport['category'];\n\n if (!title) return;\n\n btn.disabled = true;\n btn.textContent = 'Sending...';\n\n const detected = autoDetect();\n\n const report: BugReport = {\n projectId: config.projectId,\n title,\n description,\n category,\n severity,\n tags: detected.tags.length ? detected.tags : undefined,\n context: buildContext(),\n consoleLogs: getLogs(),\n errors: getErrors(),\n networkCaptures: getFailedNetworkCaptures(),\n breadcrumbs: getBreadcrumbs(),\n performance: getPerformanceMetrics() ?? undefined,\n screenshot: screenshotData ?? undefined,\n annotation: annotator?.getAnnotation() ?? undefined,\n pins: annotator?.getPins().length ? annotator.getPins() : undefined,\n createdAt: Date.now(),\n };\n\n const result = await submitReport(report);\n\n // Save to history\n addToHistory({\n title: report.title,\n description: report.description,\n category: report.category,\n severity: report.severity,\n tags: report.tags,\n screenshot: report.screenshot,\n pins: report.pins,\n url: window.location.href,\n createdAt: report.createdAt,\n status: result.success ? 'sent' : 'draft',\n });\n\n if (result.success) {\n msgEl.className = 'bs-msg bs-msg-ok';\n msgEl.innerHTML = `${I.check} Bug reported — thank you!`;\n setTimeout(close, 1200);\n } else {\n msgEl.className = 'bs-msg bs-msg-err';\n msgEl.textContent = result.error ?? 'Could not send. Saved as draft.';\n btn.disabled = false;\n btn.textContent = 'Submit Report';\n }\n });\n}\n\n// ─── Open / Close ────────────────────────────────────────\n\nfunction open() {\n if (isOpen) return;\n isOpen = true;\n activeTab = 'report';\n hideToolbar();\n\n backdrop = document.createElement('div');\n backdrop.className = 'bs-backdrop';\n document.body.appendChild(backdrop);\n\n const fails = getFailedNetworkCaptures().length;\n const errs = getErrors().length;\n\n modal = document.createElement('div');\n modal.className = `bs-modal bs-ly-${currentLayout.id}`;\n applyThemeVars(modal);\n\n const tabsHtml = `\n <div class=\"bs-tabs\">\n <button class=\"bs-tab bs-active\" data-tab=\"report\">${I.report} Report</button>\n <button class=\"bs-tab\" data-tab=\"console\">${I.console} Console <span class=\"bs-tab-badge\">${getLogs().length}</span></button>\n <button class=\"bs-tab\" data-tab=\"network\">${I.network} Network ${fails ? `<span class=\"bs-tab-badge bs-warn\">${fails}</span>` : `<span class=\"bs-tab-badge\">${getNetworkCaptures().length}</span>`}</button>\n <button class=\"bs-tab\" data-tab=\"context\">${I.ctx} Context ${errs ? `<span class=\"bs-tab-badge bs-warn\">${errs}</span>` : ''}</button>\n <button class=\"bs-tab\" data-tab=\"history\">${I.history} History <span class=\"bs-tab-badge\">${getReportHistory().length}</span></button>\n <button class=\"bs-tab\" data-tab=\"settings\" style=\"margin-left:auto\">${I.settings}</button>\n </div>`;\n\n const user = getCurrentUser();\n const initials = user ? user.name.split(' ').map(w => w[0]).join('').toUpperCase().slice(0, 2) : '';\n const pinActive = isPinModeActive();\n\n const headerHtml = user ? `\n <div class=\"bs-hdr\">\n <div class=\"bs-logo\">BugStash</div>\n <div class=\"bs-hdr-right\">\n <button class=\"bs-pin-toggle${pinActive ? ' active' : ''}\" data-bs-pin-toggle title=\"Toggle pin mode\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${pinActive ? 'ON' : 'OFF'}\n </button>\n <div class=\"bs-user-badge\">\n <div class=\"bs-user-avatar\">${initials}</div>\n <span>${user.name.split(' ')[0]}</span>\n </div>\n <button class=\"bs-login-logout\" data-bs-logout title=\"Sign out\">Logout</button>\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>\n </div>` : `\n <div class=\"bs-hdr\" style=\"justify-content:flex-end\">\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>`;\n\n const useSidebar = currentLayout.tabPosition === 'left';\n const useBottomTabs = currentLayout.tabPosition === 'bottom';\n\n // If not logged in, show login form instead of tabs\n const contentHtml = user ? tabReport() : tabLogin();\n\n if (useSidebar) {\n modal.innerHTML = `\n ${headerHtml}\n <div class=\"bs-body-wrap\">\n ${user ? tabsHtml : ''}\n <div class=\"bs-scroll\">${contentHtml}</div>\n </div>`;\n } else if (useBottomTabs) {\n modal.innerHTML = `\n ${headerHtml}\n <div class=\"bs-scroll\">${contentHtml}</div>\n ${user ? `<div class=\"bs-tab-divider\"></div>${tabsHtml}` : ''}`;\n } else {\n modal.innerHTML = `\n ${headerHtml}\n ${user ? `${tabsHtml}<div class=\"bs-tab-divider\"></div>` : ''}\n <div class=\"bs-scroll\">${contentHtml}</div>`;\n }\n document.body.appendChild(modal);\n\n if (fab) fab.classList.add('bs-open');\n\n requestAnimationFrame(() => {\n backdrop?.classList.add('bs-in');\n modal?.classList.add('bs-in');\n });\n\n // Tab switching\n modal.querySelectorAll('.bs-tab').forEach(tab => {\n tab.addEventListener('click', () => switchTab((tab as HTMLElement).dataset.tab as typeof activeTab));\n });\n\n modal.querySelector('[data-bs-close]')?.addEventListener('click', close);\n backdrop.addEventListener('click', close);\n\n // Pin toggle\n modal.querySelector('[data-bs-pin-toggle]')?.addEventListener('click', () => {\n const active = togglePinMode();\n const btn = modal?.querySelector('[data-bs-pin-toggle]');\n if (btn) {\n btn.classList.toggle('active', active);\n btn.innerHTML = `\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${active ? 'ON' : 'OFF'}\n `;\n }\n });\n\n // Logout\n modal.querySelector('[data-bs-logout]')?.addEventListener('click', () => {\n apiLogout();\n close();\n // Reopen to show login form\n setTimeout(() => open(), 300);\n });\n\n // Login form binding\n if (!user) {\n bindLoginForm();\n } else {\n bindTabContent();\n }\n\n const escHandler = (e: KeyboardEvent) => { if (e.key === 'Escape') { close(); document.removeEventListener('keydown', escHandler); } };\n document.addEventListener('keydown', escHandler);\n}\n\nfunction bindLoginForm() {\n if (!modal) return;\n\n const submitBtn = modal.querySelector('#bs-login-submit');\n const emailInput = modal.querySelector('#bs-login-email') as HTMLInputElement;\n const passInput = modal.querySelector('#bs-login-pass') as HTMLInputElement;\n const errorEl = modal.querySelector('#bs-login-error') as HTMLElement;\n\n if (!submitBtn || !emailInput || !passInput) return;\n\n const doLogin = async () => {\n const email = emailInput.value.trim();\n const password = passInput.value;\n\n if (!email || !password) {\n errorEl.textContent = 'Please enter email and password';\n errorEl.style.display = 'block';\n return;\n }\n\n submitBtn.setAttribute('disabled', 'true');\n (submitBtn as HTMLButtonElement).textContent = 'Signing in...';\n errorEl.style.display = 'none';\n\n const result = await apiLogin(email, password, config.projectId);\n\n if (result.success) {\n // Initialize live pins + realtime now that user is logged in\n initLivePins(config.projectId);\n connectRealtime(config.projectId);\n // Reopen panel with full UI\n close();\n setTimeout(() => open(), 300);\n } else {\n errorEl.textContent = result.error || 'Invalid credentials';\n errorEl.style.display = 'block';\n submitBtn.removeAttribute('disabled');\n (submitBtn as HTMLButtonElement).textContent = 'Sign In';\n }\n };\n\n submitBtn.addEventListener('click', doLogin);\n passInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') doLogin(); });\n emailInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') passInput.focus(); });\n\n // Auto-focus email\n setTimeout(() => emailInput.focus(), 100);\n}\n\nfunction close() {\n if (!isOpen) return;\n if (fab) fab.classList.remove('bs-open');\n if (modal) {\n modal.classList.remove('bs-in');\n modal.classList.add('bs-out');\n }\n if (backdrop) backdrop.classList.remove('bs-in');\n\n setTimeout(() => {\n modal?.remove();\n backdrop?.remove();\n modal = null;\n backdrop = null;\n isOpen = false;\n }, 350);\n}\n\n// ─── Theme ───────────────────────────────────────────────\n\nfunction applyThemeVars(el: HTMLElement) {\n for (const [key, val] of Object.entries(currentTheme.vars)) {\n el.style.setProperty(key, val);\n }\n}\n\nexport function setTheme(themeId: string) {\n const theme = getThemeById(themeId);\n if (!theme) return;\n currentTheme = theme;\n if (modal) applyThemeVars(modal);\n if (fab) applyThemeVars(fab);\n if (toolbar) applyThemeVars(toolbar);\n}\n\nexport function getCurrentThemeId(): string {\n return currentTheme.id;\n}\n\n// ─── Layout ──────────────────────────────────────────────\n\nexport function setLayout(layoutId: string) {\n const layout = getLayoutById(layoutId);\n if (!layout) return;\n currentLayout = layout;\n // If modal is open, close and reopen with new layout\n if (isOpen) {\n close();\n setTimeout(open, 400);\n }\n}\n\nexport function getCurrentLayoutId(): string {\n return currentLayout.id;\n}\n\n// ─── Init / Destroy ──────────────────────────────────────\n\nexport function initPanel(cfg: BugStashConfig) {\n config = cfg;\n\n styleEl = document.createElement('style');\n styleEl.textContent = STYLES + LAYOUT_CSS;\n document.head.appendChild(styleEl);\n\n const side = cfg.panelPosition === 'bottom-left' ? 'left' : 'right';\n\n fab = document.createElement('button');\n fab.className = 'bs-fab';\n applyThemeVars(fab);\n fab.innerHTML = `${I.bug}<span class=\"bs-fab-label\">Report a bug</span>`;\n fab.style[side] = '24px';\n fab.addEventListener('click', () => (isOpen ? close() : open()));\n document.body.appendChild(fab);\n\n // ── Quick Action Toolbar ──\n toolbar = document.createElement('div');\n toolbar.className = 'bs-toolbar';\n toolbar.style[side] = '32px';\n applyThemeVars(toolbar);\n\n const isMac = navigator.platform.toUpperCase().includes('MAC');\n const mod = isMac ? '⌘' : 'Ctrl';\n\n const tbButtons: { icon: string; tip: string; kbd: string; action: () => void; id?: string }[] = [\n {\n icon: I.cam,\n tip: 'Screenshot',\n kbd: `${mod}+Shift+S`,\n action: async () => {\n const shot = await captureScreenshot();\n if (shot) {\n // Open panel to report tab with screenshot pre-attached\n if (!isOpen) open();\n setTimeout(() => {\n const area = modal?.querySelector('[data-bs-screenshot]') as HTMLElement;\n if (area) {\n (area as any).__screenshot = shot;\n area.classList.add('bs-captured');\n const title = area.querySelector('[data-bs-shot-title]');\n const sub = area.querySelector('[data-bs-shot-sub]');\n if (title) title.textContent = 'Screenshot captured!';\n if (sub) sub.textContent = 'Click to retake or annotate';\n // Trigger annotation setup\n area.click();\n }\n }, 400);\n }\n },\n },\n {\n icon: I.pin,\n tip: 'Toggle Pins',\n kbd: `${mod}+Shift+P`,\n id: 'bs-tb-pin',\n action: () => {\n const active = togglePinMode();\n const btn = toolbar?.querySelector('#bs-tb-pin');\n if (btn) btn.classList.toggle('bs-active', active);\n // Also update modal pin toggle if open\n const modalBtn = modal?.querySelector('[data-bs-pin-toggle]');\n if (modalBtn) {\n modalBtn.classList.toggle('active', active);\n modalBtn.innerHTML = `\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${active ? 'ON' : 'OFF'}\n `;\n }\n },\n },\n {\n icon: currentTheme.id === 'black' ? I.sun : I.moon,\n tip: 'Toggle Theme',\n kbd: `${mod}+Shift+T`,\n id: 'bs-tb-theme',\n action: () => {\n const newId = currentTheme.id === 'black' ? 'white' : 'black';\n setTheme(newId);\n if (toolbar) applyThemeVars(toolbar);\n const btn = toolbar?.querySelector('#bs-tb-theme');\n if (btn) btn.innerHTML = `${currentTheme.id === 'black' ? I.sun : I.moon}<span class=\"bs-toolbar-tip\">${currentTheme.id === 'black' ? 'Light' : 'Dark'} Mode<span class=\"bs-toolbar-kbd\">${mod}+Shift+T</span></span>`;\n },\n },\n {\n icon: I.report,\n tip: 'Open Panel',\n kbd: `${mod}+Shift+B`,\n action: () => { isOpen ? close() : open(); },\n },\n ];\n\n for (const tb of tbButtons) {\n const btn = document.createElement('button');\n btn.className = 'bs-toolbar-btn';\n if (tb.id) btn.id = tb.id;\n btn.innerHTML = `${tb.icon}<span class=\"bs-toolbar-tip\">${tb.tip}<span class=\"bs-toolbar-kbd\">${tb.kbd}</span></span>`;\n btn.addEventListener('click', (e) => { e.stopPropagation(); tb.action(); });\n toolbar.appendChild(btn);\n }\n\n document.body.appendChild(toolbar);\n\n // Show toolbar on FAB hover or always show after first interaction\n fab.addEventListener('mouseenter', () => { if (!isOpen) showToolbar(); });\n fab.addEventListener('mouseleave', (e) => {\n const related = e.relatedTarget as HTMLElement;\n if (!toolbar?.contains(related)) hideToolbar();\n });\n toolbar.addEventListener('mouseenter', () => showToolbar());\n toolbar.addEventListener('mouseleave', (e) => {\n const related = e.relatedTarget as HTMLElement;\n if (!fab?.contains(related)) hideToolbar();\n });\n\n // ── Keyboard Shortcuts ──\n keyHandler = (e: KeyboardEvent) => {\n const hasModShift = (e.ctrlKey || e.metaKey) && e.shiftKey;\n if (!hasModShift) return;\n\n if (e.key === 'B' || e.key === 'b') {\n e.preventDefault();\n isOpen ? close() : open();\n } else if (e.key === 'S' || e.key === 's') {\n e.preventDefault();\n tbButtons[0].action(); // Screenshot\n } else if (e.key === 'P' || e.key === 'p') {\n e.preventDefault();\n tbButtons[1].action(); // Pin toggle\n } else if (e.key === 'T' || e.key === 't') {\n e.preventDefault();\n tbButtons[2].action(); // Theme toggle\n }\n };\n document.addEventListener('keydown', keyHandler);\n}\n\nfunction showToolbar() {\n if (toolbarVisible || isOpen) return;\n toolbarVisible = true;\n toolbar?.classList.add('bs-show');\n}\n\nfunction hideToolbar() {\n toolbarVisible = false;\n toolbar?.classList.remove('bs-show');\n}\n\nexport function destroyPanel() {\n close();\n fab?.remove();\n fab = null;\n toolbar?.remove();\n toolbar = null;\n toolbarVisible = false;\n styleEl?.remove();\n styleEl = null;\n if (keyHandler) document.removeEventListener('keydown', keyHandler);\n keyHandler = null;\n}\n","/**\n * Annotation drawing tool for screenshots.\n * Provides a canvas overlay for drawing arrows, rectangles, circles, and freehand on screenshots.\n */\n\nimport type { AnnotationShape } from '@bugstash/shared';\n\nexport { AnnotationShape };\n\nexport interface AnnotationResult {\n dataUrl: string; // The annotated screenshot as a data URL\n annotations: AnnotationShape[];\n}\n\nlet overlay: HTMLDivElement | null = null;\nlet canvas: HTMLCanvasElement | null = null;\nlet ctx: CanvasRenderingContext2D | null = null;\nlet screenshotImg: HTMLImageElement | null = null;\nlet currentTool: AnnotationShape['type'] = 'freehand';\nlet currentColor = '#ef4444';\nlet lineWidth = 3;\nlet shapes: AnnotationShape[] = [];\nlet currentShape: AnnotationShape | null = null;\nlet isDrawing = false;\nlet resolvePromise: ((result: AnnotationResult | null) => void) | null = null;\n\nconst TOOLS: { id: AnnotationShape['type']; label: string; icon: string }[] = [\n { id: 'freehand', label: 'Draw', icon: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z' },\n { id: 'rectangle', label: 'Rect', icon: 'M3 3h18v18H3V3zm2 2v14h14V5H5z' },\n { id: 'circle', label: 'Circle', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z' },\n { id: 'arrow', label: 'Arrow', icon: 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z' },\n];\n\nconst COLORS = ['#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6', '#ffffff', '#000000'];\n\n/**\n * Opens the annotation editor overlay on a screenshot.\n * Returns a promise that resolves when the user saves or cancels.\n */\nexport function openAnnotationEditor(screenshotDataUrl: string): Promise<AnnotationResult | null> {\n return new Promise((resolve) => {\n resolvePromise = resolve;\n shapes = [];\n currentShape = null;\n currentTool = 'freehand';\n currentColor = '#ef4444';\n\n createOverlay(screenshotDataUrl);\n });\n}\n\nfunction createOverlay(screenshotDataUrl: string) {\n if (overlay) overlay.remove();\n\n overlay = document.createElement('div');\n overlay.id = 'bs-annotation-overlay';\n\n const style = document.createElement('style');\n style.textContent = `\n #bs-annotation-overlay {\n position: fixed; inset: 0; z-index: 2147483647;\n background: rgba(0,0,0,0.85);\n display: flex; flex-direction: column;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n .bs-ann-toolbar {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 16px; background: #1a1d2e;\n border-bottom: 1px solid #333;\n }\n .bs-ann-tool {\n width: 36px; height: 36px; border-radius: 8px;\n border: 2px solid transparent; background: #222639;\n cursor: pointer; display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n .bs-ann-tool:hover { border-color: #555; }\n .bs-ann-tool.active { border-color: #6E9ED0; background: #2a3550; }\n .bs-ann-tool svg { width: 18px; height: 18px; fill: #ccc; }\n .bs-ann-color {\n width: 24px; height: 24px; border-radius: 50%;\n border: 2px solid transparent; cursor: pointer;\n transition: transform 0.15s;\n }\n .bs-ann-color:hover { transform: scale(1.15); }\n .bs-ann-color.active { border-color: #fff; }\n .bs-ann-sep { width: 1px; height: 28px; background: #444; margin: 0 6px; }\n .bs-ann-btn {\n padding: 8px 18px; border-radius: 8px; border: none;\n font-size: 13px; font-weight: 600; cursor: pointer;\n margin-left: auto;\n }\n .bs-ann-cancel { background: #333; color: #aaa; margin-left: 8px; }\n .bs-ann-cancel:hover { background: #444; color: #fff; }\n .bs-ann-save { background: linear-gradient(135deg, #6E9ED0, #8FAFD6); color: #fff; }\n .bs-ann-save:hover { opacity: 0.9; }\n .bs-ann-undo { background: #333; color: #aaa; font-size: 12px; padding: 6px 12px; }\n .bs-ann-undo:hover { color: #fff; }\n .bs-ann-canvas-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center;\n overflow: hidden; padding: 16px;\n }\n .bs-ann-canvas-wrap canvas { cursor: crosshair; border-radius: 4px; }\n `;\n\n overlay.appendChild(style);\n\n // Toolbar\n const toolbar = document.createElement('div');\n toolbar.className = 'bs-ann-toolbar';\n\n // Tool buttons\n for (const tool of TOOLS) {\n const btn = document.createElement('button');\n btn.className = `bs-ann-tool${tool.id === currentTool ? ' active' : ''}`;\n btn.title = tool.label;\n btn.innerHTML = `<svg viewBox=\"0 0 24 24\"><path d=\"${tool.icon}\"/></svg>`;\n btn.addEventListener('click', () => {\n currentTool = tool.id;\n toolbar.querySelectorAll('.bs-ann-tool').forEach((b) => b.classList.remove('active'));\n btn.classList.add('active');\n });\n toolbar.appendChild(btn);\n }\n\n toolbar.appendChild(createSep());\n\n // Color buttons\n for (const color of COLORS) {\n const btn = document.createElement('button');\n btn.className = `bs-ann-color${color === currentColor ? ' active' : ''}`;\n btn.style.background = color;\n btn.addEventListener('click', () => {\n currentColor = color;\n toolbar.querySelectorAll('.bs-ann-color').forEach((b) => b.classList.remove('active'));\n btn.classList.add('active');\n });\n toolbar.appendChild(btn);\n }\n\n toolbar.appendChild(createSep());\n\n // Undo\n const undoBtn = document.createElement('button');\n undoBtn.className = 'bs-ann-btn bs-ann-undo';\n undoBtn.textContent = 'Undo';\n undoBtn.addEventListener('click', () => {\n shapes.pop();\n redrawCanvas();\n });\n toolbar.appendChild(undoBtn);\n\n // Save / Cancel\n const saveBtn = document.createElement('button');\n saveBtn.className = 'bs-ann-btn bs-ann-save';\n saveBtn.textContent = 'Save';\n saveBtn.addEventListener('click', saveAnnotation);\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'bs-ann-btn bs-ann-cancel';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n cleanup();\n resolvePromise?.(null);\n });\n\n toolbar.appendChild(saveBtn);\n toolbar.appendChild(cancelBtn);\n overlay.appendChild(toolbar);\n\n // Canvas\n const canvasWrap = document.createElement('div');\n canvasWrap.className = 'bs-ann-canvas-wrap';\n\n canvas = document.createElement('canvas');\n ctx = canvas.getContext('2d')!;\n canvasWrap.appendChild(canvas);\n overlay.appendChild(canvasWrap);\n\n document.body.appendChild(overlay);\n\n // Load screenshot\n screenshotImg = new Image();\n screenshotImg.onload = () => {\n if (!canvas || !ctx || !screenshotImg) return;\n\n // Fit to viewport\n const maxW = window.innerWidth - 32;\n const maxH = window.innerHeight - 100;\n let w = screenshotImg.width;\n let h = screenshotImg.height;\n const scale = Math.min(1, maxW / w, maxH / h);\n w = Math.round(w * scale);\n h = Math.round(h * scale);\n\n canvas.width = w;\n canvas.height = h;\n redrawCanvas();\n setupCanvasEvents();\n };\n screenshotImg.src = screenshotDataUrl;\n}\n\nfunction createSep(): HTMLDivElement {\n const sep = document.createElement('div');\n sep.className = 'bs-ann-sep';\n return sep;\n}\n\nfunction setupCanvasEvents() {\n if (!canvas) return;\n\n canvas.addEventListener('mousedown', (e) => {\n isDrawing = true;\n const { x, y } = getCanvasPos(e);\n\n currentShape = {\n type: currentTool,\n color: currentColor,\n lineWidth,\n points: [{ x, y }],\n x, y, width: 0, height: 0,\n };\n });\n\n canvas.addEventListener('mousemove', (e) => {\n if (!isDrawing || !currentShape) return;\n const { x, y } = getCanvasPos(e);\n\n if (currentShape.type === 'freehand') {\n currentShape.points!.push({ x, y });\n } else {\n currentShape.width = x - currentShape.x!;\n currentShape.height = y - currentShape.y!;\n }\n redrawCanvas();\n drawShape(currentShape);\n });\n\n const endDraw = () => {\n if (isDrawing && currentShape) {\n shapes.push(currentShape);\n currentShape = null;\n }\n isDrawing = false;\n redrawCanvas();\n };\n\n canvas.addEventListener('mouseup', endDraw);\n canvas.addEventListener('mouseleave', endDraw);\n}\n\nfunction getCanvasPos(e: MouseEvent): { x: number; y: number } {\n const rect = canvas!.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n}\n\nfunction redrawCanvas() {\n if (!ctx || !canvas || !screenshotImg) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(screenshotImg, 0, 0, canvas.width, canvas.height);\n for (const shape of shapes) {\n drawShape(shape);\n }\n}\n\nfunction drawShape(shape: AnnotationShape) {\n if (!ctx) return;\n ctx.strokeStyle = shape.color;\n ctx.fillStyle = shape.color;\n ctx.lineWidth = shape.lineWidth;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n switch (shape.type) {\n case 'freehand': {\n if (!shape.points || shape.points.length < 2) return;\n ctx.beginPath();\n ctx.moveTo(shape.points[0].x, shape.points[0].y);\n for (let i = 1; i < shape.points.length; i++) {\n ctx.lineTo(shape.points[i].x, shape.points[i].y);\n }\n ctx.stroke();\n break;\n }\n case 'rectangle': {\n ctx.strokeRect(shape.x!, shape.y!, shape.width!, shape.height!);\n break;\n }\n case 'circle': {\n const cx = shape.x! + shape.width! / 2;\n const cy = shape.y! + shape.height! / 2;\n const rx = Math.abs(shape.width!) / 2;\n const ry = Math.abs(shape.height!) / 2;\n ctx.beginPath();\n ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n ctx.stroke();\n break;\n }\n case 'arrow': {\n const startX = shape.x!;\n const startY = shape.y!;\n const endX = shape.x! + shape.width!;\n const endY = shape.y! + shape.height!;\n const headLen = 14;\n const angle = Math.atan2(endY - startY, endX - startX);\n\n ctx.beginPath();\n ctx.moveTo(startX, startY);\n ctx.lineTo(endX, endY);\n ctx.stroke();\n\n // Arrowhead\n ctx.beginPath();\n ctx.moveTo(endX, endY);\n ctx.lineTo(endX - headLen * Math.cos(angle - Math.PI / 6), endY - headLen * Math.sin(angle - Math.PI / 6));\n ctx.lineTo(endX - headLen * Math.cos(angle + Math.PI / 6), endY - headLen * Math.sin(angle + Math.PI / 6));\n ctx.closePath();\n ctx.fill();\n break;\n }\n }\n}\n\nfunction saveAnnotation() {\n if (!canvas) { cleanup(); resolvePromise?.(null); return; }\n const dataUrl = canvas.toDataURL('image/png');\n const result: AnnotationResult = { dataUrl, annotations: shapes };\n cleanup();\n resolvePromise?.(result);\n}\n\nfunction cleanup() {\n overlay?.remove();\n overlay = null;\n canvas = null;\n ctx = null;\n screenshotImg = null;\n shapes = [];\n currentShape = null;\n isDrawing = false;\n}\n","import type { BugStashConfig } from '@bugstash/shared';\nimport { initPanel, destroyPanel, setTheme, getCurrentThemeId, setLayout, getCurrentLayoutId } from './panel';\nimport { initLogger, getLogs, clearLogs, restoreConsole } from './logger';\nimport { initNetwork, getNetworkCaptures, getFailedNetworkCaptures, clearNetworkCaptures, restoreNetwork } from './network';\nimport { initErrors, getErrors, clearErrors, restoreErrors } from './errors';\nimport { initBreadcrumbs, getBreadcrumbs, addBreadcrumb, clearBreadcrumbs, restoreBreadcrumbs } from './breadcrumbs';\nimport { initPerformance, getPerformanceMetrics, restorePerformance } from './performance';\nimport { setEndpoint, getCurrentUser, login, logout } from './api';\nimport { getThemes, getThemeById } from './themes';\nimport { getLayouts, getLayoutById } from './layouts';\nimport { initLivePins, destroyLivePins, togglePinMode, isPinModeActive } from './livepins';\nimport { connectRealtime, disconnectRealtime, isConnected } from './realtime';\nimport { openAnnotationEditor, type AnnotationResult } from './annotation';\nimport { redactString, redactObject } from './redact';\n\nexport type { AnnotationResult };\n\nexport type {\n BugStashConfig,\n LogEntry,\n NetworkEntry,\n ErrorEntry,\n Breadcrumb,\n PerformanceMetrics,\n BugReport,\n ReportContext,\n APIResponse,\n AuthUser,\n AuthTokens,\n LivePin,\n PinComment,\n Member,\n Organization,\n Project,\n Webhook,\n WebhookEvent,\n Integration,\n IntegrationType,\n SourceMap,\n PlanLimits,\n QuotaStatus,\n OrgBranding,\n AnnotationShape,\n TwoFactorSetup,\n TwoFactorStatus,\n DuplicateMatch,\n} from '@bugstash/shared';\n\nlet initialized = false;\n\n/**\n * Auto-detect the environment from the current hostname when `environment`\n * is not explicitly set.\n *\n * Production hostnames → SDK stays silent (no UI, no network calls)\n * Staging/preview hosts → SDK activates in staging mode\n * localhost / 127.x / *.local / IP → SDK activates in development mode\n *\n * Users can always override by passing `environment` explicitly.\n */\nfunction detectEnvironment(): 'development' | 'staging' | 'production' {\n if (typeof window === 'undefined') return 'production';\n const host = window.location.hostname;\n\n // Explicit localhost / loopback / local network\n if (\n host === 'localhost' ||\n host === '127.0.0.1' ||\n host === '0.0.0.0' ||\n host.endsWith('.local') ||\n /^192\\.168\\./.test(host) ||\n /^10\\./.test(host) ||\n /^172\\.(1[6-9]|2\\d|3[01])\\./.test(host)\n ) return 'development';\n\n // Common staging/preview patterns\n if (\n host.includes('staging') ||\n host.includes('stage') ||\n host.includes('preview') ||\n host.includes('preprod') ||\n host.includes('pre-prod') ||\n host.includes('qa.') ||\n host.includes('.qa') ||\n host.includes('test.') ||\n host.includes('.dev.') ||\n host.includes('vercel.app') || // Vercel preview deployments\n host.includes('netlify.app') || // Netlify preview deployments\n host.includes('pages.dev') || // Cloudflare Pages previews\n host.includes('ngrok.io') || // ngrok tunnels\n host.includes('ngrok-free.app') || // ngrok free tier\n host.includes('localhost.run') || // localhost.run tunnels\n host.includes('loca.lt') // localtunnel\n ) return 'staging';\n\n // Everything else is treated as production — SDK will be silent\n return 'production';\n}\n\nexport const BugStash = {\n init(options: BugStashConfig) {\n if (initialized) return;\n if (typeof window === 'undefined') return;\n\n const env = options.environment ?? detectEnvironment();\n if (env === 'production') return;\n\n initialized = true;\n\n if (options.endpoint) setEndpoint(options.endpoint);\n\n // Order matters: breadcrumbs first (other modules push to it)\n initBreadcrumbs(options.maxBreadcrumbs);\n initLogger(options.maxLogs);\n initNetwork(options.maxNetworkCaptures);\n initErrors();\n if (options.enablePerformance !== false) initPerformance();\n initPanel(options);\n\n // Init live pins if enabled and user is logged in\n if (options.enableLivePins !== false) {\n const user = getCurrentUser();\n if (user) {\n initLivePins(options.projectId);\n connectRealtime(options.projectId);\n }\n }\n },\n\n destroy() {\n if (!initialized) return;\n destroyPanel();\n destroyLivePins();\n disconnectRealtime();\n restoreConsole();\n restoreNetwork();\n restoreErrors();\n restoreBreadcrumbs();\n restorePerformance();\n initialized = false;\n },\n\n // Programmatic API\n getLogs,\n clearLogs,\n getNetworkCaptures,\n getFailedNetworkCaptures,\n clearNetworkCaptures,\n getErrors,\n clearErrors,\n getBreadcrumbs,\n clearBreadcrumbs,\n getPerformanceMetrics,\n addBreadcrumb,\n // Theme API\n getThemes,\n getThemeById,\n setTheme,\n getCurrentThemeId,\n // Layout API\n getLayouts,\n getLayoutById,\n setLayout,\n getCurrentLayoutId,\n // Auth API\n getCurrentUser,\n login,\n logout,\n // Live Pins API\n togglePinMode,\n isPinModeActive,\n // Real-time\n isConnected,\n // Annotation\n openAnnotationEditor,\n // PII Redaction\n redactString,\n redactObject,\n};\n\nexport default BugStash;\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["crumbs","maxCrumbs","clickHandler","inputHandler","popstateHandler","hashHandler","getSelector","el","tag","cls","text","label","addBreadcrumb","crumb","initBreadcrumbs","max","e","target","inputTimers","existing","isPassword","getBreadcrumbs","clearBreadcrumbs","restoreBreadcrumbs","REDACT_PLACEHOLDER","PATTERNS","match","eqIdx","colonIdx","redactString","input","result","pattern","replacement","PATTERNS","redactLogArgs","args","redactString","redactObject","obj","result","key","value","lk","REDACT_PLACEHOLDER","originals","logs","maxLogs","serialize","args","a","capture","level","entry","redactLogArgs","addBreadcrumb","initLogger","max","getLogs","clearLogs","restoreConsole","captures","maxCaptures","originalFetch","originalXHROpen","originalXHRSend","record","entry","addBreadcrumb","shortenUrl","url","u","params","key","lk","qs","redactString","patchFetch","input","init","method","rawUrl","start","response","err","patchXHR","rest","body","initNetwork","max","getNetworkCaptures","getFailedNetworkCaptures","c","clearNetworkCaptures","restoreNetwork","errors","onErrorHandler","onRejectionHandler","initErrors","event","entry","addBreadcrumb","reason","message","getErrors","clearErrors","restoreErrors","metrics","lcpObserver","clsObserver","fidObserver","initPerformance","onLoad","nav","paints","p","mem","list","entries","last","clsValue","entry","getPerformanceMetrics","restorePerformance","showFlashAnimation","flash","style","captureScreenshot","result","captureSvgForeignObject","w","h","clone","sourceElements","cloneElements","i","computed","el","props","prop","img","src","html","svg","blob","url","resolve","canvas","ctx","PRIMARY_ENDPOINT","FALLBACK_ENDPOINT","endpoint","_usingFallback","setEndpoint","url","getEndpoint","fetchWithFallback","init","err","previousEndpoint","fallbackUrl","STORAGE_KEY","getStoredAuth","raw","auth","setStoredAuth","clearStoredAuth","getCurrentUser","getAccessToken","authHeaders","res","data","login","email","password","projectId","logout","submitReport","report","headers","authHeaders","fetchWithFallback","endpoint","fetchPagePins","projectId","pathname","createPin","pin","updatePin","pinId","updates","deletePin","fetchComments","createComment","body","mentions","fetchProjectMembers","QUEUE_KEY","queueOfflineAction","action","queue","getOfflineQueue","flushOfflineQueue","flushed","remaining","result","THEMES","getThemes","getThemeById","id","getDefaultTheme","LAYOUTS","getLayouts","getLayoutById","id","l","getDefaultLayout","LAYOUT_CSS","pollTimer","lastPollTime","POLL_INTERVAL","handlers","currentProjectId","knownPinIds","connectRealtime","projectId","startPolling","poll","token","getAccessToken","endpoint","getEndpoint","pathname","res","data","pins","serverTime","pin","emit","disconnectRealtime","onRealtimeEvent","type","handler","event","h","registerKnownPins","pinIds","isConnected","pollTimer","projectId","container","pins","members","pinMode","activePopup","currentPathname","PIN_COLORS","initLivePins","projId","createOverlay","loadPins","loadMembers","setupRealtimeListeners","watchNavigation","destroyLivePins","togglePinMode","enabled","isPinModeActive","style","e","x","y","el","showNewPinForm","result","fetchPagePins","registerKnownPins","p","renderPins","fetchProjectMembers","pin","i","dot","color","showPinPopup","timeAgo","ts","diff","mins","hrs","statusColor","status","dotEl","closePopup","popup","commentsRes","fetchComments","comments","user","getCurrentUser","canManage","escapeHtml","input","body","res","createComment","commentsEl","c","queueOfflineAction","updatePin","deletePin","getSelector","selector","classes","parent","siblings","idx","getXPath","parts","current","sib","pageX","pageY","targetEl","form","rect","memberOptions","m","title","desc","priority","category","assigneeId","xpath","logs","getLogs","l","errors","getErrors","netErrors","getFailedNetworkCaptures","n","screenshot","captureScreenshot","pinData","createPin","onRealtimeEvent","event","updated","id","comment","lastPath","check","origPush","origReplace","args","str","div","config","fab","toolbar","modal","backdrop","styleEl","keyHandler","isOpen","toolbarVisible","activeTab","currentTheme","getDefaultTheme","currentLayout","getDefaultLayout","I","STYLES","tabLogin","esc","s","timeAgo","ts","fmtTime","HISTORY_KEY","getReportHistory","saveReportHistory","entries","addToHistory","entry","id","deleteFromHistory","e","updateInHistory","updates","idx","buildContext","config","autoDetect","errors","getErrors","logs","getLogs","net","getNetworkCaptures","failedNet","getFailedNetworkCaptures","crumbs","getBreadcrumbs","perf","getPerformanceMetrics","consoleErrors","l","severity","tags","tabReport","d","categories","hasIssues","c","tabConsole","lvMap","tabNetwork","caps","n","tabContext","html","errs","bars","label","val","max","pct","p","b","ctx","tabHistory","catLabels","fmtDate","diffMs","diffMin","diffH","diffD","pinsHtml","tabSettings","themes","getThemes","layouts","getLayouts","t","setupAnnotation","container","screenshotData","COLORS","currentColor","currentTool","brushSize","zoom","isDark","shapes","pins","selectedIdx","hoveredIdx","dragging","drawing","dragOffX","dragOffY","startX","startY","currentDraw","PIN_COLORS","img","wrap","viewport","canvas","toolbar","tIcons","toolNames","toolBtns","setTool","btn","color","i","sizeSlider","right","mkBtn","title","svg","zoomOut","zoomLabel","zoomIn","zoomReset","undoBtn","clearBtn","applyZoom","el","pinLayer","pinList","renderPins","pin","pctX","pctY","pinDragging","onMove","me","r","onUp","item","del","outlineColor","drawOutline","fn","lw","renderShape","preview","alpha","stroke","angle","headLen","fontSize","isSelected","isHovered","shapeBounds","handles","hx","hy","render","x","y","minX","minY","maxX","maxY","hitTest","pad","moveShape","dx","dy","scale","samplePoints","totalBrightness","sx","sy","px","coords","autoSelectDrag","hit","note","input","rx","ry","cx2","cy2","endDraw","keyHandler","bakePins","switchTab","tab","modal","activeTab","scroll","renderers","bindTabContent","card","existing","confirm","yes","no","editSev","sb","row","save","cancel","newTitle","newDesc","setTheme","layout","getLayoutById","close","open","cat","sev","annotator","titleEl","subEl","area","backdrop","captureScreenshot","form","msgEl","description","category","detected","report","result","submitReport","isOpen","hideToolbar","fails","applyThemeVars","tabsHtml","user","getCurrentUser","initials","w","pinActive","isPinModeActive","headerHtml","useSidebar","useBottomTabs","contentHtml","fab","active","togglePinMode","logout","bindLoginForm","escHandler","submitBtn","emailInput","passInput","errorEl","doLogin","email","password","login","initLivePins","connectRealtime","key","themeId","theme","getThemeById","getCurrentThemeId","setLayout","layoutId","getCurrentLayoutId","initPanel","cfg","styleEl","LAYOUT_CSS","side","mod","tbButtons","shot","sub","modalBtn","newId","tb","showToolbar","related","toolbarVisible","destroyPanel","overlay","canvas","ctx","screenshotImg","currentTool","currentColor","lineWidth","shapes","currentShape","isDrawing","resolvePromise","TOOLS","COLORS","openAnnotationEditor","screenshotDataUrl","resolve","createOverlay","style","toolbar","tool","btn","b","createSep","color","undoBtn","redrawCanvas","saveBtn","saveAnnotation","cancelBtn","cleanup","canvasWrap","maxW","maxH","w","h","scale","setupCanvasEvents","sep","e","x","y","getCanvasPos","drawShape","endDraw","rect","shape","i","cx","cy","rx","ry","startX","startY","endX","endY","headLen","angle","result","initialized","detectEnvironment","host","BugStash","options","setEndpoint","initBreadcrumbs","initLogger","initNetwork","initErrors","initPerformance","initPanel","getCurrentUser","initLivePins","connectRealtime","destroyPanel","destroyLivePins","disconnectRealtime","restoreConsole","restoreNetwork","restoreErrors","restoreBreadcrumbs","restorePerformance","getLogs","clearLogs","getNetworkCaptures","getFailedNetworkCaptures","clearNetworkCaptures","getErrors","clearErrors","getBreadcrumbs","clearBreadcrumbs","getPerformanceMetrics","addBreadcrumb","getThemes","getThemeById","setTheme","getCurrentThemeId","getLayouts","getLayoutById","setLayout","getCurrentLayoutId","login","logout","togglePinMode","isPinModeActive","isConnected","openAnnotationEditor","redactString","redactObject","index_default"]}
1
+ {"version":3,"sources":["../src/breadcrumbs.ts","../src/redact.ts","../src/logger.ts","../src/network.ts","../src/errors.ts","../src/performance.ts","../src/screenshot.ts","../src/api.ts","../src/themes.ts","../src/layouts.ts","../src/realtime.ts","../src/livepins.ts","../src/panel.ts","../src/annotation.ts","../src/index.ts"],"sourcesContent":["import type { Breadcrumb } from '@bugstash/shared';\n\nlet crumbs: Breadcrumb[] = [];\nlet maxCrumbs = 50;\nlet clickHandler: ((e: MouseEvent) => void) | null = null;\nlet inputHandler: ((e: Event) => void) | null = null;\nlet popstateHandler: (() => void) | null = null;\nlet hashHandler: (() => void) | null = null;\n\nfunction getSelector(el: Element): string {\n if (el.id) return `#${el.id}`;\n const tag = el.tagName.toLowerCase();\n const cls = el.className && typeof el.className === 'string'\n ? '.' + el.className.trim().split(/\\s+/).slice(0, 2).join('.')\n : '';\n const text = (el.textContent || '').trim().slice(0, 30);\n const label = text ? ` \"${text}\"` : '';\n return `${tag}${cls}${label}`;\n}\n\nexport function addBreadcrumb(crumb: Breadcrumb) {\n crumbs.push(crumb);\n if (crumbs.length > maxCrumbs) crumbs.shift();\n}\n\nexport function initBreadcrumbs(max?: number) {\n if (max) maxCrumbs = max;\n\n // Track clicks\n clickHandler = (e: MouseEvent) => {\n const target = e.target as Element;\n if (!target || !target.tagName) return;\n addBreadcrumb({\n type: 'click',\n category: 'ui',\n message: `Clicked ${getSelector(target)}`,\n timestamp: Date.now(),\n data: { x: e.clientX, y: e.clientY, selector: getSelector(target) },\n });\n };\n document.addEventListener('click', clickHandler, true);\n\n // Track input changes (debounced per element)\n const inputTimers = new WeakMap<Element, number>();\n inputHandler = (e: Event) => {\n const target = e.target as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n if (!target || !target.tagName) return;\n const tag = target.tagName.toLowerCase();\n if (tag !== 'input' && tag !== 'textarea' && tag !== 'select') return;\n\n // Debounce per element\n const existing = inputTimers.get(target);\n if (existing) clearTimeout(existing);\n inputTimers.set(\n target,\n window.setTimeout(() => {\n const isPassword = target instanceof HTMLInputElement && target.type === 'password';\n addBreadcrumb({\n type: 'input',\n category: 'ui',\n message: `Input ${getSelector(target)}`,\n timestamp: Date.now(),\n data: {\n selector: getSelector(target),\n value: isPassword ? '[redacted]' : undefined,\n },\n });\n }, 300),\n );\n };\n document.addEventListener('input', inputHandler, true);\n\n // Track navigation\n popstateHandler = () => {\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${window.location.pathname}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n };\n window.addEventListener('popstate', popstateHandler);\n\n hashHandler = () => {\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Hash changed to ${window.location.hash}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n };\n window.addEventListener('hashchange', hashHandler);\n\n // Initial breadcrumb\n addBreadcrumb({\n type: 'navigation',\n category: 'navigation',\n message: `Page loaded: ${window.location.pathname}`,\n timestamp: Date.now(),\n data: { url: window.location.href },\n });\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...crumbs];\n}\n\nexport function clearBreadcrumbs() {\n crumbs = [];\n}\n\nexport function restoreBreadcrumbs() {\n if (clickHandler) document.removeEventListener('click', clickHandler, true);\n if (inputHandler) document.removeEventListener('input', inputHandler, true);\n if (popstateHandler) window.removeEventListener('popstate', popstateHandler);\n if (hashHandler) window.removeEventListener('hashchange', hashHandler);\n clickHandler = null;\n inputHandler = null;\n popstateHandler = null;\n hashHandler = null;\n}\n","/**\n * PII/sensitive data redaction for captured data.\n * Masks passwords, tokens, credit cards, SSNs, emails in captured logs and network data.\n */\n\nconst REDACT_PLACEHOLDER = '[REDACTED]';\n\n// Patterns for common sensitive data\nconst PATTERNS: [RegExp, string | ((match: string) => string)][] = [\n // Credit card numbers (Visa, MC, Amex, etc.)\n [/\\b(?:\\d[ -]*?){13,19}\\b/g, '[CC_REDACTED]'],\n // SSN\n [/\\b\\d{3}-\\d{2}-\\d{4}\\b/g, '[SSN_REDACTED]'],\n // Email addresses (in log strings, not for user context)\n // Intentionally NOT redacting emails since they're often needed for debugging\n // Bearer tokens\n [/Bearer\\s+[A-Za-z0-9\\-._~+/]+=*/g, 'Bearer [TOKEN_REDACTED]'],\n // JWT tokens (xxx.yyy.zzz pattern)\n [/eyJ[A-Za-z0-9_-]+\\.eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+/g, '[JWT_REDACTED]'],\n // API keys (long hex/base64 strings that look like keys)\n [/(?:api[_-]?key|apikey|secret|token|password|passwd|authorization)['\":\\s=]+['\"]?([A-Za-z0-9\\-._~+/]{20,})['\"]?/gi, (match) => {\n const eqIdx = match.search(/[=:]/);\n return match.slice(0, eqIdx + 1) + ' ' + REDACT_PLACEHOLDER;\n }],\n // AWS access keys\n [/AKIA[0-9A-Z]{16}/g, '[AWS_KEY_REDACTED]'],\n // Generic password fields in JSON\n [/\"(?:password|passwd|secret|token|access_token|refresh_token|api_key|apiKey|private_key)\":\\s*\"[^\"]*\"/gi, (match) => {\n const colonIdx = match.indexOf(':');\n return match.slice(0, colonIdx + 1) + ' \"' + REDACT_PLACEHOLDER + '\"';\n }],\n];\n\n// Header names that should be redacted\nconst SENSITIVE_HEADERS = new Set([\n 'authorization',\n 'cookie',\n 'set-cookie',\n 'x-api-key',\n 'x-auth-token',\n 'x-csrf-token',\n 'proxy-authorization',\n]);\n\n/** Redact sensitive data from a string. */\nexport function redactString(input: string): string {\n let result = input;\n for (const [pattern, replacement] of PATTERNS) {\n if (typeof replacement === 'function') {\n result = result.replace(pattern, replacement as any);\n } else {\n result = result.replace(pattern, replacement);\n }\n }\n return result;\n}\n\n/** Redact sensitive headers from a headers object. */\nexport function redactHeaders(headers: Record<string, string> | undefined): Record<string, string> | undefined {\n if (!headers) return headers;\n const redacted: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (SENSITIVE_HEADERS.has(key.toLowerCase())) {\n redacted[key] = REDACT_PLACEHOLDER;\n } else {\n redacted[key] = redactString(value);\n }\n }\n return redacted;\n}\n\n/** Redact an array of log argument strings. */\nexport function redactLogArgs(args: string[]): string[] {\n return args.map(redactString);\n}\n\n/** Redact sensitive data from serialized objects. */\nexport function redactObject(obj: any): any {\n if (typeof obj === 'string') return redactString(obj);\n if (Array.isArray(obj)) return obj.map(redactObject);\n if (obj && typeof obj === 'object') {\n const result: any = {};\n for (const [key, value] of Object.entries(obj)) {\n const lk = key.toLowerCase();\n if (lk.includes('password') || lk.includes('secret') || lk.includes('token') ||\n lk.includes('apikey') || lk.includes('api_key') || lk.includes('private')) {\n result[key] = REDACT_PLACEHOLDER;\n } else {\n result[key] = redactObject(value);\n }\n }\n return result;\n }\n return obj;\n}\n","import type { LogEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\nimport { redactLogArgs } from './redact';\n\nconst originals = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n info: console.info,\n};\n\nlet logs: LogEntry[] = [];\nlet maxLogs = 50;\n\nfunction serialize(args: any[]): string[] {\n return args.map((a) => {\n if (a instanceof Error) return `${a.name}: ${a.message}\\n${a.stack ?? ''}`;\n if (typeof a === 'object') {\n try {\n return JSON.stringify(a, null, 2);\n } catch {\n return String(a);\n }\n }\n return String(a);\n });\n}\n\nfunction capture(level: LogEntry['level'], args: any[]) {\n const entry: LogEntry = {\n level,\n args: redactLogArgs(serialize(args)),\n timestamp: Date.now(),\n };\n if (level === 'error') {\n entry.stack = new Error().stack?.split('\\n').slice(2).join('\\n');\n }\n logs.push(entry);\n if (logs.length > maxLogs) logs.shift();\n\n addBreadcrumb({\n type: 'console',\n category: `console.${level}`,\n message: entry.args.join(' ').slice(0, 200),\n timestamp: entry.timestamp,\n });\n}\n\nexport function initLogger(max?: number) {\n if (max) maxLogs = max;\n\n for (const level of Object.keys(originals) as LogEntry['level'][]) {\n console[level] = function (...args: any[]) {\n capture(level, args);\n originals[level].apply(console, args);\n };\n }\n}\n\nexport function getLogs(): LogEntry[] {\n return [...logs];\n}\n\nexport function clearLogs() {\n logs = [];\n}\n\nexport function restoreConsole() {\n for (const level of Object.keys(originals) as LogEntry['level'][]) {\n console[level] = originals[level];\n }\n}\n","import type { NetworkEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\nimport { redactString } from './redact';\n\nlet captures: NetworkEntry[] = [];\nlet maxCaptures = 50;\nlet originalFetch: typeof window.fetch;\nlet originalXHROpen: typeof XMLHttpRequest.prototype.open;\nlet originalXHRSend: typeof XMLHttpRequest.prototype.send;\n\nfunction record(entry: NetworkEntry) {\n captures.push(entry);\n if (captures.length > maxCaptures) captures.shift();\n\n addBreadcrumb({\n type: 'network',\n category: entry.failed ? 'network.error' : 'network.ok',\n message: `${entry.method} ${entry.url} → ${entry.status} (${entry.duration}ms)`,\n timestamp: entry.timestamp,\n data: { status: entry.status, duration: entry.duration },\n });\n}\n\nfunction shortenUrl(url: string): string {\n try {\n const u = new URL(url, window.location.origin);\n // Redact sensitive query params (tokens, keys, etc.)\n const params = new URLSearchParams(u.search);\n for (const key of params.keys()) {\n const lk = key.toLowerCase();\n if (lk.includes('token') || lk.includes('key') || lk.includes('secret') || lk.includes('password') || lk.includes('auth')) {\n params.set(key, '[REDACTED]');\n }\n }\n const qs = params.toString();\n return u.pathname + (qs ? '?' + qs : '');\n } catch {\n return redactString(url);\n }\n}\n\nfunction patchFetch() {\n originalFetch = window.fetch;\n\n window.fetch = async function (input: any, init?: any) {\n const method = init?.method?.toUpperCase() ?? 'GET';\n const rawUrl = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;\n const url = shortenUrl(rawUrl);\n const start = Date.now();\n\n try {\n const response = await originalFetch.call(window, input, init);\n record({\n method,\n url,\n status: response.status,\n statusText: response.statusText,\n duration: Date.now() - start,\n responseType: response.headers.get('content-type') ?? undefined,\n timestamp: start,\n failed: response.status >= 400,\n });\n return response;\n } catch (err) {\n record({\n method,\n url,\n status: 0,\n statusText: 'Network Error',\n duration: Date.now() - start,\n timestamp: start,\n failed: true,\n });\n throw err;\n }\n };\n}\n\nfunction patchXHR() {\n originalXHROpen = XMLHttpRequest.prototype.open;\n originalXHRSend = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string | URL, ...rest: any[]) {\n (this as any).__bs_method = method.toUpperCase();\n (this as any).__bs_url = shortenUrl(typeof url === 'string' ? url : url.href);\n return originalXHROpen.apply(this, [method, url, ...rest] as any);\n };\n\n XMLHttpRequest.prototype.send = function (body?: any) {\n const start = Date.now();\n\n this.addEventListener('loadend', function () {\n record({\n method: (this as any).__bs_method ?? 'GET',\n url: (this as any).__bs_url ?? '',\n status: this.status,\n statusText: this.statusText,\n duration: Date.now() - start,\n responseType: this.getResponseHeader('content-type') ?? undefined,\n timestamp: start,\n failed: this.status >= 400 || this.status === 0,\n });\n });\n\n return originalXHRSend.call(this, body);\n };\n}\n\nexport function initNetwork(max?: number) {\n if (max) maxCaptures = max;\n patchFetch();\n patchXHR();\n}\n\nexport function getNetworkCaptures(): NetworkEntry[] {\n return [...captures];\n}\n\nexport function getFailedNetworkCaptures(): NetworkEntry[] {\n return captures.filter((c) => c.failed);\n}\n\nexport function clearNetworkCaptures() {\n captures = [];\n}\n\nexport function restoreNetwork() {\n if (originalFetch) window.fetch = originalFetch;\n if (originalXHROpen) XMLHttpRequest.prototype.open = originalXHROpen;\n if (originalXHRSend) XMLHttpRequest.prototype.send = originalXHRSend;\n}\n","import type { ErrorEntry } from '@bugstash/shared';\nimport { addBreadcrumb } from './breadcrumbs';\n\nlet errors: ErrorEntry[] = [];\nlet onErrorHandler: ((e: ErrorEvent) => void) | null = null;\nlet onRejectionHandler: ((e: PromiseRejectionEvent) => void) | null = null;\n\nexport function initErrors() {\n onErrorHandler = (event: ErrorEvent) => {\n const entry: ErrorEntry = {\n message: event.message || 'Unknown error',\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n stack: event.error?.stack,\n type: 'error',\n timestamp: Date.now(),\n };\n errors.push(entry);\n addBreadcrumb({\n type: 'error',\n category: 'exception',\n message: entry.message,\n timestamp: entry.timestamp,\n data: { source: entry.source, lineno: entry.lineno },\n });\n };\n\n onRejectionHandler = (event: PromiseRejectionEvent) => {\n const reason = event.reason;\n const message =\n reason instanceof Error ? reason.message : typeof reason === 'string' ? reason : 'Unhandled promise rejection';\n const entry: ErrorEntry = {\n message,\n stack: reason instanceof Error ? reason.stack : undefined,\n type: 'unhandledrejection',\n timestamp: Date.now(),\n };\n errors.push(entry);\n addBreadcrumb({\n type: 'error',\n category: 'promise',\n message,\n timestamp: entry.timestamp,\n });\n };\n\n window.addEventListener('error', onErrorHandler);\n window.addEventListener('unhandledrejection', onRejectionHandler);\n}\n\nexport function getErrors(): ErrorEntry[] {\n return [...errors];\n}\n\nexport function clearErrors() {\n errors = [];\n}\n\nexport function restoreErrors() {\n if (onErrorHandler) window.removeEventListener('error', onErrorHandler);\n if (onRejectionHandler) window.removeEventListener('unhandledrejection', onRejectionHandler);\n onErrorHandler = null;\n onRejectionHandler = null;\n}\n","import type { PerformanceMetrics } from '@bugstash/shared';\n\nlet metrics: PerformanceMetrics | null = null;\nlet lcpObserver: PerformanceObserver | null = null;\nlet clsObserver: PerformanceObserver | null = null;\nlet fidObserver: PerformanceObserver | null = null;\n\nexport function initPerformance() {\n metrics = { timestamp: Date.now() };\n\n // Navigation timing\n if (performance.getEntriesByType) {\n const onLoad = () => {\n const [nav] = performance.getEntriesByType('navigation') as PerformanceNavigationTiming[];\n if (nav && metrics) {\n metrics.pageLoadTime = Math.round(nav.loadEventEnd - nav.startTime);\n metrics.domContentLoaded = Math.round(nav.domContentLoadedEventEnd - nav.startTime);\n }\n\n // Paint timing\n const paints = performance.getEntriesByType('paint');\n for (const p of paints) {\n if (p.name === 'first-paint' && metrics) metrics.firstPaint = Math.round(p.startTime);\n if (p.name === 'first-contentful-paint' && metrics) metrics.firstContentfulPaint = Math.round(p.startTime);\n }\n\n // Resource count\n if (metrics) {\n metrics.resourceCount = performance.getEntriesByType('resource').length;\n }\n\n // Memory (Chrome only)\n const mem = (performance as any).memory;\n if (mem && metrics) {\n metrics.memoryUsage = {\n usedJSHeapSize: mem.usedJSHeapSize,\n totalJSHeapSize: mem.totalJSHeapSize,\n };\n }\n };\n\n if (document.readyState === 'complete') {\n setTimeout(onLoad, 0);\n } else {\n window.addEventListener('load', () => setTimeout(onLoad, 100));\n }\n }\n\n // LCP\n if (typeof PerformanceObserver !== 'undefined') {\n try {\n lcpObserver = new PerformanceObserver((list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1];\n if (last && metrics) metrics.largestContentfulPaint = Math.round(last.startTime);\n });\n lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });\n } catch {}\n\n // CLS\n try {\n let clsValue = 0;\n clsObserver = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (!(entry as any).hadRecentInput) {\n clsValue += (entry as any).value;\n }\n }\n if (metrics) metrics.cumulativeLayoutShift = Math.round(clsValue * 1000) / 1000;\n });\n clsObserver.observe({ type: 'layout-shift', buffered: true });\n } catch {}\n\n // FID\n try {\n fidObserver = new PerformanceObserver((list) => {\n const [entry] = list.getEntries();\n if (entry && metrics) metrics.firstInputDelay = Math.round((entry as any).processingStart - entry.startTime);\n });\n fidObserver.observe({ type: 'first-input', buffered: true });\n } catch {}\n }\n}\n\nexport function getPerformanceMetrics(): PerformanceMetrics | null {\n if (metrics) metrics.timestamp = Date.now();\n return metrics ? { ...metrics } : null;\n}\n\nexport function restorePerformance() {\n lcpObserver?.disconnect();\n clsObserver?.disconnect();\n fidObserver?.disconnect();\n lcpObserver = null;\n clsObserver = null;\n fidObserver = null;\n metrics = null;\n}\n","/**\n * Silent screenshot capture with multiple fallback strategies.\n * 1. SVG foreignObject (zero-dep, no permission)\n * 2. html2canvas (loaded on-demand from CDN, no permission)\n * 3. Canvas direct-render (basic but reliable fallback)\n * No browser permission popups ever.\n */\n\n/** Show a camera shutter flash animation */\nfunction showFlashAnimation(): void {\n const flash = document.createElement('div');\n flash.style.cssText = `\n position: fixed; inset: 0; z-index: 2147483647;\n background: white; opacity: 0;\n pointer-events: none;\n animation: bs-flash 0.4s ease-out forwards;\n `;\n\n if (!document.getElementById('bs-flash-style')) {\n const style = document.createElement('style');\n style.id = 'bs-flash-style';\n style.textContent = `\n @keyframes bs-flash {\n 0% { opacity: 0; }\n 15% { opacity: 0.7; }\n 100% { opacity: 0; }\n }\n `;\n document.head.appendChild(style);\n }\n\n document.body.appendChild(flash);\n flash.addEventListener('animationend', () => flash.remove());\n}\n\nexport async function captureScreenshot(): Promise<string | null> {\n showFlashAnimation();\n\n // Strategy 1: SVG foreignObject\n try {\n const result = await captureSvgForeignObject();\n if (result) return result;\n } catch { /* fall through */ }\n\n // Strategy 2: html2canvas (CDN loaded on demand)\n try {\n const result = await captureWithHtml2Canvas();\n if (result) return result;\n } catch { /* fall through */ }\n\n // Strategy 3: Basic canvas render (always works but low quality)\n try {\n const result = await captureBasicCanvas();\n if (result) return result;\n } catch { /* fall through */ }\n\n return null;\n}\n\n/** Strategy 1: SVG foreignObject — zero-dep, no permission */\nasync function captureSvgForeignObject(): Promise<string | null> {\n const w = window.innerWidth;\n const h = window.innerHeight;\n\n const clone = document.documentElement.cloneNode(true) as HTMLElement;\n const sourceElements = document.documentElement.querySelectorAll('*');\n const cloneElements = clone.querySelectorAll('*');\n\n for (let i = 0; i < sourceElements.length && i < cloneElements.length; i++) {\n const computed = window.getComputedStyle(sourceElements[i]);\n const el = cloneElements[i] as HTMLElement;\n if (el.style) {\n const props = [\n 'background', 'background-color', 'background-image',\n 'color', 'font', 'font-size', 'font-family', 'font-weight',\n 'border', 'border-radius', 'padding', 'margin',\n 'display', 'flex-direction', 'align-items', 'justify-content',\n 'gap', 'width', 'height', 'max-width', 'max-height',\n 'overflow', 'position', 'top', 'left', 'right', 'bottom',\n 'box-shadow', 'text-shadow', 'opacity', 'transform',\n 'text-align', 'line-height', 'letter-spacing',\n 'text-decoration', 'visibility', 'z-index',\n 'grid-template-columns', 'grid-template-rows',\n 'box-sizing',\n ];\n for (const prop of props) {\n try { el.style.setProperty(prop, computed.getPropertyValue(prop)); } catch {}\n }\n }\n }\n\n // Remove scripts, BugStash UI, and flash elements\n clone.querySelectorAll('script, [data-bugstash], .bs-fab, .bs-toolbar, .bs-modal, .bs-backdrop, [id=\"bs-flash-style\"]').forEach(el => el.remove());\n\n // Remove cross-origin images\n clone.querySelectorAll('img').forEach(img => {\n try {\n const src = img.getAttribute('src') || '';\n if (src && !src.startsWith('data:') && !src.startsWith(window.location.origin)) {\n img.removeAttribute('src');\n img.style.backgroundColor = '#e5e7eb';\n }\n } catch {}\n });\n\n // Remove iframes (they break SVG foreignObject)\n clone.querySelectorAll('iframe').forEach(el => el.remove());\n\n // Remove canvas elements (can't serialize)\n clone.querySelectorAll('canvas').forEach(el => el.remove());\n\n // Remove video/audio elements\n clone.querySelectorAll('video, audio').forEach(el => el.remove());\n\n const serializer = new XMLSerializer();\n const html = serializer.serializeToString(clone);\n\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\"><foreignObject width=\"100%\" height=\"100%\">${html}</foreignObject></svg>`;\n\n const blob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n\n return new Promise<string | null>((resolve) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => {\n const canvas = document.createElement('canvas');\n canvas.width = w * 0.5;\n canvas.height = h * 0.5;\n const ctx = canvas.getContext('2d');\n if (!ctx) { URL.revokeObjectURL(url); resolve(null); return; }\n ctx.scale(0.5, 0.5);\n ctx.drawImage(img, 0, 0);\n URL.revokeObjectURL(url);\n try {\n resolve(canvas.toDataURL('image/jpeg', 0.6));\n } catch {\n resolve(null);\n }\n };\n img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };\n img.src = url;\n });\n}\n\n/** Strategy 2: Load html2canvas from CDN and use it */\nasync function captureWithHtml2Canvas(): Promise<string | null> {\n // Load html2canvas if not already loaded\n const w = window as any;\n if (!w.html2canvas) {\n await new Promise<void>((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js';\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('Failed to load html2canvas'));\n document.head.appendChild(script);\n });\n }\n\n if (!w.html2canvas) return null;\n\n const canvas = await w.html2canvas(document.body, {\n scale: 0.5,\n useCORS: true,\n allowTaint: false,\n logging: false,\n backgroundColor: null,\n ignoreElements: (el: HTMLElement) => {\n return el.classList?.contains('bs-fab') ||\n el.classList?.contains('bs-toolbar') ||\n el.classList?.contains('bs-modal') ||\n el.classList?.contains('bs-backdrop') ||\n el.id === 'bs-flash-style';\n },\n });\n\n try {\n return canvas.toDataURL('image/jpeg', 0.6);\n } catch {\n return null;\n }\n}\n\n/** Strategy 3: Basic canvas render — draws background color + text summary */\nasync function captureBasicCanvas(): Promise<string | null> {\n const w = window.innerWidth;\n const h = window.innerHeight;\n const canvas = document.createElement('canvas');\n canvas.width = w * 0.5;\n canvas.height = h * 0.5;\n const ctx = canvas.getContext('2d');\n if (!ctx) return null;\n\n ctx.scale(0.5, 0.5);\n\n // Get page background color\n const bodyBg = window.getComputedStyle(document.body).backgroundColor;\n ctx.fillStyle = bodyBg || '#ffffff';\n ctx.fillRect(0, 0, w, h);\n\n // Draw visible text content as a basic representation\n ctx.fillStyle = '#888888';\n ctx.font = '14px sans-serif';\n ctx.fillText(`Screenshot of: ${document.title || window.location.href}`, 20, 30);\n ctx.fillText(`Viewport: ${w}x${h}`, 20, 54);\n ctx.fillText(`Time: ${new Date().toLocaleString()}`, 20, 78);\n\n // Draw rough block layout\n const elements = document.querySelectorAll('main, header, footer, section, article, nav, aside, .card, [class*=\"container\"]');\n ctx.strokeStyle = 'rgba(128,128,128,0.3)';\n ctx.lineWidth = 1;\n elements.forEach(el => {\n const rect = el.getBoundingClientRect();\n if (rect.width > 10 && rect.height > 10) {\n ctx.strokeRect(rect.left, rect.top, rect.width, rect.height);\n }\n });\n\n try {\n return canvas.toDataURL('image/jpeg', 0.6);\n } catch {\n return null;\n }\n}\n","import type { BugReport, APIResponse, AuthUser, AuthTokens, LivePin, PinComment, Member } from '@bugstash/shared';\n\n// Primary cloud backend. Falls back to Azure if custom domain is unreachable.\n// Self-hosted users can override via BugStash.init({ endpoint: '...' }).\nconst PRIMARY_ENDPOINT = 'https://bugstash-backend.vercel.app';\nconst FALLBACK_ENDPOINT = 'https://bugstash-backend.vercel.app';\n\nlet endpoint = PRIMARY_ENDPOINT;\nlet _usingFallback = false;\n\nexport function setEndpoint(url: string) {\n endpoint = url.replace(/\\/$/, '');\n _usingFallback = false;\n}\n\nexport function getEndpoint() {\n return endpoint;\n}\n\n/**\n * Tries the current endpoint. On network failure (ERR_CONNECTION_REFUSED, etc.),\n * transparently falls back to the Azure backend so SDK login/reports always work\n * — even if a developer passes a bad endpoint or localhost isn't running.\n */\nasync function fetchWithFallback(url: string, init?: RequestInit): Promise<Response> {\n try {\n const res = await fetch(url, init);\n return res;\n } catch (err) {\n // Already on the final fallback — nothing left to try\n if (_usingFallback) throw err;\n\n // Fall back to Azure regardless of what the current endpoint is\n _usingFallback = true;\n const previousEndpoint = endpoint;\n endpoint = FALLBACK_ENDPOINT;\n const fallbackUrl = url.replace(previousEndpoint, FALLBACK_ENDPOINT);\n return fetch(fallbackUrl, init);\n }\n}\n\n// ─── Token Management ────────────────────────────────────\n\nconst STORAGE_KEY = 'bugstash_auth';\n\ninterface StoredAuth {\n user: AuthUser;\n tokens: AuthTokens;\n}\n\nfunction getStoredAuth(): StoredAuth | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const auth = JSON.parse(raw) as StoredAuth;\n // Check if access token expired\n if (auth.tokens.expiresAt < Date.now()) {\n // Try to refresh\n return auth; // Will be refreshed on next request\n }\n return auth;\n } catch {\n return null;\n }\n}\n\nfunction setStoredAuth(auth: StoredAuth) {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(auth));\n}\n\nexport function clearStoredAuth() {\n localStorage.removeItem(STORAGE_KEY);\n}\n\nexport function getCurrentUser(): AuthUser | null {\n return getStoredAuth()?.user || null;\n}\n\nexport function getAccessToken(): string | null {\n return getStoredAuth()?.tokens.accessToken || null;\n}\n\nasync function authHeaders(): Promise<Record<string, string>> {\n const auth = getStoredAuth();\n if (!auth) return { 'Content-Type': 'application/json' };\n\n // Refresh if expired\n if (auth.tokens.expiresAt < Date.now() + 60000) {\n try {\n const res = await fetchWithFallback(`${endpoint}/api/auth/refresh`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: auth.tokens.refreshToken }),\n });\n if (res.ok) {\n const data = await res.json();\n if (data.success) {\n auth.tokens = data.data;\n setStoredAuth(auth);\n }\n }\n } catch { /* Use existing token */ }\n }\n\n return {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${auth.tokens.accessToken}`,\n };\n}\n\n// ─── Auth API ────────────────────────────────────────────\n\nexport async function login(email: string, password: string, projectId: string): Promise<APIResponse<{ user: AuthUser; tokens: AuthTokens }>> {\n try {\n const res = await fetchWithFallback(`${endpoint}/api/auth/login`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password, projectId }),\n });\n const data = await res.json();\n if (data.success) {\n setStoredAuth({ user: data.data.user, tokens: data.data.tokens });\n }\n return data;\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function logout() {\n clearStoredAuth();\n}\n\nexport async function fetchMe(): Promise<APIResponse<AuthUser>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/auth/me`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Reports API ─────────────────────────────────────────\n\nexport async function submitReport(report: BugReport): Promise<APIResponse<{ id: string }>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/reports`, {\n method: 'POST',\n headers,\n body: JSON.stringify(report),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error - could not reach BugStash' };\n }\n}\n\n// ─── Pins API ────────────────────────────────────────────\n\nexport async function fetchPagePins(projectId: string, pathname: string): Promise<APIResponse<LivePin[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/by-page?projectId=${projectId}&pathname=${encodeURIComponent(pathname)}`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function createPin(pin: Partial<LivePin>): Promise<APIResponse<LivePin>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins`, {\n method: 'POST',\n headers,\n body: JSON.stringify(pin),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function updatePin(pinId: string, updates: Partial<LivePin>): Promise<APIResponse<LivePin>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(updates),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function deletePin(pinId: string): Promise<APIResponse<void>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}`, {\n method: 'DELETE',\n headers,\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Comments API ────────────────────────────────────────\n\nexport async function fetchComments(pinId: string): Promise<APIResponse<PinComment[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}/comments`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\nexport async function createComment(pinId: string, body: string, mentions: string[] = []): Promise<APIResponse<PinComment>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/pins/${pinId}/comments`, {\n method: 'POST',\n headers,\n body: JSON.stringify({ body, mentions }),\n });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Members API ─────────────────────────────────────────\n\nexport async function fetchProjectMembers(projectId: string): Promise<APIResponse<Member[]>> {\n try {\n const headers = await authHeaders();\n const res = await fetchWithFallback(`${endpoint}/api/members/for-project/${projectId}`, { headers });\n return await res.json();\n } catch {\n return { success: false, error: 'Network error' };\n }\n}\n\n// ─── Offline Queue ───────────────────────────────────────\n\nconst QUEUE_KEY = 'bugstash_offline_queue';\n\ninterface QueuedAction {\n id: string;\n type: 'create_pin' | 'create_comment' | 'update_pin' | 'submit_report';\n data: any;\n timestamp: number;\n}\n\nexport function queueOfflineAction(action: Omit<QueuedAction, 'id' | 'timestamp'>) {\n const queue = getOfflineQueue();\n queue.push({\n ...action,\n id: Math.random().toString(36).slice(2),\n timestamp: Date.now(),\n });\n localStorage.setItem(QUEUE_KEY, JSON.stringify(queue));\n}\n\nexport function getOfflineQueue(): QueuedAction[] {\n try {\n return JSON.parse(localStorage.getItem(QUEUE_KEY) || '[]');\n } catch {\n return [];\n }\n}\n\nexport async function flushOfflineQueue(): Promise<number> {\n const queue = getOfflineQueue();\n if (queue.length === 0) return 0;\n\n let flushed = 0;\n const remaining: QueuedAction[] = [];\n\n for (const action of queue) {\n try {\n let result: APIResponse<any>;\n switch (action.type) {\n case 'create_pin':\n result = await createPin(action.data);\n break;\n case 'create_comment':\n result = await createComment(action.data.pinId, action.data.body, action.data.mentions);\n break;\n case 'update_pin':\n result = await updatePin(action.data.pinId, action.data.updates);\n break;\n case 'submit_report':\n result = await submitReport(action.data);\n break;\n default:\n result = { success: false, error: 'Unknown action' };\n }\n if (result.success) {\n flushed++;\n } else {\n remaining.push(action);\n }\n } catch {\n remaining.push(action);\n }\n }\n\n localStorage.setItem(QUEUE_KEY, JSON.stringify(remaining));\n return flushed;\n}\n\n// Auto-flush when back online\nif (typeof window !== 'undefined') {\n window.addEventListener('online', () => {\n flushOfflineQueue().catch(() => {});\n });\n}\n","export interface BsTheme {\n id: string;\n name: string;\n preview: [string, string]; // [bg, accent] for switcher preview\n vars: Record<string, string>;\n}\n\nconst THEMES: BsTheme[] = [\n // ─── Slate (default — blue-gray) ──────────────────\n {\n id: 'slate',\n name: 'Slate',\n preview: ['#0f1117', '#6E9ED0'],\n vars: {\n '--bs-bg': '#0f1117',\n '--bs-bg2': '#1a1d27',\n '--bs-bg3': '#2a2d37',\n '--bs-text': '#e8eaed',\n '--bs-muted': '#9ca3af',\n '--bs-border': '#2a2d37',\n '--bs-accent': '#6E9ED0',\n '--bs-accent2': '#C3CAD6',\n '--bs-fab1': '#6E9ED0',\n '--bs-fab2': '#4a7ba8',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── Pure Black ────────────────────────────────────\n {\n id: 'black',\n name: 'Dark',\n preview: ['#0a0a0a', '#ffffff'],\n vars: {\n '--bs-bg': '#0a0a0a',\n '--bs-bg2': '#141414',\n '--bs-bg3': '#1e1e1e',\n '--bs-text': '#f5f5f5',\n '--bs-muted': '#737373',\n '--bs-border': '#262626',\n '--bs-accent': '#f5f5f5',\n '--bs-accent2': '#d4d4d4',\n '--bs-fab1': '#262626',\n '--bs-fab2': '#171717',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── Pure White ────────────────────────────────────\n {\n id: 'white',\n name: 'Light',\n preview: ['#ffffff', '#0a0a0a'],\n vars: {\n '--bs-bg': '#ffffff',\n '--bs-bg2': '#f5f5f5',\n '--bs-bg3': '#e5e5e5',\n '--bs-text': '#0a0a0a',\n '--bs-muted': '#737373',\n '--bs-border': '#e5e5e5',\n '--bs-accent': '#0a0a0a',\n '--bs-accent2': '#404040',\n '--bs-fab1': '#0a0a0a',\n '--bs-fab2': '#262626',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#dc2626',\n '--bs-green': '#16a34a',\n '--bs-orange': '#ea580c',\n '--bs-yellow': '#ca8a04',\n },\n },\n];\n\nexport function getThemes(): BsTheme[] {\n return THEMES;\n}\n\nexport function getThemeById(id: string): BsTheme | undefined {\n return THEMES.find((t) => t.id === id);\n}\n\nexport function getDefaultTheme(): BsTheme {\n return THEMES[0];\n}\n","export interface BsLayout {\n id: string;\n name: string;\n description: string;\n tabPosition: 'top' | 'left' | 'bottom';\n}\n\nconst LAYOUTS: BsLayout[] = [\n { id: 'classic', name: 'Center', description: 'Centered modal', tabPosition: 'top' },\n { id: 'drawer-right', name: 'Right Drawer', description: 'Slides from right', tabPosition: 'top' },\n { id: 'bottom-sheet', name: 'Bottom Sheet', description: 'Slides from bottom', tabPosition: 'top' },\n { id: 'sidebar-tabs', name: 'Sidebar', description: 'Side navigation', tabPosition: 'left' },\n];\n\nexport function getLayouts(): BsLayout[] {\n return LAYOUTS;\n}\n\nexport function getLayoutById(id: string): BsLayout | undefined {\n return LAYOUTS.find((l) => l.id === id);\n}\n\nexport function getDefaultLayout(): BsLayout {\n return LAYOUTS[0];\n}\n\n// ─── Layout CSS ──────────────────────────────────────────\n\nexport const LAYOUT_CSS = `\n/* ── 1. Classic (default — no overrides) ── */\n\n/* ── 2. Drawer Right ── */\n.bs-ly-drawer-right.bs-modal {\n top: 0; left: auto; right: 0; bottom: 0;\n width: 420px; max-width: 100vw; max-height: 100vh;\n height: 100vh;\n border-radius: 0;\n transform: translateX(100%);\n transition: transform 0.4s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-drawer-right.bs-modal.bs-in {\n transform: translateX(0);\n opacity: 1;\n}\n\n/* ── 3. Bottom Sheet ── */\n.bs-ly-bottom-sheet.bs-modal {\n top: auto; left: 50%; right: auto; bottom: 0;\n width: 600px; max-width: 100vw;\n max-height: 80vh;\n border-radius: var(--bs-radius) var(--bs-radius) 0 0;\n transform: translate(-50%, 100%);\n transition: transform 0.45s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-bottom-sheet.bs-modal.bs-in {\n transform: translate(-50%, 0);\n opacity: 1;\n}\n\n/* ── 4. Sidebar Tabs ── */\n.bs-ly-sidebar-tabs.bs-modal {\n width: 620px;\n}\n.bs-ly-sidebar-tabs .bs-body-wrap {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n.bs-ly-sidebar-tabs .bs-tabs {\n flex-direction: column;\n padding: 12px 0 12px 12px;\n gap: 4px;\n min-width: 140px;\n border-right: 1px solid var(--bs-border);\n overflow-y: auto;\n}\n.bs-ly-sidebar-tabs .bs-tab {\n border-radius: var(--bs-radius-sm);\n padding: 10px 12px;\n width: 100%;\n}\n.bs-ly-sidebar-tabs .bs-tab.bs-active::after {\n top: 8px; bottom: 8px; left: 0; right: auto;\n width: 2px; height: auto;\n border-radius: 0 2px 2px 0;\n}\n.bs-ly-sidebar-tabs .bs-tab-divider { display: none; }\n.bs-ly-sidebar-tabs .bs-scroll { flex: 1; }\n`;\n\nexport default LAYOUTS;\n","import { getEndpoint, getAccessToken } from './api';\nimport type { WSEvent } from '@bugstash/shared';\n\ntype EventHandler = (event: WSEvent) => void;\n\nlet pollTimer: ReturnType<typeof setInterval> | null = null;\nlet lastPollTime = 0;\nconst POLL_INTERVAL = 5000; // 5 seconds\nconst handlers = new Map<string, Set<EventHandler>>();\nlet currentProjectId: string | null = null;\nlet knownPinIds = new Set<string>();\n\nexport function connectRealtime(projectId: string) {\n currentProjectId = projectId;\n lastPollTime = Date.now();\n startPolling();\n}\n\nfunction startPolling() {\n if (pollTimer) return;\n pollTimer = setInterval(poll, POLL_INTERVAL);\n}\n\nasync function poll() {\n if (!currentProjectId) return;\n const token = getAccessToken();\n if (!token) return;\n\n try {\n const endpoint = getEndpoint();\n const pathname = window.location.pathname;\n const res = await fetch(\n `${endpoint}/api/pins/poll?projectId=${currentProjectId}&pathname=${encodeURIComponent(pathname)}&since=${lastPollTime}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n\n if (!res.ok) return;\n const data = await res.json();\n if (!data.success) return;\n\n const { pins, serverTime } = data.data;\n lastPollTime = serverTime;\n\n for (const pin of pins) {\n if (knownPinIds.has(pin.id)) {\n emit('pin:updated', {\n type: 'pin:updated',\n projectId: currentProjectId,\n data: pin,\n userId: '',\n timestamp: Date.now(),\n });\n } else {\n knownPinIds.add(pin.id);\n emit('pin:created', {\n type: 'pin:created',\n projectId: currentProjectId,\n data: pin,\n userId: '',\n timestamp: Date.now(),\n });\n }\n }\n } catch {\n // Silently fail — will retry next interval\n }\n}\n\nexport function disconnectRealtime() {\n if (pollTimer) {\n clearInterval(pollTimer);\n pollTimer = null;\n }\n currentProjectId = null;\n knownPinIds.clear();\n lastPollTime = 0;\n}\n\nexport function onRealtimeEvent(type: string, handler: EventHandler) {\n if (!handlers.has(type)) handlers.set(type, new Set());\n handlers.get(type)!.add(handler);\n return () => {\n handlers.get(type)?.delete(handler);\n };\n}\n\nfunction emit(type: string, event: WSEvent) {\n handlers.get(type)?.forEach((h) => h(event));\n handlers.get('*')?.forEach((h) => h(event));\n}\n\n/** Register known pin IDs so polling can detect new vs updated */\nexport function registerKnownPins(pinIds: string[]) {\n knownPinIds = new Set(pinIds);\n}\n\n// Cursor and navigation are no-ops in polling mode\nexport function sendCursorPosition(_x: number, _y: number, _pageUrl: string) {}\nexport function sendPageNavigate(_pageUrl: string) {}\n\nexport function isConnected(): boolean {\n return pollTimer !== null;\n}\n","import type { LivePin, Member } from '@bugstash/shared';\nimport { fetchPagePins, createPin, updatePin, deletePin, fetchComments, createComment, fetchProjectMembers, getCurrentUser, queueOfflineAction } from './api';\nimport { onRealtimeEvent, sendPageNavigate, registerKnownPins } from './realtime';\nimport { captureScreenshot } from './screenshot';\nimport { getLogs } from './logger';\nimport { getErrors } from './errors';\nimport { getFailedNetworkCaptures } from './network';\n\nlet projectId: string;\nlet container: HTMLDivElement | null = null;\nlet pins: LivePin[] = [];\nlet members: Member[] = [];\nlet pinMode = false;\nlet activePopup: HTMLDivElement | null = null;\nlet currentPathname = '';\n\nconst PIN_COLORS: Record<string, string> = {\n open: '#f97316',\n in_progress: '#3b82f6',\n resolved: '#22c55e',\n closed: '#6b7280',\n};\n\nexport function initLivePins(projId: string) {\n projectId = projId;\n currentPathname = window.location.pathname;\n\n createOverlay();\n loadPins();\n loadMembers();\n setupRealtimeListeners();\n watchNavigation();\n}\n\nexport function destroyLivePins() {\n if (container) {\n container.remove();\n container = null;\n }\n pins = [];\n}\n\nexport function togglePinMode(enabled?: boolean) {\n pinMode = enabled !== undefined ? enabled : !pinMode;\n if (container) {\n container.classList.toggle('bs-pin-mode', pinMode);\n }\n return pinMode;\n}\n\nexport function isPinModeActive() {\n return pinMode;\n}\n\n// ─── Overlay ─────────────────────────────────────────────\n\nfunction createOverlay() {\n if (container) return;\n\n container = document.createElement('div');\n container.id = 'bugstash-live-pins';\n\n const style = document.createElement('style');\n style.textContent = `\n /* Container scrolls with page so pins stick to their position */\n #bugstash-live-pins {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n min-height: 100%;\n z-index: 2147483640;\n pointer-events: none;\n }\n #bugstash-live-pins.bs-pin-mode {\n pointer-events: auto;\n cursor: crosshair;\n position: fixed;\n inset: 0;\n width: auto;\n min-height: auto;\n }\n\n /* ── Pin Marker — clean numbered dot ── */\n .bs-lp {\n position: absolute;\n pointer-events: auto;\n cursor: pointer;\n transform: translate(-50%, -50%);\n transition: transform 0.2s cubic-bezier(0.34,1.56,0.64,1);\n z-index: 1;\n }\n .bs-lp:hover { transform: translate(-50%, -50%) scale(1.2); z-index: 5; }\n .bs-lp-dot {\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: 800;\n font-family: -apple-system, system-ui, sans-serif;\n color: #fff;\n box-shadow: 0 2px 12px rgba(0,0,0,0.35), 0 0 0 2px rgba(255,255,255,0.9);\n position: relative;\n }\n .bs-lp-ring {\n position: absolute;\n inset: -4px;\n border-radius: 50%;\n border: 2px solid currentColor;\n opacity: 0;\n animation: bs-lp-pulse 2s ease-out infinite;\n }\n @keyframes bs-lp-pulse {\n 0% { opacity: 0.6; transform: scale(0.8); }\n 100% { opacity: 0; transform: scale(1.6); }\n }\n\n /* ── Popup ── */\n .bs-lp-popup {\n position: absolute;\n left: 32px;\n top: -12px;\n width: 300px;\n background: #111318;\n border: 1px solid #2a2d37;\n border-radius: 10px;\n box-shadow: 0 12px 40px rgba(0,0,0,0.5);\n z-index: 10;\n pointer-events: auto;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n color: #e8eaed;\n overflow: hidden;\n }\n .bs-lp-popup-header {\n padding: 10px 12px;\n border-bottom: 1px solid #1e2028;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n }\n .bs-lp-popup-title {\n font-size: 13px;\n font-weight: 600;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .bs-lp-popup-status {\n font-size: 9px;\n padding: 2px 7px;\n border-radius: 4px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n .bs-lp-popup-body {\n padding: 10px 12px;\n font-size: 12px;\n line-height: 1.5;\n color: #9ca3af;\n max-height: 100px;\n overflow-y: auto;\n }\n .bs-lp-popup-meta {\n padding: 6px 12px;\n font-size: 10px;\n color: #6b7280;\n border-top: 1px solid #1e2028;\n display: flex;\n justify-content: space-between;\n }\n .bs-lp-comments {\n max-height: 180px;\n overflow-y: auto;\n border-top: 1px solid #1e2028;\n }\n .bs-lp-comment {\n padding: 8px 12px;\n border-bottom: 1px solid #1a1d24;\n font-size: 12px;\n }\n .bs-lp-comment-author {\n font-weight: 600;\n color: #e8eaed;\n margin-bottom: 2px;\n font-size: 11px;\n }\n .bs-lp-comment-body {\n color: #9ca3af;\n line-height: 1.4;\n }\n .bs-lp-comment-time {\n font-size: 10px;\n color: #6b7280;\n margin-top: 2px;\n }\n .bs-lp-input-row {\n display: flex;\n border-top: 1px solid #2a2d37;\n }\n .bs-lp-input-row input {\n flex: 1;\n background: transparent;\n border: none;\n padding: 8px 12px;\n color: #e8eaed;\n font-size: 12px;\n outline: none;\n }\n .bs-lp-input-row input::placeholder { color: #4b5563; }\n .bs-lp-input-row button {\n background: #6E9ED0;\n border: none;\n color: #fff;\n padding: 0 14px;\n font-size: 11px;\n font-weight: 600;\n cursor: pointer;\n }\n .bs-lp-input-row button:hover { opacity: 0.85; }\n .bs-lp-actions {\n padding: 6px 12px;\n display: flex;\n gap: 4px;\n border-top: 1px solid #1e2028;\n }\n .bs-lp-btn {\n padding: 4px 10px;\n border-radius: 6px;\n border: 1px solid #2a2d37;\n background: #1a1d24;\n color: #9ca3af;\n font-size: 10px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n }\n .bs-lp-btn:hover { background: #222630; color: #e8eaed; }\n .bs-lp-btn.resolve { border-color: #22c55e33; color: #4ade80; }\n .bs-lp-btn.resolve:hover { background: #22c55e18; }\n .bs-lp-btn.delete { border-color: #ef444433; color: #f87171; }\n .bs-lp-btn.delete:hover { background: #ef444418; }\n .bs-lp-close {\n background: none;\n border: none;\n color: #6b7280;\n font-size: 16px;\n cursor: pointer;\n padding: 0 2px;\n line-height: 1;\n transition: color 0.15s;\n }\n .bs-lp-close:hover { color: #e8eaed; }\n\n /* ── New pin form ── */\n .bs-lp-newform {\n position: absolute;\n width: 300px;\n background: #111318;\n border: 1px solid #2a2d37;\n border-radius: 10px;\n box-shadow: 0 12px 40px rgba(0,0,0,0.5);\n z-index: 2147483645;\n pointer-events: auto;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n color: #e8eaed;\n padding: 12px;\n }\n .bs-lp-newform label {\n display: block;\n font-size: 10px;\n color: #6b7280;\n margin-bottom: 4px;\n margin-top: 8px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n .bs-lp-newform label:first-child { margin-top: 0; }\n .bs-lp-newform input, .bs-lp-newform textarea, .bs-lp-newform select {\n width: 100%;\n background: #1a1d24;\n border: 1px solid #2a2d37;\n border-radius: 6px;\n padding: 7px 10px;\n color: #e8eaed;\n font-size: 12px;\n outline: none;\n font-family: inherit;\n box-sizing: border-box;\n }\n .bs-lp-newform textarea { resize: vertical; min-height: 50px; }\n .bs-lp-newform input:focus, .bs-lp-newform textarea:focus, .bs-lp-newform select:focus {\n border-color: #6E9ED0;\n }\n .bs-lp-newform-actions {\n display: flex;\n gap: 6px;\n margin-top: 10px;\n }\n .bs-lp-newform-actions button {\n flex: 1;\n padding: 7px;\n border-radius: 6px;\n border: none;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n }\n .bs-lp-newform-submit {\n background: #6E9ED0;\n color: #fff;\n }\n .bs-lp-newform-submit:hover { opacity: 0.85; }\n .bs-lp-newform-cancel {\n background: #2a2d37;\n color: #9ca3af;\n }\n .bs-lp-newform-cancel:hover { background: #333; }\n `;\n\n container.appendChild(style);\n document.body.appendChild(container);\n\n // Click to place new pin\n container.addEventListener('click', (e) => {\n if (!pinMode) return;\n if ((e.target as HTMLElement).closest('.bs-lp, .bs-lp-popup, .bs-lp-newform')) return;\n\n // Convert to page coordinates (since container is fixed in pin mode)\n const x = e.clientX + window.scrollX;\n const y = e.clientY + window.scrollY;\n\n // Find the element under the pin (peek through overlay)\n container!.style.pointerEvents = 'none';\n const el = document.elementFromPoint(e.clientX, e.clientY);\n container!.style.pointerEvents = '';\n\n showNewPinForm(x, y, el);\n });\n}\n\n// ─── Load Data ───────────────────────────────────────────\n\nasync function loadPins() {\n const result = await fetchPagePins(projectId, window.location.pathname);\n if (result.success && result.data) {\n pins = result.data;\n registerKnownPins(pins.map(p => p.id));\n renderPins();\n }\n}\n\nasync function loadMembers() {\n const result = await fetchProjectMembers(projectId);\n if (result.success && result.data) {\n members = result.data as any[];\n }\n}\n\n// ─── Render Pins ─────────────────────────────────────────\n\nfunction renderPins() {\n if (!container) return;\n\n // Remove existing pin dots (keep style element)\n container.querySelectorAll('.bs-lp').forEach((el) => el.remove());\n\n pins.forEach((pin, i) => {\n const dot = document.createElement('div');\n dot.className = 'bs-lp';\n dot.style.left = `${pin.pageX}px`;\n dot.style.top = `${pin.pageY}px`;\n dot.dataset.pinId = pin.id;\n\n const color = PIN_COLORS[pin.status] || PIN_COLORS.open;\n\n dot.innerHTML = `\n <div class=\"bs-lp-dot\" style=\"background:${color};color:${color}\">\n ${i + 1}\n <span class=\"bs-lp-ring\"></span>\n </div>\n `;\n\n dot.addEventListener('click', (e) => {\n e.stopPropagation();\n showPinPopup(pin, dot);\n });\n\n container!.appendChild(dot);\n });\n}\n\n// ─── Pin Popup ───────────────────────────────────────────\n\nfunction timeAgo(ts: number): string {\n const diff = Date.now() - ts;\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'just now';\n if (mins < 60) return `${mins}m ago`;\n const hrs = Math.floor(mins / 60);\n if (hrs < 24) return `${hrs}h ago`;\n return `${Math.floor(hrs / 24)}d ago`;\n}\n\nfunction statusColor(status: string): string {\n const colors: Record<string, string> = {\n open: '#f97316',\n in_progress: '#3b82f6',\n resolved: '#22c55e',\n closed: '#6b7280',\n };\n return colors[status] || '#6b7280';\n}\n\nasync function showPinPopup(pin: LivePin, dotEl: HTMLDivElement) {\n closePopup();\n\n const popup = document.createElement('div');\n popup.className = 'bs-lp-popup';\n\n const commentsRes = await fetchComments(pin.id);\n const comments = commentsRes.success && commentsRes.data ? commentsRes.data : [];\n\n const user = getCurrentUser();\n const canManage = user && (user.role === 'owner' || user.role === 'admin' || user.id === pin.createdBy);\n\n popup.innerHTML = `\n <div class=\"bs-lp-popup-header\">\n <div class=\"bs-lp-popup-title\">${escapeHtml(pin.title)}</div>\n <span class=\"bs-lp-popup-status\" style=\"background:${statusColor(pin.status)}22;color:${statusColor(pin.status)}\">${pin.status.replace('_', ' ')}</span>\n <button class=\"bs-lp-close\">&times;</button>\n </div>\n ${pin.description ? `<div class=\"bs-lp-popup-body\">${escapeHtml(pin.description)}</div>` : ''}\n <div class=\"bs-lp-popup-meta\">\n <span>${pin.creatorName || 'Unknown'} &middot; ${timeAgo(pin.createdAt)}</span>\n <span>${pin.assigneeName ? `Assigned: ${pin.assigneeName}` : 'Unassigned'}</span>\n </div>\n <div class=\"bs-lp-comments\" id=\"bs-lp-comments\">\n ${comments.map((c: any) => `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(c.author?.name || c.authorName || 'Unknown')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(c.body)}</div>\n <div class=\"bs-lp-comment-time\">${timeAgo(new Date(c.createdAt).getTime())}</div>\n </div>\n `).join('')}\n </div>\n <div class=\"bs-lp-input-row\">\n <input type=\"text\" placeholder=\"Add a comment...\" id=\"bs-lp-comment-input\" />\n <button id=\"bs-lp-comment-send\">Send</button>\n </div>\n <div class=\"bs-lp-actions\">\n ${pin.status !== 'resolved'\n ? `<button class=\"bs-lp-btn resolve\" id=\"bs-lp-resolve\">Resolve</button>`\n : `<button class=\"bs-lp-btn\" id=\"bs-lp-reopen\">Reopen</button>`\n }\n ${canManage ? `<button class=\"bs-lp-btn delete\" id=\"bs-lp-delete\">Delete</button>` : ''}\n </div>\n `;\n\n dotEl.appendChild(popup);\n activePopup = popup;\n\n // Bind events\n popup.querySelector('.bs-lp-close')!.addEventListener('click', (e) => {\n e.stopPropagation();\n closePopup();\n });\n\n popup.querySelector('#bs-lp-comment-send')?.addEventListener('click', async () => {\n const input = popup.querySelector('#bs-lp-comment-input') as HTMLInputElement;\n const body = input.value.trim();\n if (!body) return;\n input.value = '';\n\n if (navigator.onLine) {\n const res = await createComment(pin.id, body);\n if (res.success && res.data) {\n const commentsEl = popup.querySelector('#bs-lp-comments')!;\n const c = res.data;\n commentsEl.innerHTML += `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(c.authorName || user?.name || 'You')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(c.body)}</div>\n <div class=\"bs-lp-comment-time\">just now</div>\n </div>\n `;\n commentsEl.scrollTop = commentsEl.scrollHeight;\n }\n } else {\n queueOfflineAction({ type: 'create_comment', data: { pinId: pin.id, body } });\n }\n });\n\n const commentInput = popup.querySelector('#bs-lp-comment-input') as HTMLInputElement;\n commentInput?.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n popup.querySelector('#bs-lp-comment-send')?.dispatchEvent(new Event('click'));\n }\n });\n\n popup.querySelector('#bs-lp-resolve')?.addEventListener('click', async () => {\n await updatePin(pin.id, { status: 'resolved' as any });\n pin.status = 'resolved';\n closePopup();\n renderPins();\n });\n\n popup.querySelector('#bs-lp-reopen')?.addEventListener('click', async () => {\n await updatePin(pin.id, { status: 'open' as any });\n pin.status = 'open';\n closePopup();\n renderPins();\n });\n\n popup.querySelector('#bs-lp-delete')?.addEventListener('click', async () => {\n if (!confirm('Delete this pin?')) return;\n await deletePin(pin.id);\n pins = pins.filter((p) => p.id !== pin.id);\n closePopup();\n renderPins();\n });\n\n // Prevent clicks inside popup from creating new pins\n popup.addEventListener('click', (e) => e.stopPropagation());\n}\n\nfunction closePopup() {\n activePopup?.remove();\n activePopup = null;\n}\n\n// ─── New Pin Form ────────────────────────────────────────\n\nfunction getSelector(el: Element | null): string {\n if (!el || el === document.body || el === document.documentElement) return 'body';\n if (el.id) return `#${el.id}`;\n let selector = el.tagName.toLowerCase();\n if (el.className && typeof el.className === 'string') {\n const classes = el.className.trim().split(/\\s+/).filter(c => !c.startsWith('bs-')).slice(0, 3);\n if (classes.length) selector += '.' + classes.join('.');\n }\n const parent = el.parentElement;\n if (parent && parent !== document.body) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === el.tagName);\n if (siblings.length > 1) {\n const idx = siblings.indexOf(el);\n selector += `:nth-child(${idx + 1})`;\n }\n return getSelector(parent) + ' > ' + selector;\n }\n return selector;\n}\n\nfunction getXPath(el: Element | null): string {\n if (!el) return '';\n const parts: string[] = [];\n let current: Element | null = el;\n while (current && current !== document.body) {\n let idx = 1;\n let sib = current.previousElementSibling;\n while (sib) {\n if (sib.tagName === current.tagName) idx++;\n sib = sib.previousElementSibling;\n }\n parts.unshift(`${current.tagName.toLowerCase()}[${idx}]`);\n current = current.parentElement;\n }\n return '/body/' + parts.join('/');\n}\n\nfunction showNewPinForm(pageX: number, pageY: number, targetEl: Element | null) {\n closePopup();\n container?.querySelectorAll('.bs-lp-newform').forEach(e => e.remove());\n\n const form = document.createElement('div');\n form.className = 'bs-lp-newform';\n form.style.left = `${pageX + 16}px`;\n form.style.top = `${pageY - 8}px`;\n\n // Ensure form stays in viewport\n requestAnimationFrame(() => {\n const rect = form.getBoundingClientRect();\n if (rect.right > window.innerWidth - 16) {\n form.style.left = `${pageX - 336}px`;\n }\n if (rect.bottom > window.innerHeight - 16) {\n form.style.top = `${pageY - rect.height}px`;\n }\n });\n\n const memberOptions = members\n .filter(m => (m as any).userId !== getCurrentUser()?.id)\n .map(m => `<option value=\"${(m as any).userId}\">${escapeHtml((m as any).name)}</option>`)\n .join('');\n\n form.innerHTML = `\n <label>Title *</label>\n <input type=\"text\" id=\"bs-np-title\" placeholder=\"What's the issue?\" autofocus />\n <label>Description</label>\n <textarea id=\"bs-np-desc\" placeholder=\"Describe the problem...\"></textarea>\n <label>Priority</label>\n <select id=\"bs-np-priority\">\n <option value=\"low\">Low</option>\n <option value=\"medium\" selected>Medium</option>\n <option value=\"high\">High</option>\n <option value=\"critical\">Critical</option>\n </select>\n <label>Category</label>\n <select id=\"bs-np-category\">\n <option value=\"ui\">UI</option>\n <option value=\"functionality\">Functionality</option>\n <option value=\"performance\">Performance</option>\n <option value=\"content\">Content</option>\n <option value=\"other\" selected>Other</option>\n </select>\n ${memberOptions ? `\n <label>Assign to</label>\n <select id=\"bs-np-assignee\">\n <option value=\"\">Unassigned</option>\n ${memberOptions}\n </select>\n ` : ''}\n <div class=\"bs-lp-newform-actions\">\n <button class=\"bs-lp-newform-cancel\" id=\"bs-np-cancel\">Cancel</button>\n <button class=\"bs-lp-newform-submit\" id=\"bs-np-submit\">Create Pin</button>\n </div>\n `;\n\n container!.appendChild(form);\n\n form.addEventListener('click', (e) => e.stopPropagation());\n\n form.querySelector('#bs-np-cancel')!.addEventListener('click', () => form.remove());\n\n form.querySelector('#bs-np-submit')!.addEventListener('click', async () => {\n const title = (form.querySelector('#bs-np-title') as HTMLInputElement).value.trim();\n if (!title) {\n (form.querySelector('#bs-np-title') as HTMLInputElement).style.borderColor = '#ef4444';\n return;\n }\n\n const desc = (form.querySelector('#bs-np-desc') as HTMLTextAreaElement).value.trim();\n const priority = (form.querySelector('#bs-np-priority') as HTMLSelectElement).value;\n const category = (form.querySelector('#bs-np-category') as HTMLSelectElement).value;\n const assigneeEl = form.querySelector('#bs-np-assignee') as HTMLSelectElement;\n const assigneeId = assigneeEl?.value || undefined;\n\n const selector = getSelector(targetEl);\n const xpath = getXPath(targetEl);\n\n // Capture context\n const logs = getLogs().slice(-20).map(l => `[${l.level}] ${l.args.join(' ')}`);\n const errors = getErrors().slice(-10).map(e => `${e.message} at ${e.source}:${e.lineno}`);\n const netErrors = getFailedNetworkCaptures().slice(-10).map(n => `${n.method} ${n.url} → ${n.status}`);\n\n // Take screenshot\n let screenshot: string | undefined;\n try {\n form.style.display = 'none';\n container!.style.display = 'none';\n screenshot = await captureScreenshot() ?? undefined;\n container!.style.display = '';\n form.style.display = '';\n } catch { /* no screenshot */ }\n\n const pinData = {\n projectId,\n pageUrl: window.location.href,\n pathname: window.location.pathname,\n elementSelector: selector,\n elementXPath: xpath,\n xPercent: 0,\n yPercent: 0,\n pageX,\n pageY,\n title,\n description: desc,\n screenshot,\n priority: priority as 'low' | 'medium' | 'high' | 'critical',\n category: category as 'ui' | 'functionality' | 'performance' | 'content' | 'other',\n assigneeId,\n browserInfo: navigator.userAgent,\n screenSize: `${screen.width}x${screen.height}`,\n viewportSize: `${window.innerWidth}x${window.innerHeight}`,\n devicePixelRatio: window.devicePixelRatio,\n consoleLogs: logs,\n networkErrors: netErrors,\n jsErrors: errors,\n };\n\n form.remove();\n\n if (navigator.onLine) {\n const res = await createPin(pinData);\n if (res.success && res.data) {\n pins.push(res.data);\n renderPins();\n }\n } else {\n // Queue for later\n queueOfflineAction({ type: 'create_pin', data: pinData });\n // Optimistic local pin\n pins.push({\n ...pinData,\n id: 'local-' + Date.now(),\n orgId: '',\n status: 'open',\n tags: [],\n createdById: getCurrentUser()?.id || '',\n creatorName: getCurrentUser()?.name || '',\n commentCount: 0,\n createdAt: Date.now(),\n updatedAt: Date.now(),\n } as any);\n renderPins();\n }\n });\n\n // Focus title input\n setTimeout(() => (form.querySelector('#bs-np-title') as HTMLInputElement)?.focus(), 50);\n}\n\n// ─── Real-time Updates ───────────────────────────────────\n\nfunction setupRealtimeListeners() {\n onRealtimeEvent('pin:created', (event) => {\n const pin = event.data as LivePin;\n if (pin.pathname === window.location.pathname) {\n // Don't duplicate if we created it\n if (!pins.find(p => p.id === pin.id)) {\n pins.push(pin);\n renderPins();\n }\n }\n });\n\n onRealtimeEvent('pin:updated', (event) => {\n const updated = event.data as LivePin;\n const idx = pins.findIndex(p => p.id === updated.id);\n if (idx >= 0) {\n pins[idx] = { ...pins[idx], ...updated };\n renderPins();\n }\n });\n\n onRealtimeEvent('pin:deleted', (event) => {\n const { id } = event.data;\n pins = pins.filter(p => p.id !== id);\n closePopup();\n renderPins();\n });\n\n onRealtimeEvent('comment:created', (event) => {\n // If popup is open for this pin, add the comment\n const comment = event.data;\n if (activePopup) {\n const commentsEl = activePopup.querySelector('#bs-lp-comments');\n if (commentsEl) {\n commentsEl.innerHTML += `\n <div class=\"bs-lp-comment\">\n <div class=\"bs-lp-comment-author\">${escapeHtml(comment.author?.name || 'Someone')}</div>\n <div class=\"bs-lp-comment-body\">${escapeHtml(comment.body)}</div>\n <div class=\"bs-lp-comment-time\">just now</div>\n </div>\n `;\n commentsEl.scrollTop = commentsEl.scrollHeight;\n }\n }\n });\n}\n\n// ─── Navigation Watch ────────────────────────────────────\n\nfunction watchNavigation() {\n // Watch for SPA navigation\n let lastPath = window.location.pathname;\n\n const check = () => {\n if (window.location.pathname !== lastPath) {\n lastPath = window.location.pathname;\n sendPageNavigate(window.location.href);\n loadPins(); // Reload pins for new page\n }\n };\n\n // Intercept pushState/replaceState\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n\n history.pushState = function (...args) {\n origPush.apply(this, args);\n check();\n };\n\n history.replaceState = function (...args) {\n origReplace.apply(this, args);\n check();\n };\n\n window.addEventListener('popstate', check);\n}\n\n// ─── Util ────────────────────────────────────────────────\n\nfunction escapeHtml(str: string): string {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n}\n","import type { BugStashConfig, BugReport, ReportContext } from '@bugstash/shared';\nimport { getLogs } from './logger';\nimport { getNetworkCaptures, getFailedNetworkCaptures } from './network';\nimport { getErrors } from './errors';\nimport { getBreadcrumbs } from './breadcrumbs';\nimport { getPerformanceMetrics } from './performance';\nimport { captureScreenshot } from './screenshot';\nimport { submitReport, login as apiLogin, getCurrentUser, logout as apiLogout } from './api';\nimport { getDefaultTheme, getThemeById, getThemes, type BsTheme } from './themes';\nimport { getDefaultLayout, getLayoutById, getLayouts, LAYOUT_CSS, type BsLayout } from './layouts';\nimport { initLivePins, togglePinMode, isPinModeActive } from './livepins';\nimport { connectRealtime } from './realtime';\n\nlet config: BugStashConfig;\nlet fab: HTMLButtonElement | null = null;\nlet toolbar: HTMLDivElement | null = null;\nlet modal: HTMLDivElement | null = null;\nlet backdrop: HTMLDivElement | null = null;\nlet styleEl: HTMLStyleElement | null = null;\nlet keyHandler: ((e: KeyboardEvent) => void) | null = null;\nlet isOpen = false;\nlet toolbarVisible = false;\nlet activeTab: 'report' | 'console' | 'network' | 'context' | 'history' | 'settings' = 'report';\nlet editingReportId: number | null = null;\nlet currentTheme: BsTheme = getDefaultTheme();\nlet currentLayout: BsLayout = getDefaultLayout();\n\n// ─── Icons ───────────────────────────────────────────────\n\nconst I = {\n bug: `<svg width=\"28\" height=\"28\" viewBox=\"55 38 60 105\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M95.8 44h-29c-3 0-5.4 2.4-5.4 5.4v29c0 3 2.4 5.4 5.4 5.4h19.5c13 0 23.5-10.5 23.5-23.5v-2.8c0-7.5-6-13.5-13.5-13.5h-.5zm-6.2 28.2H74.8V57.4h14.8c5.8 0 10.4 4.7 10.4 10.4s-4.7 10.4-10.4 10.4z\" fill=\"rgba(255,255,255,0.85)\"/><path d=\"M100.4 96h-33.6c-3 0-5.4 2.4-5.4 5.4v33.6c0 3 2.4 5.4 5.4 5.4h22c15 0 27-12 27-27v-3.9c0-7.5-6-13.5-13.5-13.5h-1.9zm-7.8 32.2H74.8v-20h17.8c6.7 0 12.2 5.5 12.2 12.2 0 4.3-3.5 7.8-7.8 7.8h-4.6z\" fill=\"rgba(255,255,255,1)\"/></svg>`,\n x: `<svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n cam: `<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z\"/><circle cx=\"12\" cy=\"13\" r=\"4\"/></svg>`,\n check: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n report: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"/></svg>`,\n console: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"4 17 10 11 4 5\"/><line x1=\"12\" y1=\"19\" x2=\"20\" y2=\"19\"/></svg>`,\n network: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"2\" y1=\"12\" x2=\"22\" y2=\"12\"/><path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"/></svg>`,\n ctx: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"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 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z\"/></svg>`,\n settings: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"4\" y1=\"21\" x2=\"4\" y2=\"14\"/><line x1=\"4\" y1=\"10\" x2=\"4\" y2=\"3\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"3\"/><line x1=\"20\" y1=\"21\" x2=\"20\" y2=\"16\"/><line x1=\"20\" y1=\"12\" x2=\"20\" y2=\"3\"/><line x1=\"1\" y1=\"14\" x2=\"7\" y2=\"14\"/><line x1=\"9\" y1=\"8\" x2=\"15\" y2=\"8\"/><line x1=\"17\" y1=\"16\" x2=\"23\" y2=\"16\"/></svg>`,\n history: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/></svg>`,\n pin: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>`,\n sun: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><circle cx=\"12\" cy=\"12\" r=\"5\"/><line x1=\"12\" y1=\"1\" x2=\"12\" y2=\"3\"/><line x1=\"12\" y1=\"21\" x2=\"12\" y2=\"23\"/><line x1=\"4.22\" y1=\"4.22\" x2=\"5.64\" y2=\"5.64\"/><line x1=\"18.36\" y1=\"18.36\" x2=\"19.78\" y2=\"19.78\"/><line x1=\"1\" y1=\"12\" x2=\"3\" y2=\"12\"/><line x1=\"21\" y1=\"12\" x2=\"23\" y2=\"12\"/><line x1=\"4.22\" y1=\"19.78\" x2=\"5.64\" y2=\"18.36\"/><line x1=\"18.36\" y1=\"5.64\" x2=\"19.78\" y2=\"4.22\"/></svg>`,\n moon: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/></svg>`,\n keyboard: `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/><line x1=\"6\" y1=\"8\" x2=\"6\" y2=\"8\"/><line x1=\"10\" y1=\"8\" x2=\"10\" y2=\"8\"/><line x1=\"14\" y1=\"8\" x2=\"14\" y2=\"8\"/><line x1=\"18\" y1=\"8\" x2=\"18\" y2=\"8\"/><line x1=\"8\" y1=\"12\" x2=\"16\" y2=\"12\"/><line x1=\"6\" y1=\"16\" x2=\"18\" y2=\"16\"/></svg>`,\n};\n\n// ─── Styles (CSS custom properties) ──────────────────────\n\nconst STYLES = `\n @import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@400;600;700&family=Inter:wght@300;400;500;600;700&display=swap');\n\n /* ── FAB ── */\n .bs-fab {\n all: unset;\n position: fixed;\n bottom: 24px;\n z-index: 2147483647;\n width: 56px;\n height: 56px;\n border-radius: var(--bs-radius);\n background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff;\n cursor: pointer;\n box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 0 rgba(0,0,0,0.15);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.35s cubic-bezier(0.34,1.56,0.64,1);\n animation: bs-pulse 3s ease-in-out infinite;\n }\n .bs-fab:hover {\n transform: scale(1.08) translateY(-2px);\n box-shadow: 0 8px 32px rgba(0,0,0,0.4);\n animation: none;\n }\n .bs-fab:active { transform: scale(0.95); }\n .bs-fab.bs-open {\n animation: none;\n transform: rotate(45deg) scale(0.9);\n box-shadow: 0 2px 12px rgba(0,0,0,0.3);\n }\n .bs-fab.bs-open:hover { transform: rotate(45deg) scale(1); }\n @keyframes bs-pulse {\n 0%, 100% { box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 0 rgba(0,0,0,0.15); }\n 50% { box-shadow: 0 4px 24px rgba(0,0,0,0.3), 0 0 0 10px rgba(0,0,0,0); }\n }\n .bs-fab-label {\n position: absolute;\n right: calc(100% + 12px);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-family: 'Inter', sans-serif;\n font-size: 13px;\n font-weight: 500;\n padding: 8px 14px;\n border-radius: var(--bs-radius-sm);\n white-space: nowrap;\n box-shadow: 0 4px 20px rgba(0,0,0,0.3);\n opacity: 0;\n transform: translateX(8px);\n transition: all 0.25s ease;\n pointer-events: none;\n }\n .bs-fab:hover .bs-fab-label { opacity: 1; transform: translateX(0); }\n .bs-fab-label::after {\n content: '';\n position: absolute;\n right: -6px;\n top: 50%;\n transform: translateY(-50%);\n border: 6px solid transparent;\n border-left-color: var(--bs-bg2);\n border-right: none;\n }\n\n /* ── Quick Action Toolbar ── */\n .bs-toolbar {\n position: fixed;\n z-index: 2147483646;\n display: flex;\n flex-direction: column;\n gap: 6px;\n bottom: 88px;\n opacity: 0;\n transform: translateY(10px);\n transition: all 0.3s cubic-bezier(0.34,1.56,0.64,1);\n pointer-events: none;\n }\n .bs-toolbar.bs-show {\n opacity: 1;\n transform: translateY(0);\n pointer-events: all;\n }\n .bs-toolbar-btn {\n all: unset;\n width: 40px;\n height: 40px;\n border-radius: var(--bs-radius-sm);\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n color: var(--bs-muted);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s;\n position: relative;\n box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n }\n .bs-toolbar-btn:hover { color: var(--bs-text); border-color: var(--bs-accent); background: var(--bs-bg3); }\n .bs-toolbar-btn.bs-active { color: var(--bs-accent); border-color: var(--bs-accent); }\n .bs-toolbar-tip {\n position: absolute;\n right: calc(100% + 8px);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-family: 'Inter', sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 4px 8px;\n border-radius: 6px;\n white-space: nowrap;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.15s;\n }\n .bs-toolbar-btn:hover .bs-toolbar-tip { opacity: 1; }\n .bs-toolbar-kbd {\n font-size: 9px;\n color: var(--bs-muted);\n margin-left: 4px;\n }\n\n /* ── Backdrop ── */\n .bs-backdrop {\n position: fixed;\n inset: 0;\n z-index: 2147483644;\n background: rgba(0,0,0,0);\n backdrop-filter: blur(0px);\n transition: all 0.4s ease;\n pointer-events: none;\n }\n .bs-backdrop.bs-in {\n background: rgba(10,12,20,0.55);\n backdrop-filter: blur(6px);\n pointer-events: all;\n }\n\n /* ── Modal ── */\n .bs-modal {\n position: fixed;\n z-index: 2147483645;\n top: 50%;\n left: 50%;\n width: 620px;\n height: 680px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 48px);\n background: var(--bs-bg);\n border: 1px solid var(--bs-border);\n border-radius: var(--bs-radius);\n box-shadow: 0 32px 80px rgba(0,0,0,0.55), 0 0 0 1px rgba(255,255,255,0.03) inset;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font-family: 'Inter', -apple-system, sans-serif;\n transform: translate(-50%, -50%) scale(0.88);\n opacity: 0;\n transition: transform 0.4s cubic-bezier(0.34,1.56,0.64,1),\n opacity 0.3s ease,\n width 0.35s cubic-bezier(0.25,1,0.5,1),\n height 0.35s cubic-bezier(0.25,1,0.5,1);\n }\n .bs-modal.bs-in {\n transform: translate(-50%, -50%) scale(1);\n opacity: 1;\n }\n .bs-modal.bs-out {\n transform: translate(-50%, -50%) scale(0.85);\n opacity: 0;\n transition: transform 0.3s cubic-bezier(0.4,0,1,1), opacity 0.25s ease;\n }\n\n /* ── Header ── */\n .bs-hdr {\n padding: 18px 22px 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n }\n .bs-logo {\n font-family: 'Comfortaa', cursive;\n font-weight: 700;\n font-size: 18px;\n background: linear-gradient(135deg, var(--bs-accent), #fff);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n }\n .bs-hdr-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .bs-pin-toggle {\n all: unset;\n cursor: pointer;\n padding: 5px 10px;\n border-radius: var(--bs-radius-sm);\n font-size: 11px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n color: var(--bs-muted);\n border: 1px solid var(--bs-border);\n transition: all 0.2s;\n display: flex;\n align-items: center;\n gap: 5px;\n }\n .bs-pin-toggle:hover { color: var(--bs-text); border-color: var(--bs-accent); }\n .bs-pin-toggle.active {\n background: var(--bs-accent);\n color: #fff;\n border-color: var(--bs-accent);\n -webkit-text-fill-color: #fff;\n }\n .bs-user-badge {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--bs-muted);\n font-family: 'Inter', sans-serif;\n }\n .bs-user-avatar {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: linear-gradient(135deg, var(--bs-accent), var(--bs-accent2));\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 10px;\n font-weight: 700;\n color: #fff;\n }\n .bs-login-form {\n padding: 32px 24px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 14px;\n }\n .bs-login-logo {\n font-family: 'Comfortaa', cursive;\n font-weight: 700;\n font-size: 28px;\n background: linear-gradient(135deg, var(--bs-accent), #fff);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 4px;\n }\n .bs-login-subtitle {\n font-size: 13px;\n color: var(--bs-muted);\n margin-bottom: 8px;\n }\n .bs-login-input {\n width: 100%;\n max-width: 300px;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm);\n border: 1px solid var(--bs-border);\n background: var(--bs-bg2);\n color: var(--bs-text);\n font-size: 13px;\n font-family: 'Inter', sans-serif;\n outline: none;\n transition: border-color 0.2s;\n box-sizing: border-box;\n }\n .bs-login-input:focus { border-color: var(--bs-accent); }\n .bs-login-input::placeholder { color: var(--bs-muted); opacity: 0.6; }\n .bs-login-btn {\n width: 100%;\n max-width: 300px;\n padding: 10px;\n border-radius: var(--bs-radius-sm);\n border: none;\n background: linear-gradient(135deg, var(--bs-accent), var(--bs-accent2));\n color: #fff;\n font-size: 14px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: opacity 0.2s;\n }\n .bs-login-btn:hover { opacity: 0.9; }\n .bs-login-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n .bs-login-error {\n font-size: 12px;\n color: var(--bs-red);\n max-width: 300px;\n text-align: center;\n }\n .bs-login-logout {\n all: unset;\n cursor: pointer;\n font-size: 11px;\n color: var(--bs-muted);\n font-family: 'Inter', sans-serif;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.15s;\n }\n .bs-login-logout:hover { color: var(--bs-red); }\n .bs-close-btn {\n all: unset;\n cursor: pointer;\n color: var(--bs-muted);\n padding: 6px;\n border-radius: var(--bs-radius-sm);\n display: flex;\n transition: all 0.2s;\n }\n .bs-close-btn:hover { color: var(--bs-text); background: var(--bs-bg3); }\n\n /* ── Tabs ── */\n .bs-tabs {\n display: flex;\n gap: 2px;\n padding: 12px 22px 0;\n position: relative;\n flex-shrink: 0;\n }\n .bs-tab {\n all: unset;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm) var(--bs-radius-sm) 0 0;\n font-family: 'Inter', sans-serif;\n font-size: 12px;\n font-weight: 600;\n color: var(--bs-muted);\n transition: all 0.25s ease;\n position: relative;\n }\n .bs-tab:hover { color: var(--bs-text); background: var(--bs-bg2); }\n .bs-tab.bs-active {\n color: var(--bs-accent);\n background: var(--bs-bg2);\n }\n .bs-tab.bs-active::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 8px;\n right: 8px;\n height: 2px;\n background: var(--bs-accent);\n border-radius: 2px 2px 0 0;\n animation: bs-tabIn 0.25s ease;\n }\n @keyframes bs-tabIn { from { transform: scaleX(0); } to { transform: scaleX(1); } }\n .bs-tab-badge {\n font-size: 10px;\n font-weight: 700;\n padding: 1px 6px;\n border-radius: 10px;\n background: var(--bs-bg3);\n color: var(--bs-muted);\n line-height: 1.4;\n }\n .bs-tab.bs-active .bs-tab-badge { background: var(--bs-accent); color: #fff; }\n .bs-tab-badge.bs-warn { background: var(--bs-red); color: #fff; }\n .bs-tab-divider {\n height: 1px;\n background: var(--bs-border);\n flex-shrink: 0;\n }\n\n /* ── Scrollable Body ── */\n .bs-scroll {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 16px 22px 22px;\n overscroll-behavior: contain;\n }\n .bs-scroll::-webkit-scrollbar { width: 5px; }\n .bs-scroll::-webkit-scrollbar-track { background: transparent; }\n .bs-scroll::-webkit-scrollbar-thumb { background: var(--bs-border); border-radius: 4px; }\n\n /* ── View slide animation ── */\n .bs-view { animation: bs-slideUp 0.3s cubic-bezier(0.22,1,0.36,1); }\n @keyframes bs-slideUp {\n from { opacity: 0; transform: translateY(12px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* ── Form ── */\n .bs-field { margin-bottom: 16px; }\n .bs-field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--bs-text);\n margin-bottom: 7px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .bs-field-hint { font-size: 11px; font-weight: 400; color: var(--bs-muted); }\n .bs-input, .bs-textarea {\n width: 100%;\n padding: 11px 14px;\n border: 1.5px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n font-size: 14px;\n font-family: 'Inter', sans-serif;\n background: var(--bs-bg2);\n color: var(--bs-text);\n box-sizing: border-box;\n transition: all 0.2s ease;\n -webkit-appearance: none;\n }\n .bs-input::placeholder, .bs-textarea::placeholder { color: var(--bs-muted); opacity: 0.5; }\n .bs-input:focus, .bs-textarea:focus {\n outline: none;\n border-color: var(--bs-accent);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--bs-accent) 15%, transparent);\n }\n .bs-textarea { resize: vertical; min-height: 76px; line-height: 1.5; }\n /* ── Severity ── */\n .bs-sev-row { display: flex; gap: 8px; }\n .bs-sev-btn {\n all: unset;\n flex: 1;\n padding: 10px 0;\n border-radius: var(--bs-radius-sm);\n text-align: center;\n font-size: 12px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: all 0.25s ease;\n position: relative;\n }\n .bs-sev-btn.bs-sev-low { background: color-mix(in srgb, var(--bs-green) 8%, transparent); color: var(--bs-green); border: 1.5px solid color-mix(in srgb, var(--bs-green) 15%, transparent); }\n .bs-sev-btn.bs-sev-medium { background: color-mix(in srgb, var(--bs-yellow) 8%, transparent); color: var(--bs-yellow); border: 1.5px solid color-mix(in srgb, var(--bs-yellow) 15%, transparent); }\n .bs-sev-btn.bs-sev-high { background: color-mix(in srgb, var(--bs-orange) 8%, transparent); color: var(--bs-orange); border: 1.5px solid color-mix(in srgb, var(--bs-orange) 15%, transparent); }\n .bs-sev-btn.bs-sev-critical { background: color-mix(in srgb, var(--bs-red) 8%, transparent); color: var(--bs-red); border: 1.5px solid color-mix(in srgb, var(--bs-red) 15%, transparent); }\n .bs-sev-btn:hover { transform: translateY(-1px); }\n .bs-sev-btn:active { transform: scale(0.96); }\n .bs-sev-btn.bs-picked { box-shadow: 0 0 0 2px currentColor; transform: translateY(-1px); }\n .bs-sev-btn.bs-picked::after {\n content: '';\n position: absolute;\n top: 4px;\n right: 6px;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: currentColor;\n animation: bs-pop 0.3s cubic-bezier(0.34,1.56,0.64,1);\n }\n @keyframes bs-pop { from { transform: scale(0); } to { transform: scale(1); } }\n\n /* ── Screenshot ── */\n .bs-shot-area {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n background: var(--bs-bg2);\n border: 1.5px dashed var(--bs-border);\n border-radius: var(--bs-radius-sm);\n margin-bottom: 16px;\n cursor: pointer;\n transition: all 0.25s ease;\n }\n .bs-shot-area:hover { border-color: var(--bs-accent); border-style: solid; background: var(--bs-bg3); }\n .bs-shot-area:active { transform: scale(0.98); }\n .bs-shot-icon {\n width: 40px;\n height: 40px;\n border-radius: var(--bs-radius-sm);\n background: color-mix(in srgb, var(--bs-accent) 12%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--bs-accent);\n flex-shrink: 0;\n }\n .bs-shot-text { flex: 1; }\n .bs-shot-title { font-size: 13px; font-weight: 600; color: var(--bs-text); }\n .bs-shot-sub { font-size: 11px; color: var(--bs-muted); margin-top: 2px; }\n .bs-shot-area.bs-captured { border-style: solid; border-color: var(--bs-green); }\n .bs-shot-area.bs-captured .bs-shot-icon { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n\n /* ── Category Chips ── */\n .bs-cat-row { display: flex; flex-wrap: wrap; gap: 6px; }\n .bs-cat-btn {\n all: unset;\n padding: 7px 14px;\n border-radius: 20px;\n font-size: 12px;\n font-weight: 600;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n transition: all 0.2s ease;\n background: var(--bs-bg2);\n color: var(--bs-muted);\n border: 1.5px solid var(--bs-border);\n }\n .bs-cat-btn:hover { color: var(--bs-text); border-color: var(--bs-accent); }\n .bs-cat-btn.bs-picked {\n background: color-mix(in srgb, var(--bs-accent) 12%, transparent);\n color: var(--bs-accent);\n border-color: var(--bs-accent);\n }\n\n /* ── Context Bar ── */\n .bs-ctx-bar {\n display: flex;\n gap: 2px;\n margin-bottom: 16px;\n background: var(--bs-bg2);\n border-radius: var(--bs-radius-sm);\n padding: 3px;\n border: 1px solid var(--bs-border);\n }\n .bs-ctx-chip {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n padding: 8px 4px;\n border-radius: calc(var(--bs-radius-sm) - 2px);\n transition: background 0.2s;\n }\n .bs-ctx-chip.bs-has { background: var(--bs-bg3); }\n .bs-ctx-chip.bs-alert { background: color-mix(in srgb, var(--bs-red) 8%, transparent); }\n .bs-ctx-n {\n font-size: 15px;\n font-weight: 700;\n color: var(--bs-text);\n line-height: 1;\n }\n .bs-ctx-chip.bs-alert .bs-ctx-n { color: var(--bs-red); }\n .bs-ctx-l {\n font-size: 9px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n color: var(--bs-muted);\n }\n\n /* ── Report Summary Bar ── */\n .bs-report-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n border-radius: var(--bs-radius-sm);\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n margin-bottom: 16px;\n font-size: 12px;\n color: var(--bs-muted);\n }\n .bs-report-summary.bs-alert {\n background: color-mix(in srgb, var(--bs-red) 6%, transparent);\n border-color: color-mix(in srgb, var(--bs-red) 15%, transparent);\n color: var(--bs-red);\n }\n .bs-report-summary.bs-has { color: var(--bs-text); }\n .bs-report-summary-left { display: flex; align-items: center; gap: 8px; }\n .bs-report-summary-icon {\n width: 22px; height: 22px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--bs-green) 12%, transparent);\n color: var(--bs-green);\n display: flex; align-items: center; justify-content: center;\n font-size: 10px; flex-shrink: 0;\n }\n .bs-report-summary-icon.bs-warn {\n background: color-mix(in srgb, var(--bs-red) 12%, transparent);\n color: var(--bs-red);\n font-weight: 800; font-size: 12px;\n }\n .bs-input-title {\n font-size: 16px !important;\n font-weight: 600;\n padding: 14px !important;\n }\n\n .bs-auto-step-n {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: color-mix(in srgb, var(--bs-accent) 15%, transparent);\n color: var(--bs-accent);\n font-size: 10px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n .bs-auto-muted {\n font-size: 12px;\n color: var(--bs-muted);\n padding: 6px 0;\n }\n\n /* ── Submit ── */\n .bs-submit-btn {\n all: unset;\n width: 100%;\n padding: 14px;\n background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff;\n border-radius: var(--bs-radius-sm);\n font-size: 15px;\n font-weight: 700;\n font-family: 'Inter', sans-serif;\n cursor: pointer;\n text-align: center;\n box-sizing: border-box;\n transition: all 0.3s ease;\n position: relative;\n overflow: hidden;\n }\n .bs-submit-btn:hover { box-shadow: 0 8px 28px rgba(0,0,0,0.3); transform: translateY(-1px); }\n .bs-submit-btn:active { transform: translateY(0) scale(0.98); }\n .bs-submit-btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none !important; box-shadow: none !important; }\n .bs-submit-btn.bs-submit-ok {\n background: var(--bs-green) !important;\n opacity: 1 !important;\n display: flex; align-items: center; justify-content: center; gap: 6px;\n }\n .bs-submit-btn.bs-submit-err {\n background: var(--bs-red) !important;\n opacity: 1 !important;\n font-size: 13px;\n }\n\n /* ── Console ── */\n .bs-log {\n padding: 8px 10px;\n border-radius: var(--bs-radius-sm);\n margin-bottom: 4px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11.5px;\n line-height: 1.5;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n transition: background 0.15s;\n }\n .bs-log:hover { background: var(--bs-bg2); }\n .bs-log-lv {\n font-weight: 700;\n text-transform: uppercase;\n font-size: 9px;\n padding: 3px 6px;\n border-radius: 5px;\n flex-shrink: 0;\n margin-top: 2px;\n letter-spacing: 0.4px;\n }\n .bs-log-lv.bs-le { background: color-mix(in srgb, var(--bs-red) 12%, transparent); color: var(--bs-red); }\n .bs-log-lv.bs-lw { background: color-mix(in srgb, var(--bs-orange) 10%, transparent); color: var(--bs-orange); }\n .bs-log-lv.bs-ll { background: var(--bs-bg3); color: var(--bs-muted); }\n .bs-log-lv.bs-li { background: color-mix(in srgb, var(--bs-accent) 10%, transparent); color: var(--bs-accent); }\n .bs-log-lv.bs-ld { background: var(--bs-bg2); color: var(--bs-muted); }\n .bs-log-m { color: var(--bs-text); word-break: break-word; flex: 1; white-space: pre-wrap; }\n .bs-log-t { color: var(--bs-muted); opacity: 0.5; flex-shrink: 0; font-size: 10px; margin-top: 3px; }\n\n /* ── Network ── */\n .bs-net {\n padding: 9px 10px;\n border-radius: var(--bs-radius-sm);\n margin-bottom: 4px;\n font-family: 'SF Mono', 'Fira Code', monospace;\n font-size: 11.5px;\n display: flex;\n gap: 8px;\n align-items: center;\n transition: background 0.15s;\n }\n .bs-net:hover { background: var(--bs-bg2); }\n .bs-net-m { font-weight: 700; font-size: 10px; color: var(--bs-accent); flex-shrink: 0; width: 34px; }\n .bs-net-s { font-weight: 700; font-size: 10px; padding: 3px 7px; border-radius: 5px; flex-shrink: 0; }\n .bs-net-s.bs-ok { background: color-mix(in srgb, var(--bs-green) 10%, transparent); color: var(--bs-green); }\n .bs-net-s.bs-fail { background: color-mix(in srgb, var(--bs-red) 10%, transparent); color: var(--bs-red); }\n .bs-net-u { color: var(--bs-text); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .bs-net-d { color: var(--bs-muted); opacity: 0.5; flex-shrink: 0; font-size: 10px; }\n\n /* ── Context: Errors ── */\n .bs-err-card {\n padding: 12px 14px;\n margin-bottom: 8px;\n background: color-mix(in srgb, var(--bs-red) 6%, transparent);\n border: 1px solid color-mix(in srgb, var(--bs-red) 10%, transparent);\n border-radius: var(--bs-radius-sm);\n transition: border-color 0.2s;\n }\n .bs-err-card:hover { border-color: color-mix(in srgb, var(--bs-red) 20%, transparent); }\n .bs-err-m { color: var(--bs-red); font-weight: 600; font-size: 13px; margin-bottom: 6px; line-height: 1.4; }\n .bs-err-stack {\n font-family: 'SF Mono', monospace;\n font-size: 10px;\n color: var(--bs-muted);\n white-space: pre-wrap;\n max-height: 72px;\n overflow-y: auto;\n line-height: 1.5;\n }\n .bs-err-meta { font-size: 10px; color: var(--bs-muted); margin-top: 6px; }\n\n /* ── Context: Section Title ── */\n .bs-sec {\n font-size: 10px;\n font-weight: 700;\n color: var(--bs-accent);\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin: 20px 0 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid var(--bs-border);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .bs-sec:first-child { margin-top: 0; }\n .bs-sec-n {\n background: var(--bs-bg3);\n color: var(--bs-muted);\n font-size: 9px;\n padding: 2px 6px;\n border-radius: 5px;\n }\n\n /* ── KV Grid ── */\n .bs-kv {\n display: grid;\n grid-template-columns: 100px 1fr;\n gap: 7px 12px;\n font-size: 12px;\n }\n .bs-kv-k { color: var(--bs-muted); font-size: 11px; }\n .bs-kv-v { color: var(--bs-text); word-break: break-all; font-size: 11px; }\n\n /* ── Breadcrumbs ── */\n .bs-bc {\n padding: 7px 10px;\n border-radius: 8px;\n margin-bottom: 3px;\n font-size: 11px;\n display: flex;\n gap: 8px;\n align-items: flex-start;\n transition: background 0.15s;\n }\n .bs-bc:hover { background: var(--bs-bg2); }\n .bs-bc-t {\n font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;\n padding: 3px 6px; border-radius: 5px; flex-shrink: 0;\n background: var(--bs-bg3); color: var(--bs-muted);\n }\n .bs-bc-t.bs-t-click { color: var(--bs-accent); background: color-mix(in srgb, var(--bs-accent) 10%, transparent); }\n .bs-bc-t.bs-t-input { color: var(--bs-green); background: color-mix(in srgb, var(--bs-green) 10%, transparent); }\n .bs-bc-t.bs-t-navigation { color: var(--bs-accent2); background: color-mix(in srgb, var(--bs-accent2) 10%, transparent); }\n .bs-bc-t.bs-t-error { color: var(--bs-red); background: color-mix(in srgb, var(--bs-red) 10%, transparent); }\n .bs-bc-t.bs-t-network { color: var(--bs-orange); background: color-mix(in srgb, var(--bs-orange) 10%, transparent); }\n .bs-bc-t.bs-t-console { color: var(--bs-yellow); background: color-mix(in srgb, var(--bs-yellow) 10%, transparent); }\n .bs-bc-t.bs-t-custom { color: var(--bs-accent); background: color-mix(in srgb, var(--bs-accent) 10%, transparent); }\n .bs-bc-m { color: var(--bs-text); flex: 1; line-height: 1.4; }\n .bs-bc-time { color: var(--bs-muted); opacity: 0.5; font-size: 10px; flex-shrink: 0; }\n\n /* ── Performance ── */\n .bs-pf { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }\n .bs-pf-l { font-size: 11px; color: var(--bs-muted); width: 85px; flex-shrink: 0; }\n .bs-pf-tr { flex: 1; height: 6px; background: var(--bs-bg3); border-radius: 4px; overflow: hidden; }\n .bs-pf-fl { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--bs-accent), var(--bs-accent2)); transition: width 0.6s cubic-bezier(0.34,1.56,0.64,1); }\n .bs-pf-fl.bs-slow { background: linear-gradient(90deg, var(--bs-orange), var(--bs-red)); }\n .bs-pf-v { font-size: 11px; font-weight: 600; color: var(--bs-text); width: 55px; text-align: right; flex-shrink: 0; }\n\n /* ── Annotation ── */\n .bs-ann-wrap { position: relative; margin-bottom: 16px; border-radius: var(--bs-radius-sm); overflow: hidden; border: 1.5px solid var(--bs-border); animation: bs-slideUp 0.3s ease; }\n .bs-ann-viewport { overflow: hidden; position: relative; }\n .bs-ann-canvas { display: block; width: 100%; transform-origin: 0 0; transition: transform 0.15s ease; }\n .bs-ann-canvas.bs-select { cursor: default; }\n .bs-ann-canvas.bs-draw { cursor: crosshair; }\n .bs-ann-canvas.bs-arrow { cursor: crosshair; }\n .bs-ann-canvas.bs-rect { cursor: crosshair; }\n .bs-ann-canvas.bs-circle { cursor: crosshair; }\n .bs-ann-canvas.bs-text { cursor: text; }\n .bs-ann-canvas.bs-highlight { cursor: crosshair; }\n .bs-ann-canvas.bs-grab { cursor: grab; }\n .bs-ann-canvas.bs-grabbing { cursor: grabbing; }\n .bs-ann-toolbar { display: flex; gap: 2px; padding: 6px 8px; background: var(--bs-bg2); border-top: 1px solid var(--bs-border); align-items: center; flex-wrap: wrap; }\n .bs-ann-sep { width: 1px; height: 20px; background: var(--bs-border); margin: 0 4px; flex-shrink: 0; }\n .bs-ann-btn {\n all: unset; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;\n border-radius: 6px; cursor: pointer; color: var(--bs-muted); transition: all 0.15s; font-size: 14px;\n }\n .bs-ann-btn:hover { background: var(--bs-bg3); color: var(--bs-text); }\n .bs-ann-btn.bs-sel { background: color-mix(in srgb, var(--bs-accent) 15%, transparent); color: var(--bs-accent); }\n .bs-ann-btn[title]::after { content: none; }\n .bs-ann-dot {\n width: 20px; height: 20px; border-radius: 50%; border: 2.5px solid transparent; cursor: pointer;\n transition: all 0.15s; flex-shrink: 0;\n }\n .bs-ann-dot:hover { transform: scale(1.15); }\n .bs-ann-dot.bs-sel { border-color: var(--bs-text); transform: scale(1.15); box-shadow: 0 0 8px rgba(255,255,255,0.15); }\n .bs-ann-size {\n width: 60px; height: 4px; -webkit-appearance: none; appearance: none; background: var(--bs-border);\n border-radius: 2px; outline: none; cursor: pointer;\n }\n .bs-ann-size::-webkit-slider-thumb {\n -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;\n background: var(--bs-accent); cursor: pointer; border: 2px solid var(--bs-bg);\n }\n .bs-ann-zoom-label { font-size: 10px; font-weight: 600; color: var(--bs-muted); min-width: 32px; text-align: center; }\n .bs-ann-right { margin-left: auto; display: flex; gap: 2px; align-items: center; }\n .bs-ann-clr-btn {\n all: unset; padding: 3px 10px; border: 1px solid var(--bs-border); border-radius: 6px;\n color: var(--bs-muted); font-size: 10px; cursor: pointer; font-family: 'Inter', sans-serif; transition: all 0.15s;\n }\n .bs-ann-clr-btn:hover { color: var(--bs-red); border-color: color-mix(in srgb, var(--bs-red) 30%, transparent); }\n\n /* ── Pin Tool ── */\n .bs-ann-canvas.bs-pin { cursor: crosshair; }\n .bs-ann-pins { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }\n .bs-ann-pin {\n position: absolute;\n width: 26px; height: 26px;\n border-radius: 50% 50% 50% 0;\n transform: translate(-50%, -100%) rotate(-45deg);\n display: flex; align-items: center; justify-content: center;\n font-size: 11px; font-weight: 700; font-family: 'Inter', sans-serif;\n color: #fff;\n pointer-events: all;\n cursor: grab;\n transition: transform 0.15s, box-shadow 0.15s;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n z-index: 1;\n }\n .bs-ann-pin:hover { transform: translate(-50%, -100%) rotate(-45deg) scale(1.15); box-shadow: 0 4px 16px rgba(0,0,0,0.4); z-index: 2; }\n .bs-ann-pin.bs-dragging { cursor: grabbing; transform: translate(-50%, -100%) rotate(-45deg) scale(1.2); z-index: 3; }\n .bs-ann-pin-n { transform: rotate(45deg); line-height: 1; }\n .bs-ann-pin-pulse {\n position: absolute; inset: -4px; border-radius: 50% 50% 50% 0;\n border: 2px solid currentColor; opacity: 0;\n animation: bs-pin-ring 1.5s ease-out forwards;\n }\n @keyframes bs-pin-ring { 0% { opacity: 0.6; inset: -4px; } 100% { opacity: 0; inset: -14px; } }\n\n /* ── Pin List (below canvas) ── */\n .bs-ann-pin-list {\n max-height: 140px;\n overflow-y: auto;\n border-top: 1px solid var(--bs-border);\n background: var(--bs-bg2);\n }\n .bs-ann-pin-item {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 8px 12px;\n border-bottom: 1px solid color-mix(in srgb, var(--bs-border) 50%, transparent);\n font-size: 12px;\n color: var(--bs-text);\n }\n .bs-ann-pin-item:last-child { border-bottom: none; }\n .bs-ann-pin-num {\n width: 22px; height: 22px;\n border-radius: 50%;\n display: flex; align-items: center; justify-content: center;\n font-size: 11px; font-weight: 700; color: #fff;\n flex-shrink: 0;\n }\n .bs-ann-pin-body { flex: 1; min-width: 0; }\n .bs-ann-pin-note { word-break: break-word; line-height: 1.4; }\n .bs-ann-pin-loc { font-size: 10px; color: var(--bs-muted); margin-top: 2px; }\n .bs-ann-pin-del {\n all: unset; cursor: pointer; color: var(--bs-muted); font-size: 14px;\n padding: 2px 4px; border-radius: 4px; transition: color 0.15s;\n flex-shrink: 0;\n }\n .bs-ann-pin-del:hover { color: var(--bs-red); }\n\n /* ── History ── */\n .bs-hist-card {\n background: var(--bs-bg2);\n border: 1px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n padding: 14px;\n margin-bottom: 10px;\n transition: border-color 0.2s;\n }\n .bs-hist-card:hover { border-color: var(--bs-accent); }\n .bs-hist-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; margin-bottom: 8px; }\n .bs-hist-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--bs-text);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .bs-hist-actions { display: flex; gap: 4px; flex-shrink: 0; }\n .bs-hist-btn {\n all: unset;\n width: 26px; height: 26px;\n display: flex; align-items: center; justify-content: center;\n border-radius: 6px;\n cursor: pointer;\n color: var(--bs-muted);\n transition: all 0.15s;\n font-size: 12px;\n }\n .bs-hist-btn:hover { background: var(--bs-bg3); color: var(--bs-text); }\n .bs-hist-btn.bs-del:hover { color: var(--bs-red); }\n .bs-hist-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 6px; }\n .bs-hist-badge {\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n }\n .bs-hist-badge.bs-sev-low { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n .bs-hist-badge.bs-sev-medium { background: color-mix(in srgb, var(--bs-yellow) 12%, transparent); color: var(--bs-yellow); }\n .bs-hist-badge.bs-sev-high { background: color-mix(in srgb, var(--bs-orange) 12%, transparent); color: var(--bs-orange); }\n .bs-hist-badge.bs-sev-critical { background: color-mix(in srgb, var(--bs-red) 12%, transparent); color: var(--bs-red); }\n .bs-hist-badge.bs-cat { background: color-mix(in srgb, var(--bs-accent) 12%, transparent); color: var(--bs-accent); }\n .bs-hist-badge.bs-status-sent { background: color-mix(in srgb, var(--bs-green) 12%, transparent); color: var(--bs-green); }\n .bs-hist-badge.bs-status-draft { background: color-mix(in srgb, var(--bs-yellow) 12%, transparent); color: var(--bs-yellow); }\n .bs-hist-desc { font-size: 12px; color: var(--bs-muted); line-height: 1.5; margin-bottom: 6px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }\n .bs-hist-foot { display: flex; justify-content: space-between; align-items: center; font-size: 10px; color: var(--bs-muted); }\n .bs-hist-pins { display: flex; gap: 4px; }\n .bs-hist-pin-dot { width: 18px; height: 18px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 9px; font-weight: 700; color: #fff; }\n .bs-hist-thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; border: 1px solid var(--bs-border); flex-shrink: 0; }\n .bs-hist-confirm {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 14px;\n background: color-mix(in srgb, var(--bs-red) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--bs-red) 20%, transparent);\n border-radius: var(--bs-radius-sm);\n margin-bottom: 10px;\n font-size: 12px; color: var(--bs-text);\n animation: bs-slideUp 0.2s ease;\n }\n .bs-hist-confirm-yes {\n all: unset; padding: 4px 12px; background: var(--bs-red); color: #fff; border-radius: 6px;\n font-size: 11px; font-weight: 600; cursor: pointer; font-family: 'Inter', sans-serif;\n }\n .bs-hist-confirm-no {\n all: unset; padding: 4px 12px; border: 1px solid var(--bs-border); border-radius: 6px;\n font-size: 11px; font-weight: 600; cursor: pointer; color: var(--bs-muted); font-family: 'Inter', sans-serif;\n }\n .bs-hist-edit-wrap { margin-bottom: 10px; animation: bs-slideUp 0.2s ease; }\n .bs-hist-edit-row { display: flex; gap: 6px; margin-top: 8px; }\n .bs-hist-save {\n all: unset; padding: 6px 16px; background: linear-gradient(135deg, var(--bs-fab1), var(--bs-fab2));\n color: #fff; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; font-family: 'Inter', sans-serif;\n }\n .bs-hist-cancel {\n all: unset; padding: 6px 16px; border: 1px solid var(--bs-border); border-radius: 6px;\n font-size: 12px; font-weight: 600; cursor: pointer; color: var(--bs-muted); font-family: 'Inter', sans-serif;\n }\n\n /* ── Empty ── */\n .bs-empty { text-align: center; padding: 36px 16px; color: var(--bs-muted); font-size: 13px; line-height: 1.6; }\n .bs-empty svg { opacity: 0.12; margin-bottom: 10px; }\n\n /* ── Settings ── */\n .bs-set-sec {\n font-size: 11px;\n font-weight: 700;\n color: var(--bs-accent);\n text-transform: uppercase;\n letter-spacing: 0.8px;\n margin: 0 0 12px;\n }\n .bs-set-sec + .bs-set-sec { margin-top: 24px; }\n .bs-set-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));\n gap: 8px;\n }\n .bs-set-card {\n all: unset;\n cursor: pointer;\n border: 2px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n overflow: hidden;\n transition: all 0.2s ease;\n display: flex;\n flex-direction: column;\n }\n .bs-set-card:hover { border-color: var(--bs-accent); transform: translateY(-1px); }\n .bs-set-card.bs-picked { border-color: var(--bs-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bs-accent) 25%, transparent); }\n .bs-set-preview {\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n }\n .bs-set-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n border: 1px solid rgba(255,255,255,0.1);\n }\n .bs-set-name {\n padding: 6px 8px;\n font-family: 'Inter', sans-serif;\n font-size: 10px;\n font-weight: 600;\n text-align: center;\n color: var(--bs-text);\n background: var(--bs-bg2);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .bs-set-ly-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));\n gap: 8px;\n }\n .bs-set-ly {\n all: unset;\n cursor: pointer;\n border: 2px solid var(--bs-border);\n border-radius: var(--bs-radius-sm);\n padding: 10px 12px;\n transition: all 0.2s ease;\n font-family: 'Inter', sans-serif;\n }\n .bs-set-ly:hover { border-color: var(--bs-accent); transform: translateY(-1px); }\n .bs-set-ly.bs-picked { border-color: var(--bs-accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bs-accent) 25%, transparent); }\n .bs-set-ly-name { font-size: 12px; font-weight: 600; color: var(--bs-text); margin-bottom: 2px; }\n .bs-set-ly-desc { font-size: 10px; color: var(--bs-muted); }\n`;\n\n// ─── Login Tab ───────────────────────────────────────────\n\nfunction tabLogin(): string {\n return `\n <div class=\"bs-login-form\">\n <div class=\"bs-login-logo\">BugStash</div>\n <div class=\"bs-login-subtitle\">Sign in to report bugs & collaborate</div>\n <input class=\"bs-login-input\" type=\"email\" id=\"bs-login-email\" placeholder=\"Email\" autocomplete=\"email\" />\n <input class=\"bs-login-input\" type=\"password\" id=\"bs-login-pass\" placeholder=\"Password\" autocomplete=\"current-password\" />\n <div class=\"bs-login-error\" id=\"bs-login-error\" style=\"display:none\"></div>\n <button class=\"bs-login-btn\" id=\"bs-login-submit\">Sign In</button>\n <div style=\"font-size:11px;color:var(--bs-muted);margin-top:4px\">Contact your admin for an account</div>\n </div>\n `;\n}\n\n// ─── Helpers ─────────────────────────────────────────────\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\nfunction timeAgo(ts: number): string {\n const s = Math.floor((Date.now() - ts) / 1000);\n if (s < 5) return 'now';\n if (s < 60) return `${s}s ago`;\n if (s < 3600) return `${Math.floor(s / 60)}m ago`;\n return new Date(ts).toLocaleTimeString();\n}\nfunction fmtTime(ts: number): string {\n return new Date(ts).toLocaleTimeString('en', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n}\n\n// ─── Report History (localStorage) ───────────────────────\n\nconst HISTORY_KEY = 'bugstash_history';\n\ninterface HistoryEntry {\n id: number;\n title: string;\n description: string;\n category: string;\n severity: string;\n tags?: string[];\n screenshot?: string;\n pins?: { number: number; x: number; y: number; note: string }[];\n url: string;\n createdAt: number;\n status: 'sent' | 'draft';\n}\n\nfunction getReportHistory(): HistoryEntry[] {\n try {\n return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]');\n } catch { return []; }\n}\n\nfunction saveReportHistory(entries: HistoryEntry[]) {\n try {\n localStorage.setItem(HISTORY_KEY, JSON.stringify(entries));\n } catch { /* quota exceeded */ }\n}\n\nfunction addToHistory(entry: Omit<HistoryEntry, 'id'>) {\n const entries = getReportHistory();\n const id = Date.now();\n entries.unshift({ ...entry, id });\n // Keep last 50\n if (entries.length > 50) entries.length = 50;\n saveReportHistory(entries);\n}\n\nfunction deleteFromHistory(id: number) {\n const entries = getReportHistory().filter(e => e.id !== id);\n saveReportHistory(entries);\n}\n\nfunction updateInHistory(id: number, updates: Partial<HistoryEntry>) {\n const entries = getReportHistory();\n const idx = entries.findIndex(e => e.id === id);\n if (idx >= 0) {\n entries[idx] = { ...entries[idx], ...updates };\n saveReportHistory(entries);\n }\n}\n\n// ─── Build Context ───────────────────────────────────────\n\nfunction buildContext(): ReportContext {\n return {\n url: window.location.href,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n language: navigator.language,\n cookiesEnabled: navigator.cookieEnabled,\n online: navigator.onLine,\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n timestamp: Date.now(),\n environment: config.environment ?? 'development',\n commitHash: config.commitHash,\n user: config.user,\n };\n}\n\n// ─── Tab Content ─────────────────────────────────────────\n\nfunction autoDetect() {\n const errors = getErrors();\n const logs = getLogs();\n const net = getNetworkCaptures();\n const failedNet = getFailedNetworkCaptures();\n const crumbs = getBreadcrumbs();\n const perf = getPerformanceMetrics();\n const consoleErrors = logs.filter(l => l.level === 'error');\n\n // Auto-detect severity\n let severity: BugReport['severity'] = 'low';\n if (errors.length >= 3 || failedNet.length >= 3) severity = 'critical';\n else if (errors.length >= 1 || failedNet.length >= 2) severity = 'high';\n else if (consoleErrors.length > 0 || failedNet.length >= 1) severity = 'medium';\n\n // Auto-generate tags\n const tags: string[] = [];\n if (errors.length) tags.push('has-errors');\n if (failedNet.length) tags.push('network-failures');\n if (consoleErrors.length) tags.push('console-errors');\n if (perf?.pageLoadTime && perf.pageLoadTime > 3000) tags.push('slow-load');\n if (perf?.cumulativeLayoutShift && perf.cumulativeLayoutShift > 0.25) tags.push('layout-shift');\n if (!navigator.onLine) tags.push('offline');\n if (window.innerWidth < 768) tags.push('mobile');\n\n return { severity, tags,\n counts: { logs: logs.length, network: net.length, failedNet: failedNet.length, errors: errors.length, crumbs: crumbs.length } };\n}\n\nfunction tabReport(): string {\n const d = autoDetect();\n const categories: { id: BugReport['category']; label: string }[] = [\n { id: 'ui', label: 'UI' },\n { id: 'functionality', label: 'Feature' },\n { id: 'performance', label: 'Speed' },\n { id: 'crash', label: 'Crash' },\n { id: 'security', label: 'Security' },\n { id: 'other', label: 'Other' },\n ];\n\n const hasIssues = d.counts.errors > 0 || d.counts.failedNet > 0;\n const summaryClass = hasIssues ? ' bs-alert' : d.counts.logs > 0 ? ' bs-has' : '';\n\n return `<div class=\"bs-view\">\n <form data-bs-form>\n <div class=\"bs-report-summary${summaryClass}\">\n <div class=\"bs-report-summary-left\">\n ${hasIssues\n ? `<div class=\"bs-report-summary-icon bs-warn\">!</div><span>${d.counts.errors} error${d.counts.errors !== 1 ? 's' : ''}, ${d.counts.failedNet} failed request${d.counts.failedNet !== 1 ? 's' : ''} detected</span>`\n : `<div class=\"bs-report-summary-icon\">${I.check}</div><span>Auto-collecting ${d.counts.logs} logs, ${d.counts.network} requests, ${d.counts.crumbs} actions</span>`}\n </div>\n </div>\n <div class=\"bs-field\">\n <input class=\"bs-input bs-input-title\" name=\"title\" placeholder=\"What's the bug?\" required autocomplete=\"off\" />\n </div>\n <div class=\"bs-field\">\n <textarea class=\"bs-textarea\" name=\"description\" placeholder=\"Steps to reproduce or extra details (optional)\"></textarea>\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Category</div>\n <input type=\"hidden\" name=\"category\" value=\"functionality\" />\n <div class=\"bs-cat-row\">\n ${categories.map(c => `<button type=\"button\" class=\"bs-cat-btn${c.id === 'functionality' ? ' bs-picked' : ''}\" data-cat=\"${c.id}\">${c.label}</button>`).join('')}\n </div>\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Severity</div>\n <input type=\"hidden\" name=\"severity\" value=\"${d.severity}\" />\n <div class=\"bs-sev-row\">\n <button type=\"button\" class=\"bs-sev-btn bs-sev-low${d.severity === 'low' ? ' bs-picked' : ''}\" data-sev=\"low\">Low</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-medium${d.severity === 'medium' ? ' bs-picked' : ''}\" data-sev=\"medium\">Med</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-high${d.severity === 'high' ? ' bs-picked' : ''}\" data-sev=\"high\">High</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-critical${d.severity === 'critical' ? ' bs-picked' : ''}\" data-sev=\"critical\">Critical</button>\n </div>\n </div>\n <div class=\"bs-shot-area\" data-bs-screenshot>\n <div class=\"bs-shot-icon\">${I.cam}</div>\n <div class=\"bs-shot-text\">\n <div class=\"bs-shot-title\" data-bs-shot-title>Attach screenshot</div>\n <div class=\"bs-shot-sub\" data-bs-shot-sub>Capture & annotate the current view</div>\n </div>\n </div>\n <div data-bs-annotate></div>\n <button type=\"submit\" class=\"bs-submit-btn\">Submit Report</button>\n </form>\n </div>`;\n}\n\nfunction tabConsole(): string {\n const logs = getLogs();\n const lvMap: Record<string, string> = { error: 'bs-le', warn: 'bs-lw', log: 'bs-ll', info: 'bs-li', debug: 'bs-ld' };\n if (!logs.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No console logs captured yet.<br>Use the app — logs will appear here automatically.</p></div></div>`;\n }\n return `<div class=\"bs-view\">${logs.slice().reverse().map(l =>\n `<div class=\"bs-log\"><span class=\"bs-log-lv ${lvMap[l.level] || 'bs-ll'}\">${l.level}</span><span class=\"bs-log-m\">${esc(l.args.join(' ')).slice(0, 500)}</span><span class=\"bs-log-t\">${fmtTime(l.timestamp)}</span></div>`\n ).join('')}</div>`;\n}\n\nfunction tabNetwork(): string {\n const caps = getNetworkCaptures();\n if (!caps.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No network requests captured yet.<br>API calls will show up here automatically.</p></div></div>`;\n }\n return `<div class=\"bs-view\">${caps.slice().reverse().map(n =>\n `<div class=\"bs-net\"><span class=\"bs-net-m\">${n.method}</span><span class=\"bs-net-s ${n.failed ? 'bs-fail' : 'bs-ok'}\">${n.status || 'ERR'}</span><span class=\"bs-net-u\" title=\"${esc(n.url)}\">${esc(n.url)}</span><span class=\"bs-net-d\">${n.duration}ms</span></div>`\n ).join('')}</div>`;\n}\n\nfunction tabContext(): string {\n let html = `<div class=\"bs-view\">`;\n\n const errs = getErrors();\n if (errs.length) {\n html += `<div class=\"bs-sec\">Errors <span class=\"bs-sec-n\">${errs.length}</span></div>`;\n html += errs.slice().reverse().map(e =>\n `<div class=\"bs-err-card\"><div class=\"bs-err-m\">${esc(e.message)}</div>${e.stack ? `<div class=\"bs-err-stack\">${esc(e.stack)}</div>` : ''}<div class=\"bs-err-meta\">${e.type} &middot; ${fmtTime(e.timestamp)}${e.source ? ` &middot; ${esc(e.source)}:${e.lineno}` : ''}</div></div>`\n ).join('');\n }\n\n const perf = getPerformanceMetrics();\n if (perf) {\n html += `<div class=\"bs-sec\">Performance</div>`;\n const bars: [string, number | undefined, number][] = [\n ['Page Load', perf.pageLoadTime, 5000], ['DOM Ready', perf.domContentLoaded, 3000],\n ['First Paint', perf.firstPaint, 2000], ['FCP', perf.firstContentfulPaint, 2500],\n ['LCP', perf.largestContentfulPaint, 4000], ['FID', perf.firstInputDelay, 300],\n ];\n for (const [label, val, max] of bars) {\n if (val === undefined) continue;\n const pct = Math.min(100, (val / max) * 100);\n html += `<div class=\"bs-pf\"><span class=\"bs-pf-l\">${label}</span><div class=\"bs-pf-tr\"><div class=\"bs-pf-fl${pct > 75 ? ' bs-slow' : ''}\" style=\"width:${pct}%\"></div></div><span class=\"bs-pf-v\">${val}ms</span></div>`;\n }\n if (perf.cumulativeLayoutShift !== undefined) {\n const p = Math.min(100, perf.cumulativeLayoutShift * 400);\n html += `<div class=\"bs-pf\"><span class=\"bs-pf-l\">CLS</span><div class=\"bs-pf-tr\"><div class=\"bs-pf-fl${p > 40 ? ' bs-slow' : ''}\" style=\"width:${p}%\"></div></div><span class=\"bs-pf-v\">${perf.cumulativeLayoutShift}</span></div>`;\n }\n }\n\n const crumbs = getBreadcrumbs();\n if (crumbs.length) {\n html += `<div class=\"bs-sec\">Your activity trail <span class=\"bs-sec-n\">${crumbs.length}</span></div>`;\n html += crumbs.slice().reverse().map(b =>\n `<div class=\"bs-bc\"><span class=\"bs-bc-t bs-t-${b.type}\">${b.type}</span><span class=\"bs-bc-m\">${esc(b.message).slice(0, 120)}</span><span class=\"bs-bc-time\">${timeAgo(b.timestamp)}</span></div>`\n ).join('');\n }\n\n const ctx = buildContext();\n html += `<div class=\"bs-sec\">Environment</div>`;\n html += `<div class=\"bs-kv\">\n <span class=\"bs-kv-k\">URL</span><span class=\"bs-kv-v\">${esc(ctx.url)}</span>\n <span class=\"bs-kv-k\">Viewport</span><span class=\"bs-kv-v\">${ctx.viewportWidth}&times;${ctx.viewportHeight} @${ctx.devicePixelRatio}x</span>\n <span class=\"bs-kv-k\">Screen</span><span class=\"bs-kv-v\">${ctx.screenWidth}&times;${ctx.screenHeight}</span>\n <span class=\"bs-kv-k\">Platform</span><span class=\"bs-kv-v\">${esc(ctx.platform)}</span>\n <span class=\"bs-kv-k\">Language</span><span class=\"bs-kv-v\">${ctx.language}</span>\n ${config.commitHash ? `<span class=\"bs-kv-k\">Commit</span><span class=\"bs-kv-v\">${esc(config.commitHash)}</span>` : ''}\n ${config.user?.email ? `<span class=\"bs-kv-k\">User</span><span class=\"bs-kv-v\">${esc(config.user.email)}</span>` : ''}\n </div>`;\n\n html += `</div>`;\n return html;\n}\n\nfunction tabHistory(): string {\n const entries = getReportHistory();\n if (!entries.length) {\n return `<div class=\"bs-view\"><div class=\"bs-empty\"><p>No reports yet.<br>Submitted bugs will appear here.</p></div></div>`;\n }\n\n const catLabels: Record<string, string> = { ui: 'UI', functionality: 'Feature', performance: 'Perf', crash: 'Crash', security: 'Security', other: 'Other' };\n const fmtDate = (ts: number) => {\n const d = new Date(ts);\n const now = new Date();\n const diffMs = now.getTime() - d.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffH = Math.floor(diffMin / 60);\n if (diffH < 24) return `${diffH}h ago`;\n const diffD = Math.floor(diffH / 24);\n if (diffD < 7) return `${diffD}d ago`;\n return d.toLocaleDateString('en', { month: 'short', day: 'numeric' });\n };\n\n let html = `<div class=\"bs-view\">`;\n for (const e of entries) {\n const pinsHtml = e.pins?.length\n ? `<div class=\"bs-hist-pins\">${e.pins.slice(0, 5).map(p => `<div class=\"bs-hist-pin-dot\" style=\"background:${['#ef4444','#3b82f6','#f59e0b','#10b981','#8b5cf6'][p.number % 5]}\">${p.number}</div>`).join('')}${e.pins.length > 5 ? `<span>+${e.pins.length - 5}</span>` : ''}</div>`\n : '';\n html += `<div class=\"bs-hist-card\" data-hist-id=\"${e.id}\">\n <div class=\"bs-hist-top\">\n <div class=\"bs-hist-title\">${esc(e.title)}</div>\n ${e.screenshot ? `<img class=\"bs-hist-thumb\" src=\"${e.screenshot}\" alt=\"\"/>` : ''}\n <div class=\"bs-hist-actions\">\n <button class=\"bs-hist-btn\" data-hist-edit=\"${e.id}\" title=\"Edit\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg></button>\n <button class=\"bs-hist-btn bs-del\" data-hist-del=\"${e.id}\" title=\"Delete\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6\"/><path d=\"M14 11v6\"/></svg></button>\n </div>\n </div>\n <div class=\"bs-hist-meta\">\n <span class=\"bs-hist-badge bs-cat\">${catLabels[e.category] || e.category}</span>\n <span class=\"bs-hist-badge bs-sev-${e.severity}\">${e.severity}</span>\n <span class=\"bs-hist-badge bs-status-${e.status}\">${e.status}</span>\n </div>\n ${e.description ? `<div class=\"bs-hist-desc\">${esc(e.description)}</div>` : ''}\n <div class=\"bs-hist-foot\">\n <span>${fmtDate(e.createdAt)} &middot; ${esc(e.url.replace(/^https?:\\/\\//, '').slice(0, 40))}</span>\n ${pinsHtml}\n </div>\n </div>`;\n }\n html += `</div>`;\n return html;\n}\n\nfunction tabSettings(): string {\n const themes = getThemes();\n const layouts = getLayouts();\n\n let html = `<div class=\"bs-view\">`;\n\n html += `<div class=\"bs-set-sec\">Layout</div>`;\n html += `<div class=\"bs-set-ly-grid\">`;\n for (const l of layouts) {\n html += `<button class=\"bs-set-ly${l.id === currentLayout.id ? ' bs-picked' : ''}\" data-set-layout=\"${l.id}\"><div class=\"bs-set-ly-name\">${esc(l.name)}</div><div class=\"bs-set-ly-desc\">${esc(l.description)}</div></button>`;\n }\n html += `</div>`;\n\n html += `<div class=\"bs-set-sec\">Theme</div>`;\n html += `<div class=\"bs-set-grid\">`;\n for (const t of themes) {\n html += `<button class=\"bs-set-card${t.id === currentTheme.id ? ' bs-picked' : ''}\" data-set-theme=\"${t.id}\"><div class=\"bs-set-preview\" style=\"background:${t.preview[0]}\"><div class=\"bs-set-dot\" style=\"background:${t.preview[1]}\"></div><div class=\"bs-set-dot\" style=\"background:${t.vars['--bs-accent2'] || t.preview[1]};opacity:0.6\"></div></div><div class=\"bs-set-name\">${esc(t.name)}</div></button>`;\n }\n html += `</div>`;\n\n html += `</div>`;\n return html;\n}\n\n// ─── Annotation ──────────────────────────────────────────\n\nfunction setupAnnotation(container: HTMLElement, screenshotData: string): { getAnnotation: () => string | null; getPins: () => { number: number; x: number; y: number; note: string }[] } {\n const COLORS = ['#f87171', '#3b82f6', '#fb923c', '#4ade80', '#a78bfa', '#facc15'];\n type Tool = 'select' | 'draw' | 'arrow' | 'rect' | 'circle' | 'text' | 'highlight' | 'pin';\n\n interface AnnShape {\n type: 'draw' | 'highlight';\n color: string; size: number; alpha: number;\n points: { x: number; y: number }[];\n }\n interface AnnRect { type: 'rect'; color: string; size: number; x: number; y: number; w: number; h: number; }\n interface AnnCircle { type: 'circle'; color: string; size: number; cx: number; cy: number; rx: number; ry: number; }\n interface AnnArrow { type: 'arrow'; color: string; size: number; x1: number; y1: number; x2: number; y2: number; }\n interface AnnText { type: 'text'; color: string; size: number; x: number; y: number; text: string; }\n type AnnObj = AnnShape | AnnRect | AnnCircle | AnnArrow | AnnText;\n\n let currentColor = COLORS[0];\n interface Pin { x: number; y: number; note: string; color: string; }\n\n let currentTool: Tool = 'draw';\n let brushSize = 4;\n let zoom = 1;\n let isDark = false;\n const shapes: AnnObj[] = [];\n const pins: Pin[] = [];\n let selectedIdx = -1;\n let hoveredIdx = -1;\n let dragging = false;\n let drawing = false;\n let dragOffX = 0, dragOffY = 0;\n let startX = 0, startY = 0;\n let currentDraw: { x: number; y: number }[] = [];\n const PIN_COLORS = ['#ef4444', '#3b82f6', '#f59e0b', '#10b981', '#8b5cf6', '#ec4899'];\n\n const img = new Image();\n img.src = screenshotData;\n\n const wrap = document.createElement('div');\n wrap.className = 'bs-ann-wrap';\n const viewport = document.createElement('div');\n viewport.className = 'bs-ann-viewport';\n const canvas = document.createElement('canvas');\n canvas.className = 'bs-ann-canvas bs-draw';\n const toolbar = document.createElement('div');\n toolbar.className = 'bs-ann-toolbar';\n\n const tIcons: Record<Tool, string> = {\n select: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/></svg>`,\n draw: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M12 19l7-7 3 3-7 7-3-3z\"/><path d=\"M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z\"/><path d=\"M2 2l7.586 7.586\"/></svg>`,\n arrow: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"/><polyline points=\"12 5 19 12 12 19\"/></svg>`,\n rect: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/></svg>`,\n circle: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/></svg>`,\n text: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9.5\" y1=\"20\" x2=\"14.5\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/></svg>`,\n highlight: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M9 11l-6 6v3h9l3-3\"/><path d=\"M22 12l-4.6 4.6a2 2 0 01-2.8 0l-5.2-5.2a2 2 0 010-2.8L14 4\"/></svg>`,\n pin: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0118 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>`,\n };\n const toolNames: Record<Tool, string> = { select: 'Select & Move', draw: 'Draw', arrow: 'Arrow', rect: 'Rectangle', circle: 'Circle', text: 'Text', highlight: 'Highlight', pin: 'Pin Issue' };\n\n // Tool buttons\n const toolBtns: HTMLButtonElement[] = [];\n const setTool = (t: Tool) => {\n currentTool = t;\n selectedIdx = -1;\n canvas.className = `bs-ann-canvas bs-${t}`;\n toolBtns.forEach(b => b.classList.remove('bs-sel'));\n toolBtns.find(b => b.dataset.tool === t)?.classList.add('bs-sel');\n };\n (Object.keys(tIcons) as Tool[]).forEach(t => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.dataset.tool = t;\n btn.className = `bs-ann-btn${t === currentTool ? ' bs-sel' : ''}`;\n btn.title = toolNames[t];\n btn.innerHTML = tIcons[t];\n btn.addEventListener('click', () => setTool(t));\n toolBtns.push(btn);\n toolbar.appendChild(btn);\n });\n\n // Separator\n toolbar.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n\n // Colors\n COLORS.forEach((color, i) => {\n const d = document.createElement('button');\n d.type = 'button';\n d.className = `bs-ann-dot${i === 0 ? ' bs-sel' : ''}`;\n d.style.background = color;\n d.addEventListener('click', () => {\n currentColor = color;\n toolbar.querySelectorAll('.bs-ann-dot').forEach(t => t.classList.remove('bs-sel'));\n d.classList.add('bs-sel');\n });\n toolbar.appendChild(d);\n });\n\n toolbar.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n\n // Brush size\n const sizeSlider = document.createElement('input');\n sizeSlider.type = 'range'; sizeSlider.min = '1'; sizeSlider.max = '12'; sizeSlider.value = '4';\n sizeSlider.className = 'bs-ann-size'; sizeSlider.title = 'Brush size';\n sizeSlider.addEventListener('input', () => { brushSize = parseInt(sizeSlider.value); });\n toolbar.appendChild(sizeSlider);\n\n // Right side\n const right = document.createElement('div');\n right.className = 'bs-ann-right';\n\n const mkBtn = (title: string, svg: string) => {\n const b = document.createElement('button');\n b.type = 'button'; b.className = 'bs-ann-btn'; b.title = title; b.innerHTML = svg;\n return b;\n };\n const zoomOut = mkBtn('Zoom out', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>`);\n const zoomLabel = Object.assign(document.createElement('span'), { className: 'bs-ann-zoom-label', textContent: '100%' });\n const zoomIn = mkBtn('Zoom in', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/><line x1=\"11\" y1=\"8\" x2=\"11\" y2=\"14\"/><line x1=\"8\" y1=\"11\" x2=\"14\" y2=\"11\"/></svg>`);\n const zoomReset = mkBtn('Fit', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><path d=\"M15 3h6v6\"/><path d=\"M9 21H3v-6\"/><path d=\"M21 3l-7 7\"/><path d=\"M3 21l7-7\"/></svg>`);\n const undoBtn = mkBtn('Undo', `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 105.42-8.49L1 10\"/></svg>`);\n const clearBtn = Object.assign(document.createElement('button'), { type: 'button', className: 'bs-ann-clr-btn', textContent: 'Clear' });\n\n const applyZoom = () => { canvas.style.transform = `scale(${zoom})`; zoomLabel.textContent = `${Math.round(zoom * 100)}%`; };\n zoomIn.addEventListener('click', () => { if (zoom < 3) { zoom = Math.min(3, zoom + 0.25); applyZoom(); } });\n zoomOut.addEventListener('click', () => { if (zoom > 0.5) { zoom = Math.max(0.5, zoom - 0.25); applyZoom(); } });\n zoomReset.addEventListener('click', () => { zoom = 1; applyZoom(); });\n\n right.appendChild(Object.assign(document.createElement('div'), { className: 'bs-ann-sep' }));\n [zoomOut, zoomLabel, zoomIn, zoomReset, undoBtn, clearBtn].forEach(el => right.appendChild(el));\n toolbar.appendChild(right);\n\n // Pin overlay layer (positioned over the canvas)\n const pinLayer = document.createElement('div');\n pinLayer.className = 'bs-ann-pins';\n // Pin list below toolbar\n const pinList = document.createElement('div');\n pinList.className = 'bs-ann-pin-list';\n pinList.style.display = 'none';\n\n viewport.appendChild(canvas);\n viewport.appendChild(pinLayer);\n wrap.appendChild(viewport);\n wrap.appendChild(toolbar);\n wrap.appendChild(pinList);\n container.innerHTML = '';\n container.appendChild(wrap);\n\n // ── Pin rendering ──\n const renderPins = () => {\n pinLayer.innerHTML = '';\n pinList.innerHTML = '';\n pinList.style.display = pins.length ? '' : 'none';\n\n pins.forEach((pin, i) => {\n // Pin marker on canvas\n const el = document.createElement('div');\n el.className = 'bs-ann-pin';\n el.style.background = pin.color;\n el.style.color = pin.color;\n // Position as percentage of viewport\n const pctX = (pin.x / (canvas.width || 1)) * 100;\n const pctY = (pin.y / (canvas.height || 1)) * 100;\n el.style.left = `${pctX}%`;\n el.style.top = `${pctY}%`;\n el.innerHTML = `<span class=\"bs-ann-pin-n\">${i + 1}</span><span class=\"bs-ann-pin-pulse\"></span>`;\n el.title = `#${i + 1}: ${pin.note}`;\n\n // Drag pin\n let pinDragging = false;\n el.addEventListener('mousedown', (e) => {\n e.stopPropagation();\n pinDragging = true;\n el.classList.add('bs-dragging');\n const onMove = (me: MouseEvent) => {\n if (!pinDragging) return;\n const r = viewport.getBoundingClientRect();\n pin.x = ((me.clientX - r.left) / r.width) * canvas.width;\n pin.y = ((me.clientY - r.top) / r.height) * canvas.height;\n el.style.left = `${((me.clientX - r.left) / r.width) * 100}%`;\n el.style.top = `${((me.clientY - r.top) / r.height) * 100}%`;\n };\n const onUp = () => {\n pinDragging = false;\n el.classList.remove('bs-dragging');\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n renderPins(); // refresh list coords\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n pinLayer.appendChild(el);\n\n // Pin list item\n const item = document.createElement('div');\n item.className = 'bs-ann-pin-item';\n item.innerHTML = `\n <div class=\"bs-ann-pin-num\" style=\"background:${pin.color}\">${i + 1}</div>\n <div class=\"bs-ann-pin-body\">\n <div class=\"bs-ann-pin-note\">${esc(pin.note)}</div>\n <div class=\"bs-ann-pin-loc\">${Math.round(pctX)}% × ${Math.round(pctY)}%</div>\n </div>`;\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'bs-ann-pin-del';\n del.innerHTML = '&times;';\n del.title = 'Remove pin';\n del.addEventListener('click', () => {\n pins.splice(i, 1);\n renderPins();\n });\n item.appendChild(del);\n pinList.appendChild(item);\n });\n };\n\n // ── Render engine ──\n let ctx: CanvasRenderingContext2D;\n const outlineColor = () => isDark ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.35)';\n\n const drawOutline = (fn: () => void, lw: number) => {\n // Draw shadow outline for contrast on any background\n ctx.save();\n ctx.strokeStyle = outlineColor();\n ctx.lineWidth = lw + 3;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n ctx.globalAlpha = 0.5;\n fn();\n ctx.restore();\n };\n\n const renderShape = (s: AnnObj, preview = false) => {\n if (s.type === 'draw' || s.type === 'highlight') {\n if (s.points.length < 2) return;\n const alpha = s.type === 'highlight' ? 0.25 : 1;\n const lw = s.type === 'highlight' ? s.size * 4 + 10 : s.size;\n const stroke = () => {\n ctx.beginPath();\n ctx.moveTo(s.points[0].x, s.points[0].y);\n for (let i = 1; i < s.points.length; i++) ctx.lineTo(s.points[i].x, s.points[i].y);\n ctx.stroke();\n };\n if (s.type !== 'highlight') drawOutline(stroke, lw);\n ctx.strokeStyle = s.color; ctx.lineWidth = lw;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n ctx.globalAlpha = alpha;\n stroke();\n ctx.globalAlpha = 1;\n } else if (s.type === 'rect') {\n const stroke = () => ctx.strokeRect(s.x, s.y, s.w, s.h);\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n } else if (s.type === 'circle') {\n const stroke = () => { ctx.beginPath(); ctx.ellipse(s.cx, s.cy, Math.abs(s.rx), Math.abs(s.ry), 0, 0, Math.PI * 2); ctx.stroke(); };\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n stroke();\n } else if (s.type === 'arrow') {\n const angle = Math.atan2(s.y2 - s.y1, s.x2 - s.x1);\n const headLen = 12 + s.size * 2;\n const stroke = () => {\n ctx.beginPath(); ctx.moveTo(s.x1, s.y1); ctx.lineTo(s.x2, s.y2); ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(s.x2, s.y2);\n ctx.lineTo(s.x2 - headLen * Math.cos(angle - 0.45), s.y2 - headLen * Math.sin(angle - 0.45));\n ctx.moveTo(s.x2, s.y2);\n ctx.lineTo(s.x2 - headLen * Math.cos(angle + 0.45), s.y2 - headLen * Math.sin(angle + 0.45));\n ctx.stroke();\n };\n drawOutline(stroke, s.size);\n ctx.strokeStyle = s.color; ctx.lineWidth = s.size;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n } else if (s.type === 'text') {\n const fontSize = s.size * 5 + 12;\n ctx.font = `bold ${fontSize}px Inter, -apple-system, sans-serif`;\n // text shadow for contrast\n ctx.fillStyle = outlineColor();\n ctx.globalAlpha = 0.6;\n ctx.fillText(s.text, s.x + 1, s.y + 1);\n ctx.globalAlpha = 1;\n ctx.fillStyle = s.color;\n ctx.fillText(s.text, s.x, s.y);\n }\n\n // Selection / hover highlight\n const isSelected = !preview && selectedIdx >= 0 && shapes[selectedIdx] === s;\n const isHovered = !preview && !isSelected && hoveredIdx >= 0 && shapes[hoveredIdx] === s;\n if (isSelected || isHovered) {\n const b = shapeBounds(s);\n ctx.save();\n ctx.setLineDash([6, 4]);\n ctx.strokeStyle = isDark ? '#fff' : '#000';\n ctx.lineWidth = isSelected ? 1.5 : 1;\n ctx.globalAlpha = isSelected ? 0.7 : 0.45;\n ctx.strokeRect(b.x - 4, b.y - 4, b.w + 8, b.h + 8);\n\n // Corner/cardinal handles for rects and circles\n if (s.type === 'rect' || s.type === 'circle') {\n const hSize = 5;\n ctx.setLineDash([]);\n ctx.globalAlpha = isSelected ? 0.9 : 0.6;\n const handles: [number, number][] = s.type === 'rect'\n ? [[b.x, b.y], [b.x + b.w, b.y], [b.x, b.y + b.h], [b.x + b.w, b.y + b.h]]\n : [[b.x + b.w / 2, b.y], [b.x + b.w, b.y + b.h / 2], [b.x + b.w / 2, b.y + b.h], [b.x, b.y + b.h / 2]];\n for (const [hx, hy] of handles) {\n ctx.fillStyle = '#fff';\n ctx.fillRect(hx - hSize, hy - hSize, hSize * 2, hSize * 2);\n ctx.strokeStyle = isDark ? '#aaa' : '#333';\n ctx.lineWidth = 1.2;\n ctx.strokeRect(hx - hSize, hy - hSize, hSize * 2, hSize * 2);\n }\n }\n ctx.restore();\n }\n };\n\n const render = () => {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0);\n for (const s of shapes) renderShape(s);\n };\n\n // ── Hit testing & bounds ──\n const shapeBounds = (s: AnnObj): { x: number; y: number; w: number; h: number } => {\n if (s.type === 'rect') return { x: Math.min(s.x, s.x + s.w), y: Math.min(s.y, s.y + s.h), w: Math.abs(s.w), h: Math.abs(s.h) };\n if (s.type === 'circle') return { x: s.cx - Math.abs(s.rx), y: s.cy - Math.abs(s.ry), w: Math.abs(s.rx) * 2, h: Math.abs(s.ry) * 2 };\n if (s.type === 'arrow') {\n const x = Math.min(s.x1, s.x2), y = Math.min(s.y1, s.y2);\n return { x, y, w: Math.abs(s.x2 - s.x1) || 20, h: Math.abs(s.y2 - s.y1) || 20 };\n }\n if (s.type === 'text') return { x: s.x, y: s.y - (s.size * 5 + 12), w: s.text.length * (s.size * 3 + 8), h: s.size * 5 + 16 };\n // draw / highlight: bounding box of points\n if (s.points.length === 0) return { x: 0, y: 0, w: 0, h: 0 };\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const p of s.points) { minX = Math.min(minX, p.x); minY = Math.min(minY, p.y); maxX = Math.max(maxX, p.x); maxY = Math.max(maxY, p.y); }\n return { x: minX, y: minY, w: maxX - minX || 10, h: maxY - minY || 10 };\n };\n\n const hitTest = (x: number, y: number): number => {\n for (let i = shapes.length - 1; i >= 0; i--) {\n const b = shapeBounds(shapes[i]);\n const pad = 8;\n if (x >= b.x - pad && x <= b.x + b.w + pad && y >= b.y - pad && y <= b.y + b.h + pad) return i;\n }\n return -1;\n };\n\n const moveShape = (s: AnnObj, dx: number, dy: number) => {\n if (s.type === 'draw' || s.type === 'highlight') { for (const p of s.points) { p.x += dx; p.y += dy; } }\n else if (s.type === 'rect') { s.x += dx; s.y += dy; }\n else if (s.type === 'circle') { s.cx += dx; s.cy += dy; }\n else if (s.type === 'arrow') { s.x1 += dx; s.y1 += dy; s.x2 += dx; s.y2 += dy; }\n else if (s.type === 'text') { s.x += dx; s.y += dy; }\n };\n\n img.onload = () => {\n const maxW = container.clientWidth || 450;\n const scale = maxW / img.width;\n canvas.width = img.width;\n canvas.height = img.height;\n canvas.style.height = `${img.height * scale}px`;\n ctx = canvas.getContext('2d')!;\n ctx.drawImage(img, 0, 0);\n\n // Detect brightness: sample corners + center\n const samplePoints = [[10, 10], [canvas.width - 10, 10], [10, canvas.height - 10], [canvas.width - 10, canvas.height - 10], [canvas.width / 2, canvas.height / 2]];\n let totalBrightness = 0;\n for (const [sx, sy] of samplePoints) {\n const px = ctx.getImageData(sx, sy, 1, 1).data;\n totalBrightness += (px[0] * 299 + px[1] * 587 + px[2] * 114) / 1000;\n }\n isDark = (totalBrightness / samplePoints.length) < 128;\n\n const coords = (e: MouseEvent) => {\n const r = canvas.getBoundingClientRect();\n return { x: (e.clientX - r.left) * (canvas.width / r.width), y: (e.clientY - r.top) * (canvas.height / r.height) };\n };\n\n let autoSelectDrag = false; // true when we auto-switched to drag on hover-hit\n\n canvas.addEventListener('mousedown', e => {\n const c = coords(e);\n\n // Select mode: pick or drag\n if (currentTool === 'select') {\n const hit = hitTest(c.x, c.y);\n if (hit >= 0) {\n selectedIdx = hit;\n dragging = true;\n const b = shapeBounds(shapes[hit]);\n dragOffX = c.x - b.x;\n dragOffY = c.y - b.y;\n canvas.classList.add('bs-grabbing');\n canvas.classList.remove('bs-grab');\n render();\n } else {\n selectedIdx = -1;\n render();\n }\n return;\n }\n\n // Auto-drag: if hovering a shape in any drawing tool, grab it instead\n if (currentTool !== 'pin' && currentTool !== 'text') {\n const hit = hitTest(c.x, c.y);\n if (hit >= 0) {\n selectedIdx = hit;\n dragging = true;\n autoSelectDrag = true;\n const b = shapeBounds(shapes[hit]);\n dragOffX = c.x - b.x;\n dragOffY = c.y - b.y;\n canvas.classList.add('bs-grabbing');\n render();\n return;\n }\n }\n\n drawing = true;\n startX = c.x; startY = c.y;\n\n if (currentTool === 'pin') {\n drawing = false;\n const note = prompt('Describe the issue at this spot:');\n if (note) {\n const color = PIN_COLORS[pins.length % PIN_COLORS.length];\n pins.push({ x: c.x, y: c.y, note, color });\n renderPins();\n }\n return;\n }\n\n if (currentTool === 'text') {\n drawing = false;\n const input = prompt('Enter text:');\n if (input) {\n shapes.push({ type: 'text', color: currentColor, size: brushSize, x: c.x, y: c.y, text: input });\n render();\n }\n return;\n }\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n currentDraw = [{ x: c.x, y: c.y }];\n }\n });\n\n canvas.addEventListener('mousemove', e => {\n const c = coords(e);\n\n // Active drag (select mode or auto-drag from any tool)\n if (dragging && selectedIdx >= 0) {\n const b = shapeBounds(shapes[selectedIdx]);\n const dx = c.x - dragOffX - b.x;\n const dy = c.y - dragOffY - b.y;\n moveShape(shapes[selectedIdx], dx, dy);\n render();\n return;\n }\n\n // Select mode hover\n if (currentTool === 'select') {\n const hit = hitTest(c.x, c.y);\n canvas.classList.toggle('bs-grab', hit >= 0);\n if (hoveredIdx !== hit) { hoveredIdx = hit; render(); }\n return;\n }\n\n // Any tool: show grab cursor when hovering a shape\n if (currentTool !== 'pin' && currentTool !== 'text' && !drawing) {\n const hit = hitTest(c.x, c.y);\n canvas.classList.toggle('bs-grab', hit >= 0);\n if (hoveredIdx !== hit) { hoveredIdx = hit; render(); }\n }\n\n if (!drawing) return;\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n currentDraw.push({ x: c.x, y: c.y });\n // Live preview\n render();\n const alpha = currentTool === 'highlight' ? 0.25 : 1;\n const lw = currentTool === 'highlight' ? brushSize * 4 + 10 : brushSize;\n if (currentTool !== 'highlight') {\n ctx.save();\n ctx.strokeStyle = outlineColor(); ctx.lineWidth = lw + 3;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.globalAlpha = 0.5;\n ctx.beginPath(); ctx.moveTo(currentDraw[0].x, currentDraw[0].y);\n for (let i = 1; i < currentDraw.length; i++) ctx.lineTo(currentDraw[i].x, currentDraw[i].y);\n ctx.stroke(); ctx.restore();\n }\n ctx.strokeStyle = currentColor; ctx.lineWidth = lw;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round'; ctx.globalAlpha = alpha;\n ctx.beginPath(); ctx.moveTo(currentDraw[0].x, currentDraw[0].y);\n for (let i = 1; i < currentDraw.length; i++) ctx.lineTo(currentDraw[i].x, currentDraw[i].y);\n ctx.stroke(); ctx.globalAlpha = 1;\n } else {\n // Shape preview\n render();\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n if (currentTool === 'rect') {\n drawOutline(() => ctx.strokeRect(startX, startY, c.x - startX, c.y - startY), brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.strokeRect(startX, startY, c.x - startX, c.y - startY);\n } else if (currentTool === 'circle') {\n const rx = Math.abs(c.x - startX) / 2, ry = Math.abs(c.y - startY) / 2;\n const cx2 = startX + (c.x - startX) / 2, cy2 = startY + (c.y - startY) / 2;\n drawOutline(() => { ctx.beginPath(); ctx.ellipse(cx2, cy2, rx, ry, 0, 0, Math.PI * 2); ctx.stroke(); }, brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.beginPath(); ctx.ellipse(cx2, cy2, rx, ry, 0, 0, Math.PI * 2); ctx.stroke();\n } else if (currentTool === 'arrow') {\n const angle = Math.atan2(c.y - startY, c.x - startX);\n const headLen = 12 + brushSize * 2;\n const stroke = () => {\n ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(c.x, c.y); ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(c.x, c.y);\n ctx.lineTo(c.x - headLen * Math.cos(angle - 0.45), c.y - headLen * Math.sin(angle - 0.45));\n ctx.moveTo(c.x, c.y);\n ctx.lineTo(c.x - headLen * Math.cos(angle + 0.45), c.y - headLen * Math.sin(angle + 0.45));\n ctx.stroke();\n };\n drawOutline(stroke, brushSize);\n ctx.strokeStyle = currentColor; ctx.lineWidth = brushSize;\n ctx.lineCap = 'round'; ctx.lineJoin = 'round';\n stroke();\n }\n }\n });\n\n const endDraw = (e: MouseEvent) => {\n // Release auto-drag or select-mode drag\n if (dragging) {\n dragging = false;\n autoSelectDrag = false;\n selectedIdx = -1;\n canvas.classList.remove('bs-grabbing');\n canvas.classList.remove('bs-grab');\n render();\n if (currentTool === 'select') return;\n // For auto-drag from other tools, just stop — don't create a shape\n return;\n }\n if (!drawing) return;\n drawing = false;\n const c = coords(e);\n\n if (currentTool === 'draw' || currentTool === 'highlight') {\n if (currentDraw.length > 1) {\n shapes.push({ type: currentTool, color: currentColor, size: brushSize, alpha: currentTool === 'highlight' ? 0.25 : 1, points: [...currentDraw] });\n }\n currentDraw = [];\n } else if (currentTool === 'rect') {\n shapes.push({ type: 'rect', color: currentColor, size: brushSize, x: startX, y: startY, w: c.x - startX, h: c.y - startY });\n } else if (currentTool === 'circle') {\n const rx = Math.abs(c.x - startX) / 2, ry = Math.abs(c.y - startY) / 2;\n shapes.push({ type: 'circle', color: currentColor, size: brushSize, cx: startX + (c.x - startX) / 2, cy: startY + (c.y - startY) / 2, rx, ry });\n } else if (currentTool === 'arrow') {\n shapes.push({ type: 'arrow', color: currentColor, size: brushSize, x1: startX, y1: startY, x2: c.x, y2: c.y });\n }\n render();\n };\n\n canvas.addEventListener('mouseup', endDraw);\n canvas.addEventListener('mouseleave', (e) => {\n if (dragging) { dragging = false; autoSelectDrag = false; canvas.classList.remove('bs-grabbing'); canvas.classList.remove('bs-grab'); render(); }\n else if (drawing) endDraw(e);\n });\n\n // Delete selected with Backspace/Delete\n const keyHandler = (e: KeyboardEvent) => {\n if (selectedIdx >= 0 && (e.key === 'Delete' || e.key === 'Backspace')) {\n shapes.splice(selectedIdx, 1);\n selectedIdx = -1;\n render();\n }\n };\n document.addEventListener('keydown', keyHandler);\n\n undoBtn.addEventListener('click', () => {\n if (shapes.length) {\n shapes.pop();\n selectedIdx = -1;\n render();\n }\n });\n\n clearBtn.addEventListener('click', () => {\n shapes.length = 0;\n pins.length = 0;\n selectedIdx = -1;\n render();\n renderPins();\n });\n };\n\n // Draw pins onto canvas for final export\n const bakePins = () => {\n for (let i = 0; i < pins.length; i++) {\n const p = pins[i];\n const r = 16;\n // Pin circle\n ctx.beginPath();\n ctx.arc(p.x, p.y - r, r, 0, Math.PI * 2);\n ctx.fillStyle = p.color;\n ctx.fill();\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.stroke();\n // Pin tail\n ctx.beginPath();\n ctx.moveTo(p.x - 8, p.y - 6);\n ctx.lineTo(p.x, p.y + 4);\n ctx.lineTo(p.x + 8, p.y - 6);\n ctx.fillStyle = p.color;\n ctx.fill();\n // Number\n ctx.fillStyle = '#fff';\n ctx.font = 'bold 14px Inter, sans-serif';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(`${i + 1}`, p.x, p.y - r);\n ctx.textAlign = 'start';\n ctx.textBaseline = 'alphabetic';\n }\n };\n\n return {\n getAnnotation: () => {\n try {\n selectedIdx = -1;\n render();\n bakePins();\n return canvas.toDataURL('image/jpeg', 0.7);\n } catch { return null; }\n },\n getPins: () => pins.map((p, i) => ({ number: i + 1, x: Math.round(p.x), y: Math.round(p.y), note: p.note })),\n };\n}\n\n// ─── Switch Tab ──────────────────────────────────────────\n\nfunction switchTab(tab: typeof activeTab) {\n if (!modal) return;\n activeTab = tab;\n\n // Update tab buttons\n modal.querySelectorAll('.bs-tab').forEach(el => {\n el.classList.toggle('bs-active', (el as HTMLElement).dataset.tab === tab);\n });\n\n // Render content\n const scroll = modal.querySelector('.bs-scroll')!;\n const renderers: Record<typeof activeTab, () => string> = {\n report: tabReport,\n console: tabConsole,\n network: tabNetwork,\n context: tabContext,\n history: tabHistory,\n settings: tabSettings,\n };\n scroll.innerHTML = renderers[tab]();\n scroll.scrollTop = 0;\n bindTabContent();\n}\n\nfunction bindTabContent() {\n if (!modal) return;\n\n if (activeTab === 'history') {\n // Delete buttons\n modal.querySelectorAll('[data-hist-del]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = parseInt((btn as HTMLElement).dataset.histDel!);\n const card = modal!.querySelector(`[data-hist-id=\"${id}\"]`);\n if (!card) return;\n // Show confirm inline\n const existing = card.querySelector('.bs-hist-confirm');\n if (existing) { existing.remove(); return; }\n const confirm = document.createElement('div');\n confirm.className = 'bs-hist-confirm';\n confirm.innerHTML = `<span>Delete this report?</span>`;\n const yes = document.createElement('button');\n yes.type = 'button'; yes.className = 'bs-hist-confirm-yes'; yes.textContent = 'Delete';\n const no = document.createElement('button');\n no.type = 'button'; no.className = 'bs-hist-confirm-no'; no.textContent = 'Cancel';\n yes.addEventListener('click', () => {\n deleteFromHistory(id);\n switchTab('history');\n });\n no.addEventListener('click', () => confirm.remove());\n confirm.appendChild(yes);\n confirm.appendChild(no);\n card.appendChild(confirm);\n });\n });\n\n // Edit buttons\n modal.querySelectorAll('[data-hist-edit]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = parseInt((btn as HTMLElement).dataset.histEdit!);\n const card = modal!.querySelector(`[data-hist-id=\"${id}\"]`);\n if (!card) return;\n const existing = card.querySelector('.bs-hist-edit-wrap');\n if (existing) { existing.remove(); return; }\n // Remove any confirm dialogs\n card.querySelector('.bs-hist-confirm')?.remove();\n\n const entry = getReportHistory().find(e => e.id === id);\n if (!entry) return;\n\n const wrap = document.createElement('div');\n wrap.className = 'bs-hist-edit-wrap';\n wrap.innerHTML = `\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <input class=\"bs-input\" data-edit-title value=\"${esc(entry.title)}\" />\n </div>\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <textarea class=\"bs-textarea\" data-edit-desc style=\"min-height:56px\">${esc(entry.description)}</textarea>\n </div>\n <div class=\"bs-field\" style=\"margin-bottom:8px\">\n <div class=\"bs-sev-row\">\n <button type=\"button\" class=\"bs-sev-btn bs-sev-low${entry.severity === 'low' ? ' bs-picked' : ''}\" data-edit-sev=\"low\">Low</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-medium${entry.severity === 'medium' ? ' bs-picked' : ''}\" data-edit-sev=\"medium\">Medium</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-high${entry.severity === 'high' ? ' bs-picked' : ''}\" data-edit-sev=\"high\">High</button>\n <button type=\"button\" class=\"bs-sev-btn bs-sev-critical${entry.severity === 'critical' ? ' bs-picked' : ''}\" data-edit-sev=\"critical\">Critical</button>\n </div>\n </div>\n <div class=\"bs-hist-edit-row\"></div>`;\n\n let editSev = entry.severity;\n card.appendChild(wrap);\n\n // Severity picker in edit\n wrap.querySelectorAll('[data-edit-sev]').forEach(sb => {\n sb.addEventListener('click', () => {\n editSev = (sb as HTMLElement).dataset.editSev!;\n wrap.querySelectorAll('.bs-sev-btn').forEach(b => b.classList.remove('bs-picked'));\n sb.classList.add('bs-picked');\n });\n });\n\n const row = wrap.querySelector('.bs-hist-edit-row')!;\n const save = document.createElement('button');\n save.type = 'button'; save.className = 'bs-hist-save'; save.textContent = 'Save';\n const cancel = document.createElement('button');\n cancel.type = 'button'; cancel.className = 'bs-hist-cancel'; cancel.textContent = 'Cancel';\n\n save.addEventListener('click', () => {\n const newTitle = (wrap.querySelector('[data-edit-title]') as HTMLInputElement).value.trim();\n const newDesc = (wrap.querySelector('[data-edit-desc]') as HTMLTextAreaElement).value.trim();\n if (!newTitle) return;\n updateInHistory(id, { title: newTitle, description: newDesc, severity: editSev });\n switchTab('history');\n });\n cancel.addEventListener('click', () => wrap.remove());\n row.appendChild(save);\n row.appendChild(cancel);\n });\n });\n return;\n }\n\n if (activeTab === 'settings') {\n // Theme picker\n modal.querySelectorAll('[data-set-theme]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = (btn as HTMLElement).dataset.setTheme!;\n setTheme(id);\n // Update picked state\n modal!.querySelectorAll('[data-set-theme]').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n // Layout picker\n modal.querySelectorAll('[data-set-layout]').forEach(btn => {\n btn.addEventListener('click', () => {\n const id = (btn as HTMLElement).dataset.setLayout!;\n const layout = getLayoutById(id);\n if (!layout) return;\n currentLayout = layout;\n // Close and reopen with new layout\n close();\n setTimeout(() => {\n activeTab = 'settings';\n open();\n // After open, switch to settings tab\n setTimeout(() => switchTab('settings'), 50);\n }, 400);\n });\n });\n return;\n }\n\n if (activeTab !== 'report') return;\n\n // Category\n modal.querySelectorAll('.bs-cat-btn').forEach(btn => {\n btn.addEventListener('click', () => {\n const cat = (btn as HTMLElement).dataset.cat!;\n (modal!.querySelector('input[name=\"category\"]') as HTMLInputElement).value = cat;\n modal!.querySelectorAll('.bs-cat-btn').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n\n // Severity\n modal.querySelectorAll('.bs-sev-btn').forEach(btn => {\n btn.addEventListener('click', () => {\n const sev = (btn as HTMLElement).dataset.sev!;\n (modal!.querySelector('input[name=\"severity\"]') as HTMLInputElement).value = sev;\n modal!.querySelectorAll('.bs-sev-btn').forEach(b => b.classList.remove('bs-picked'));\n btn.classList.add('bs-picked');\n });\n });\n\n // Screenshot\n let screenshotData: string | null = null;\n let annotator: { getAnnotation: () => string | null; getPins: () => { number: number; x: number; y: number; note: string }[] } | null = null;\n\n modal.querySelector('[data-bs-screenshot]')?.addEventListener('click', async () => {\n const titleEl = modal?.querySelector('[data-bs-shot-title]');\n const subEl = modal?.querySelector('[data-bs-shot-sub]');\n const area = modal?.querySelector('[data-bs-screenshot]');\n if (titleEl) titleEl.textContent = 'Capturing...';\n\n if (modal) modal.style.visibility = 'hidden';\n if (backdrop) backdrop.style.visibility = 'hidden';\n await new Promise(r => setTimeout(r, 200));\n screenshotData = await captureScreenshot();\n if (modal) modal.style.visibility = '';\n if (backdrop) backdrop.style.visibility = '';\n\n if (screenshotData) {\n if (titleEl) titleEl.textContent = 'Screenshot captured!';\n if (subEl) subEl.textContent = 'Draw on the image below to highlight the issue';\n area?.classList.add('bs-captured');\n const container = modal?.querySelector('[data-bs-annotate]') as HTMLElement;\n if (container) annotator = setupAnnotation(container, screenshotData);\n } else {\n if (titleEl) titleEl.textContent = 'Screenshot unavailable';\n if (subEl) subEl.textContent = 'Could not capture screenshot on this page';\n }\n });\n\n // Submit\n modal.querySelector('[data-bs-form]')?.addEventListener('submit', async (e) => {\n e.preventDefault();\n const form = e.target as HTMLFormElement;\n const btn = form.querySelector('.bs-submit-btn') as HTMLButtonElement;\n\n const title = (form.elements.namedItem('title') as HTMLInputElement).value.trim();\n const description = (form.elements.namedItem('description') as HTMLTextAreaElement).value.trim();\n const severity = (form.elements.namedItem('severity') as HTMLInputElement).value as BugReport['severity'];\n const category = (form.elements.namedItem('category') as HTMLInputElement).value as BugReport['category'];\n\n if (!title) return;\n\n btn.disabled = true;\n btn.textContent = 'Sending...';\n\n const detected = autoDetect();\n\n const report: BugReport = {\n projectId: config.projectId,\n title,\n description,\n category,\n severity,\n tags: detected.tags.length ? detected.tags : undefined,\n context: buildContext(),\n consoleLogs: getLogs(),\n errors: getErrors(),\n networkCaptures: getFailedNetworkCaptures(),\n breadcrumbs: getBreadcrumbs(),\n performance: getPerformanceMetrics() ?? undefined,\n screenshot: screenshotData ?? undefined,\n annotation: annotator?.getAnnotation() ?? undefined,\n pins: annotator?.getPins().length ? annotator.getPins() : undefined,\n createdAt: Date.now(),\n };\n\n const result = await submitReport(report);\n\n // Save to history\n addToHistory({\n title: report.title,\n description: report.description,\n category: report.category,\n severity: report.severity,\n tags: report.tags,\n screenshot: report.screenshot,\n pins: report.pins,\n url: window.location.href,\n createdAt: report.createdAt,\n status: result.success ? 'sent' : 'draft',\n });\n\n if (result.success) {\n btn.innerHTML = `${I.check} Bug reported!`;\n btn.classList.add('bs-submit-ok');\n setTimeout(close, 1200);\n } else {\n btn.textContent = result.error ?? 'Failed — saved as draft';\n btn.classList.add('bs-submit-err');\n setTimeout(() => {\n btn.disabled = false;\n btn.textContent = 'Submit Report';\n btn.classList.remove('bs-submit-err');\n }, 2500);\n }\n });\n}\n\n// ─── Open / Close ────────────────────────────────────────\n\nfunction open() {\n if (isOpen) return;\n isOpen = true;\n activeTab = 'report';\n hideToolbar();\n\n backdrop = document.createElement('div');\n backdrop.className = 'bs-backdrop';\n document.body.appendChild(backdrop);\n\n const fails = getFailedNetworkCaptures().length;\n const errs = getErrors().length;\n\n modal = document.createElement('div');\n modal.className = `bs-modal bs-ly-${currentLayout.id}`;\n applyThemeVars(modal);\n\n const tabsHtml = `\n <div class=\"bs-tabs\">\n <button class=\"bs-tab bs-active\" data-tab=\"report\">${I.report} Report</button>\n <button class=\"bs-tab\" data-tab=\"console\">${I.console} Console <span class=\"bs-tab-badge\">${getLogs().length}</span></button>\n <button class=\"bs-tab\" data-tab=\"network\">${I.network} Network ${fails ? `<span class=\"bs-tab-badge bs-warn\">${fails}</span>` : `<span class=\"bs-tab-badge\">${getNetworkCaptures().length}</span>`}</button>\n <button class=\"bs-tab\" data-tab=\"context\">${I.ctx} Context ${errs ? `<span class=\"bs-tab-badge bs-warn\">${errs}</span>` : ''}</button>\n <button class=\"bs-tab\" data-tab=\"history\">${I.history} History <span class=\"bs-tab-badge\">${getReportHistory().length}</span></button>\n <button class=\"bs-tab\" data-tab=\"settings\" style=\"margin-left:auto\">${I.settings}</button>\n </div>`;\n\n const user = getCurrentUser();\n const initials = user ? user.name.split(' ').map(w => w[0]).join('').toUpperCase().slice(0, 2) : '';\n const pinActive = isPinModeActive();\n\n const headerHtml = user ? `\n <div class=\"bs-hdr\">\n <div class=\"bs-logo\">BugStash</div>\n <div class=\"bs-hdr-right\">\n <button class=\"bs-pin-toggle${pinActive ? ' active' : ''}\" data-bs-pin-toggle title=\"Toggle pin mode\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${pinActive ? 'ON' : 'OFF'}\n </button>\n <div class=\"bs-user-badge\">\n <div class=\"bs-user-avatar\">${initials}</div>\n <span>${user.name.split(' ')[0]}</span>\n </div>\n <button class=\"bs-login-logout\" data-bs-logout title=\"Sign out\">Logout</button>\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>\n </div>` : `\n <div class=\"bs-hdr\" style=\"justify-content:flex-end\">\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>`;\n\n const useSidebar = currentLayout.tabPosition === 'left';\n const useBottomTabs = currentLayout.tabPosition === 'bottom';\n\n // If not logged in, show login form instead of tabs\n const contentHtml = user ? tabReport() : tabLogin();\n\n if (useSidebar) {\n modal.innerHTML = `\n ${headerHtml}\n <div class=\"bs-body-wrap\">\n ${user ? tabsHtml : ''}\n <div class=\"bs-scroll\">${contentHtml}</div>\n </div>`;\n } else if (useBottomTabs) {\n modal.innerHTML = `\n ${headerHtml}\n <div class=\"bs-scroll\">${contentHtml}</div>\n ${user ? `<div class=\"bs-tab-divider\"></div>${tabsHtml}` : ''}`;\n } else {\n modal.innerHTML = `\n ${headerHtml}\n ${user ? `${tabsHtml}<div class=\"bs-tab-divider\"></div>` : ''}\n <div class=\"bs-scroll\">${contentHtml}</div>`;\n }\n document.body.appendChild(modal);\n\n if (fab) fab.classList.add('bs-open');\n\n requestAnimationFrame(() => {\n backdrop?.classList.add('bs-in');\n modal?.classList.add('bs-in');\n });\n\n // Tab switching\n modal.querySelectorAll('.bs-tab').forEach(tab => {\n tab.addEventListener('click', () => switchTab((tab as HTMLElement).dataset.tab as typeof activeTab));\n });\n\n modal.querySelector('[data-bs-close]')?.addEventListener('click', close);\n backdrop.addEventListener('click', close);\n\n // Pin toggle\n modal.querySelector('[data-bs-pin-toggle]')?.addEventListener('click', () => {\n const active = togglePinMode();\n const btn = modal?.querySelector('[data-bs-pin-toggle]');\n if (btn) {\n btn.classList.toggle('active', active);\n btn.innerHTML = `\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${active ? 'ON' : 'OFF'}\n `;\n }\n });\n\n // Logout\n modal.querySelector('[data-bs-logout]')?.addEventListener('click', () => {\n apiLogout();\n close();\n // Reopen to show login form\n setTimeout(() => open(), 300);\n });\n\n // Login form binding\n if (!user) {\n bindLoginForm();\n } else {\n bindTabContent();\n }\n\n const escHandler = (e: KeyboardEvent) => { if (e.key === 'Escape') { close(); document.removeEventListener('keydown', escHandler); } };\n document.addEventListener('keydown', escHandler);\n}\n\nfunction bindLoginForm() {\n if (!modal) return;\n\n const submitBtn = modal.querySelector('#bs-login-submit');\n const emailInput = modal.querySelector('#bs-login-email') as HTMLInputElement;\n const passInput = modal.querySelector('#bs-login-pass') as HTMLInputElement;\n const errorEl = modal.querySelector('#bs-login-error') as HTMLElement;\n\n if (!submitBtn || !emailInput || !passInput) return;\n\n const doLogin = async () => {\n const email = emailInput.value.trim();\n const password = passInput.value;\n\n if (!email || !password) {\n errorEl.textContent = 'Please enter email and password';\n errorEl.style.display = 'block';\n return;\n }\n\n submitBtn.setAttribute('disabled', 'true');\n (submitBtn as HTMLButtonElement).textContent = 'Signing in...';\n errorEl.style.display = 'none';\n\n const result = await apiLogin(email, password, config.projectId);\n\n if (result.success) {\n // Initialize live pins + realtime now that user is logged in\n initLivePins(config.projectId);\n connectRealtime(config.projectId);\n // Reopen panel with full UI\n close();\n setTimeout(() => open(), 300);\n } else {\n errorEl.textContent = result.error || 'Invalid credentials';\n errorEl.style.display = 'block';\n submitBtn.removeAttribute('disabled');\n (submitBtn as HTMLButtonElement).textContent = 'Sign In';\n }\n };\n\n submitBtn.addEventListener('click', doLogin);\n passInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') doLogin(); });\n emailInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') passInput.focus(); });\n\n // Auto-focus email\n setTimeout(() => emailInput.focus(), 100);\n}\n\nfunction close() {\n if (!isOpen) return;\n if (fab) fab.classList.remove('bs-open');\n if (modal) {\n modal.classList.remove('bs-in');\n modal.classList.add('bs-out');\n }\n if (backdrop) backdrop.classList.remove('bs-in');\n\n setTimeout(() => {\n modal?.remove();\n backdrop?.remove();\n modal = null;\n backdrop = null;\n isOpen = false;\n }, 350);\n}\n\n// ─── Theme ───────────────────────────────────────────────\n\nfunction applyThemeVars(el: HTMLElement) {\n for (const [key, val] of Object.entries(currentTheme.vars)) {\n el.style.setProperty(key, val);\n }\n}\n\nexport function setTheme(themeId: string) {\n const theme = getThemeById(themeId);\n if (!theme) return;\n currentTheme = theme;\n if (modal) applyThemeVars(modal);\n if (fab) applyThemeVars(fab);\n if (toolbar) applyThemeVars(toolbar);\n}\n\nexport function getCurrentThemeId(): string {\n return currentTheme.id;\n}\n\n// ─── Layout ──────────────────────────────────────────────\n\nexport function setLayout(layoutId: string) {\n const layout = getLayoutById(layoutId);\n if (!layout) return;\n currentLayout = layout;\n // If modal is open, close and reopen with new layout\n if (isOpen) {\n close();\n setTimeout(open, 400);\n }\n}\n\nexport function getCurrentLayoutId(): string {\n return currentLayout.id;\n}\n\n// ─── Init / Destroy ──────────────────────────────────────\n\nexport function initPanel(cfg: BugStashConfig) {\n config = cfg;\n\n styleEl = document.createElement('style');\n styleEl.textContent = STYLES + LAYOUT_CSS;\n document.head.appendChild(styleEl);\n\n const side = cfg.panelPosition === 'bottom-left' ? 'left' : 'right';\n\n fab = document.createElement('button');\n fab.className = 'bs-fab';\n applyThemeVars(fab);\n fab.innerHTML = `${I.bug}<span class=\"bs-fab-label\">Report a bug</span>`;\n fab.style[side] = '24px';\n fab.addEventListener('click', () => (isOpen ? close() : open()));\n document.body.appendChild(fab);\n\n // ── Quick Action Toolbar ──\n toolbar = document.createElement('div');\n toolbar.className = 'bs-toolbar';\n toolbar.style[side] = '32px';\n applyThemeVars(toolbar);\n\n const isMac = navigator.platform.toUpperCase().includes('MAC');\n const mod = isMac ? '⌘' : 'Ctrl';\n\n const tbButtons: { icon: string; tip: string; kbd: string; action: () => void; id?: string }[] = [\n {\n icon: I.cam,\n tip: 'Screenshot',\n kbd: `${mod}+Shift+S`,\n action: async () => {\n const shot = await captureScreenshot();\n if (shot) {\n // Open panel to report tab with screenshot pre-attached\n if (!isOpen) open();\n setTimeout(() => {\n const area = modal?.querySelector('[data-bs-screenshot]') as HTMLElement;\n if (area) {\n (area as any).__screenshot = shot;\n area.classList.add('bs-captured');\n const title = area.querySelector('[data-bs-shot-title]');\n const sub = area.querySelector('[data-bs-shot-sub]');\n if (title) title.textContent = 'Screenshot captured!';\n if (sub) sub.textContent = 'Click to retake or annotate';\n // Trigger annotation setup\n area.click();\n }\n }, 400);\n }\n },\n },\n {\n icon: I.pin,\n tip: 'Toggle Pins',\n kbd: `${mod}+Shift+P`,\n id: 'bs-tb-pin',\n action: () => {\n const user = getCurrentUser();\n if (!user) {\n // Not logged in — open panel to show login\n if (!isOpen) open();\n return;\n }\n // Ensure live pins are initialized\n if (!document.getElementById('bugstash-live-pins')) {\n initLivePins(config.projectId);\n connectRealtime(config.projectId);\n }\n const active = togglePinMode();\n const btn = toolbar?.querySelector('#bs-tb-pin');\n if (btn) btn.classList.toggle('bs-active', active);\n // Also update modal pin toggle if open\n const modalBtn = modal?.querySelector('[data-bs-pin-toggle]');\n if (modalBtn) {\n modalBtn.classList.toggle('active', active);\n modalBtn.innerHTML = `\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/></svg>\n Pins ${active ? 'ON' : 'OFF'}\n `;\n }\n },\n },\n {\n icon: currentTheme.id === 'black' ? I.sun : I.moon,\n tip: 'Toggle Theme',\n kbd: `${mod}+Shift+T`,\n id: 'bs-tb-theme',\n action: () => {\n const newId = currentTheme.id === 'black' ? 'white' : 'black';\n setTheme(newId);\n if (toolbar) applyThemeVars(toolbar);\n const btn = toolbar?.querySelector('#bs-tb-theme');\n if (btn) btn.innerHTML = `${currentTheme.id === 'black' ? I.sun : I.moon}<span class=\"bs-toolbar-tip\">${currentTheme.id === 'black' ? 'Light' : 'Dark'} Mode<span class=\"bs-toolbar-kbd\">${mod}+Shift+T</span></span>`;\n },\n },\n {\n icon: I.report,\n tip: 'Open Panel',\n kbd: `${mod}+Shift+B`,\n action: () => { isOpen ? close() : open(); },\n },\n ];\n\n for (const tb of tbButtons) {\n const btn = document.createElement('button');\n btn.className = 'bs-toolbar-btn';\n if (tb.id) btn.id = tb.id;\n btn.innerHTML = `${tb.icon}<span class=\"bs-toolbar-tip\">${tb.tip}<span class=\"bs-toolbar-kbd\">${tb.kbd}</span></span>`;\n btn.addEventListener('click', (e) => { e.stopPropagation(); tb.action(); });\n toolbar.appendChild(btn);\n }\n\n document.body.appendChild(toolbar);\n\n // Show toolbar on FAB hover or always show after first interaction\n fab.addEventListener('mouseenter', () => { if (!isOpen) showToolbar(); });\n fab.addEventListener('mouseleave', (e) => {\n const related = e.relatedTarget as HTMLElement;\n if (!toolbar?.contains(related)) hideToolbar();\n });\n toolbar.addEventListener('mouseenter', () => showToolbar());\n toolbar.addEventListener('mouseleave', (e) => {\n const related = e.relatedTarget as HTMLElement;\n if (!fab?.contains(related)) hideToolbar();\n });\n\n // ── Keyboard Shortcuts ──\n keyHandler = (e: KeyboardEvent) => {\n const hasModShift = (e.ctrlKey || e.metaKey) && e.shiftKey;\n if (!hasModShift) return;\n\n if (e.key === 'B' || e.key === 'b') {\n e.preventDefault();\n isOpen ? close() : open();\n } else if (e.key === 'S' || e.key === 's') {\n e.preventDefault();\n tbButtons[0].action(); // Screenshot\n } else if (e.key === 'P' || e.key === 'p') {\n e.preventDefault();\n tbButtons[1].action(); // Pin toggle\n } else if (e.key === 'T' || e.key === 't') {\n e.preventDefault();\n tbButtons[2].action(); // Theme toggle\n }\n };\n document.addEventListener('keydown', keyHandler);\n}\n\nfunction showToolbar() {\n if (toolbarVisible || isOpen) return;\n toolbarVisible = true;\n toolbar?.classList.add('bs-show');\n}\n\nfunction hideToolbar() {\n toolbarVisible = false;\n toolbar?.classList.remove('bs-show');\n}\n\nexport function destroyPanel() {\n close();\n fab?.remove();\n fab = null;\n toolbar?.remove();\n toolbar = null;\n toolbarVisible = false;\n styleEl?.remove();\n styleEl = null;\n if (keyHandler) document.removeEventListener('keydown', keyHandler);\n keyHandler = null;\n}\n","/**\n * Annotation drawing tool for screenshots.\n * Provides a canvas overlay for drawing arrows, rectangles, circles, and freehand on screenshots.\n */\n\nimport type { AnnotationShape } from '@bugstash/shared';\n\nexport { AnnotationShape };\n\nexport interface AnnotationResult {\n dataUrl: string; // The annotated screenshot as a data URL\n annotations: AnnotationShape[];\n}\n\nlet overlay: HTMLDivElement | null = null;\nlet canvas: HTMLCanvasElement | null = null;\nlet ctx: CanvasRenderingContext2D | null = null;\nlet screenshotImg: HTMLImageElement | null = null;\nlet currentTool: AnnotationShape['type'] = 'freehand';\nlet currentColor = '#ef4444';\nlet lineWidth = 3;\nlet shapes: AnnotationShape[] = [];\nlet currentShape: AnnotationShape | null = null;\nlet isDrawing = false;\nlet resolvePromise: ((result: AnnotationResult | null) => void) | null = null;\n\nconst TOOLS: { id: AnnotationShape['type']; label: string; icon: string }[] = [\n { id: 'freehand', label: 'Draw', icon: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z' },\n { id: 'rectangle', label: 'Rect', icon: 'M3 3h18v18H3V3zm2 2v14h14V5H5z' },\n { id: 'circle', label: 'Circle', icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z' },\n { id: 'arrow', label: 'Arrow', icon: 'M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z' },\n];\n\nconst COLORS = ['#ef4444', '#f97316', '#eab308', '#22c55e', '#3b82f6', '#8b5cf6', '#ffffff', '#000000'];\n\n/**\n * Opens the annotation editor overlay on a screenshot.\n * Returns a promise that resolves when the user saves or cancels.\n */\nexport function openAnnotationEditor(screenshotDataUrl: string): Promise<AnnotationResult | null> {\n return new Promise((resolve) => {\n resolvePromise = resolve;\n shapes = [];\n currentShape = null;\n currentTool = 'freehand';\n currentColor = '#ef4444';\n\n createOverlay(screenshotDataUrl);\n });\n}\n\nfunction createOverlay(screenshotDataUrl: string) {\n if (overlay) overlay.remove();\n\n overlay = document.createElement('div');\n overlay.id = 'bs-annotation-overlay';\n\n const style = document.createElement('style');\n style.textContent = `\n #bs-annotation-overlay {\n position: fixed; inset: 0; z-index: 2147483647;\n background: rgba(0,0,0,0.85);\n display: flex; flex-direction: column;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n .bs-ann-toolbar {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 16px; background: #1a1d2e;\n border-bottom: 1px solid #333;\n }\n .bs-ann-tool {\n width: 36px; height: 36px; border-radius: 8px;\n border: 2px solid transparent; background: #222639;\n cursor: pointer; display: flex; align-items: center; justify-content: center;\n transition: all 0.15s;\n }\n .bs-ann-tool:hover { border-color: #555; }\n .bs-ann-tool.active { border-color: #6E9ED0; background: #2a3550; }\n .bs-ann-tool svg { width: 18px; height: 18px; fill: #ccc; }\n .bs-ann-color {\n width: 24px; height: 24px; border-radius: 50%;\n border: 2px solid transparent; cursor: pointer;\n transition: transform 0.15s;\n }\n .bs-ann-color:hover { transform: scale(1.15); }\n .bs-ann-color.active { border-color: #fff; }\n .bs-ann-sep { width: 1px; height: 28px; background: #444; margin: 0 6px; }\n .bs-ann-btn {\n padding: 8px 18px; border-radius: 8px; border: none;\n font-size: 13px; font-weight: 600; cursor: pointer;\n margin-left: auto;\n }\n .bs-ann-cancel { background: #333; color: #aaa; margin-left: 8px; }\n .bs-ann-cancel:hover { background: #444; color: #fff; }\n .bs-ann-save { background: linear-gradient(135deg, #6E9ED0, #8FAFD6); color: #fff; }\n .bs-ann-save:hover { opacity: 0.9; }\n .bs-ann-undo { background: #333; color: #aaa; font-size: 12px; padding: 6px 12px; }\n .bs-ann-undo:hover { color: #fff; }\n .bs-ann-canvas-wrap {\n flex: 1; display: flex; align-items: center; justify-content: center;\n overflow: hidden; padding: 16px;\n }\n .bs-ann-canvas-wrap canvas { cursor: crosshair; border-radius: 4px; }\n `;\n\n overlay.appendChild(style);\n\n // Toolbar\n const toolbar = document.createElement('div');\n toolbar.className = 'bs-ann-toolbar';\n\n // Tool buttons\n for (const tool of TOOLS) {\n const btn = document.createElement('button');\n btn.className = `bs-ann-tool${tool.id === currentTool ? ' active' : ''}`;\n btn.title = tool.label;\n btn.innerHTML = `<svg viewBox=\"0 0 24 24\"><path d=\"${tool.icon}\"/></svg>`;\n btn.addEventListener('click', () => {\n currentTool = tool.id;\n toolbar.querySelectorAll('.bs-ann-tool').forEach((b) => b.classList.remove('active'));\n btn.classList.add('active');\n });\n toolbar.appendChild(btn);\n }\n\n toolbar.appendChild(createSep());\n\n // Color buttons\n for (const color of COLORS) {\n const btn = document.createElement('button');\n btn.className = `bs-ann-color${color === currentColor ? ' active' : ''}`;\n btn.style.background = color;\n btn.addEventListener('click', () => {\n currentColor = color;\n toolbar.querySelectorAll('.bs-ann-color').forEach((b) => b.classList.remove('active'));\n btn.classList.add('active');\n });\n toolbar.appendChild(btn);\n }\n\n toolbar.appendChild(createSep());\n\n // Undo\n const undoBtn = document.createElement('button');\n undoBtn.className = 'bs-ann-btn bs-ann-undo';\n undoBtn.textContent = 'Undo';\n undoBtn.addEventListener('click', () => {\n shapes.pop();\n redrawCanvas();\n });\n toolbar.appendChild(undoBtn);\n\n // Save / Cancel\n const saveBtn = document.createElement('button');\n saveBtn.className = 'bs-ann-btn bs-ann-save';\n saveBtn.textContent = 'Save';\n saveBtn.addEventListener('click', saveAnnotation);\n\n const cancelBtn = document.createElement('button');\n cancelBtn.className = 'bs-ann-btn bs-ann-cancel';\n cancelBtn.textContent = 'Cancel';\n cancelBtn.addEventListener('click', () => {\n cleanup();\n resolvePromise?.(null);\n });\n\n toolbar.appendChild(saveBtn);\n toolbar.appendChild(cancelBtn);\n overlay.appendChild(toolbar);\n\n // Canvas\n const canvasWrap = document.createElement('div');\n canvasWrap.className = 'bs-ann-canvas-wrap';\n\n canvas = document.createElement('canvas');\n ctx = canvas.getContext('2d')!;\n canvasWrap.appendChild(canvas);\n overlay.appendChild(canvasWrap);\n\n document.body.appendChild(overlay);\n\n // Load screenshot\n screenshotImg = new Image();\n screenshotImg.onload = () => {\n if (!canvas || !ctx || !screenshotImg) return;\n\n // Fit to viewport\n const maxW = window.innerWidth - 32;\n const maxH = window.innerHeight - 100;\n let w = screenshotImg.width;\n let h = screenshotImg.height;\n const scale = Math.min(1, maxW / w, maxH / h);\n w = Math.round(w * scale);\n h = Math.round(h * scale);\n\n canvas.width = w;\n canvas.height = h;\n redrawCanvas();\n setupCanvasEvents();\n };\n screenshotImg.src = screenshotDataUrl;\n}\n\nfunction createSep(): HTMLDivElement {\n const sep = document.createElement('div');\n sep.className = 'bs-ann-sep';\n return sep;\n}\n\nfunction setupCanvasEvents() {\n if (!canvas) return;\n\n canvas.addEventListener('mousedown', (e) => {\n isDrawing = true;\n const { x, y } = getCanvasPos(e);\n\n currentShape = {\n type: currentTool,\n color: currentColor,\n lineWidth,\n points: [{ x, y }],\n x, y, width: 0, height: 0,\n };\n });\n\n canvas.addEventListener('mousemove', (e) => {\n if (!isDrawing || !currentShape) return;\n const { x, y } = getCanvasPos(e);\n\n if (currentShape.type === 'freehand') {\n currentShape.points!.push({ x, y });\n } else {\n currentShape.width = x - currentShape.x!;\n currentShape.height = y - currentShape.y!;\n }\n redrawCanvas();\n drawShape(currentShape);\n });\n\n const endDraw = () => {\n if (isDrawing && currentShape) {\n shapes.push(currentShape);\n currentShape = null;\n }\n isDrawing = false;\n redrawCanvas();\n };\n\n canvas.addEventListener('mouseup', endDraw);\n canvas.addEventListener('mouseleave', endDraw);\n}\n\nfunction getCanvasPos(e: MouseEvent): { x: number; y: number } {\n const rect = canvas!.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n };\n}\n\nfunction redrawCanvas() {\n if (!ctx || !canvas || !screenshotImg) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(screenshotImg, 0, 0, canvas.width, canvas.height);\n for (const shape of shapes) {\n drawShape(shape);\n }\n}\n\nfunction drawShape(shape: AnnotationShape) {\n if (!ctx) return;\n ctx.strokeStyle = shape.color;\n ctx.fillStyle = shape.color;\n ctx.lineWidth = shape.lineWidth;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n switch (shape.type) {\n case 'freehand': {\n if (!shape.points || shape.points.length < 2) return;\n ctx.beginPath();\n ctx.moveTo(shape.points[0].x, shape.points[0].y);\n for (let i = 1; i < shape.points.length; i++) {\n ctx.lineTo(shape.points[i].x, shape.points[i].y);\n }\n ctx.stroke();\n break;\n }\n case 'rectangle': {\n ctx.strokeRect(shape.x!, shape.y!, shape.width!, shape.height!);\n break;\n }\n case 'circle': {\n const cx = shape.x! + shape.width! / 2;\n const cy = shape.y! + shape.height! / 2;\n const rx = Math.abs(shape.width!) / 2;\n const ry = Math.abs(shape.height!) / 2;\n ctx.beginPath();\n ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n ctx.stroke();\n break;\n }\n case 'arrow': {\n const startX = shape.x!;\n const startY = shape.y!;\n const endX = shape.x! + shape.width!;\n const endY = shape.y! + shape.height!;\n const headLen = 14;\n const angle = Math.atan2(endY - startY, endX - startX);\n\n ctx.beginPath();\n ctx.moveTo(startX, startY);\n ctx.lineTo(endX, endY);\n ctx.stroke();\n\n // Arrowhead\n ctx.beginPath();\n ctx.moveTo(endX, endY);\n ctx.lineTo(endX - headLen * Math.cos(angle - Math.PI / 6), endY - headLen * Math.sin(angle - Math.PI / 6));\n ctx.lineTo(endX - headLen * Math.cos(angle + Math.PI / 6), endY - headLen * Math.sin(angle + Math.PI / 6));\n ctx.closePath();\n ctx.fill();\n break;\n }\n }\n}\n\nfunction saveAnnotation() {\n if (!canvas) { cleanup(); resolvePromise?.(null); return; }\n const dataUrl = canvas.toDataURL('image/png');\n const result: AnnotationResult = { dataUrl, annotations: shapes };\n cleanup();\n resolvePromise?.(result);\n}\n\nfunction cleanup() {\n overlay?.remove();\n overlay = null;\n canvas = null;\n ctx = null;\n screenshotImg = null;\n shapes = [];\n currentShape = null;\n isDrawing = false;\n}\n","import type { BugStashConfig } from '@bugstash/shared';\nimport { initPanel, destroyPanel, setTheme, getCurrentThemeId, setLayout, getCurrentLayoutId } from './panel';\nimport { initLogger, getLogs, clearLogs, restoreConsole } from './logger';\nimport { initNetwork, getNetworkCaptures, getFailedNetworkCaptures, clearNetworkCaptures, restoreNetwork } from './network';\nimport { initErrors, getErrors, clearErrors, restoreErrors } from './errors';\nimport { initBreadcrumbs, getBreadcrumbs, addBreadcrumb, clearBreadcrumbs, restoreBreadcrumbs } from './breadcrumbs';\nimport { initPerformance, getPerformanceMetrics, restorePerformance } from './performance';\nimport { setEndpoint, getCurrentUser, login, logout } from './api';\nimport { getThemes, getThemeById } from './themes';\nimport { getLayouts, getLayoutById } from './layouts';\nimport { initLivePins, destroyLivePins, togglePinMode, isPinModeActive } from './livepins';\nimport { connectRealtime, disconnectRealtime, isConnected } from './realtime';\nimport { openAnnotationEditor, type AnnotationResult } from './annotation';\nimport { redactString, redactObject } from './redact';\n\nexport type { AnnotationResult };\n\nexport type {\n BugStashConfig,\n LogEntry,\n NetworkEntry,\n ErrorEntry,\n Breadcrumb,\n PerformanceMetrics,\n BugReport,\n ReportContext,\n APIResponse,\n AuthUser,\n AuthTokens,\n LivePin,\n PinComment,\n Member,\n Organization,\n Project,\n Webhook,\n WebhookEvent,\n Integration,\n IntegrationType,\n SourceMap,\n PlanLimits,\n QuotaStatus,\n OrgBranding,\n AnnotationShape,\n TwoFactorSetup,\n TwoFactorStatus,\n DuplicateMatch,\n} from '@bugstash/shared';\n\nlet initialized = false;\n\n/**\n * Auto-detect the environment from the current hostname when `environment`\n * is not explicitly set.\n *\n * Production hostnames → SDK stays silent (no UI, no network calls)\n * Staging/preview hosts → SDK activates in staging mode\n * localhost / 127.x / *.local / IP → SDK activates in development mode\n *\n * Users can always override by passing `environment` explicitly.\n */\nfunction detectEnvironment(): 'development' | 'staging' | 'production' {\n if (typeof window === 'undefined') return 'production';\n const host = window.location.hostname;\n\n // Explicit localhost / loopback / local network\n if (\n host === 'localhost' ||\n host === '127.0.0.1' ||\n host === '0.0.0.0' ||\n host.endsWith('.local') ||\n /^192\\.168\\./.test(host) ||\n /^10\\./.test(host) ||\n /^172\\.(1[6-9]|2\\d|3[01])\\./.test(host)\n ) return 'development';\n\n // Common staging/preview patterns\n if (\n host.includes('staging') ||\n host.includes('stage') ||\n host.includes('preview') ||\n host.includes('preprod') ||\n host.includes('pre-prod') ||\n host.includes('qa.') ||\n host.includes('.qa') ||\n host.includes('test.') ||\n host.includes('.dev.') ||\n host.includes('vercel.app') || // Vercel preview deployments\n host.includes('netlify.app') || // Netlify preview deployments\n host.includes('pages.dev') || // Cloudflare Pages previews\n host.includes('ngrok.io') || // ngrok tunnels\n host.includes('ngrok-free.app') || // ngrok free tier\n host.includes('localhost.run') || // localhost.run tunnels\n host.includes('loca.lt') // localtunnel\n ) return 'staging';\n\n // Everything else is treated as production — SDK will be silent\n return 'production';\n}\n\nexport const BugStash = {\n init(options: BugStashConfig) {\n if (initialized) return;\n if (typeof window === 'undefined') return;\n\n const env = options.environment ?? detectEnvironment();\n if (env === 'production') return;\n\n initialized = true;\n\n if (options.endpoint) setEndpoint(options.endpoint);\n\n // Order matters: breadcrumbs first (other modules push to it)\n initBreadcrumbs(options.maxBreadcrumbs);\n initLogger(options.maxLogs);\n initNetwork(options.maxNetworkCaptures);\n initErrors();\n if (options.enablePerformance !== false) initPerformance();\n initPanel(options);\n\n // Init live pins if enabled and user is logged in\n if (options.enableLivePins !== false) {\n const user = getCurrentUser();\n if (user) {\n initLivePins(options.projectId);\n connectRealtime(options.projectId);\n }\n }\n },\n\n destroy() {\n if (!initialized) return;\n destroyPanel();\n destroyLivePins();\n disconnectRealtime();\n restoreConsole();\n restoreNetwork();\n restoreErrors();\n restoreBreadcrumbs();\n restorePerformance();\n initialized = false;\n },\n\n // Programmatic API\n getLogs,\n clearLogs,\n getNetworkCaptures,\n getFailedNetworkCaptures,\n clearNetworkCaptures,\n getErrors,\n clearErrors,\n getBreadcrumbs,\n clearBreadcrumbs,\n getPerformanceMetrics,\n addBreadcrumb,\n // Theme API\n getThemes,\n getThemeById,\n setTheme,\n getCurrentThemeId,\n // Layout API\n getLayouts,\n getLayoutById,\n setLayout,\n getCurrentLayoutId,\n // Auth API\n getCurrentUser,\n login,\n logout,\n // Live Pins API\n togglePinMode,\n isPinModeActive,\n // Real-time\n isConnected,\n // Annotation\n openAnnotationEditor,\n // PII Redaction\n redactString,\n redactObject,\n};\n\nexport default BugStash;\n"],"mappings":"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c;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgiCf,SAASC,IAAmB,CA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","names":["crumbs","maxCrumbs","clickHandler","inputHandler","popstateHandler","hashHandler","getSelector","el","tag","cls","text","label","addBreadcrumb","crumb","initBreadcrumbs","max","e","target","inputTimers","existing","isPassword","getBreadcrumbs","clearBreadcrumbs","restoreBreadcrumbs","REDACT_PLACEHOLDER","PATTERNS","match","eqIdx","colonIdx","redactString","input","result","pattern","replacement","PATTERNS","redactLogArgs","args","redactString","redactObject","obj","result","key","value","lk","REDACT_PLACEHOLDER","originals","logs","maxLogs","serialize","args","a","capture","level","entry","redactLogArgs","addBreadcrumb","initLogger","max","getLogs","clearLogs","restoreConsole","captures","maxCaptures","originalFetch","originalXHROpen","originalXHRSend","record","entry","addBreadcrumb","shortenUrl","url","u","params","key","lk","qs","redactString","patchFetch","input","init","method","rawUrl","start","response","err","patchXHR","rest","body","initNetwork","max","getNetworkCaptures","getFailedNetworkCaptures","c","clearNetworkCaptures","restoreNetwork","errors","onErrorHandler","onRejectionHandler","initErrors","event","entry","addBreadcrumb","reason","message","getErrors","clearErrors","restoreErrors","metrics","lcpObserver","clsObserver","fidObserver","initPerformance","onLoad","nav","paints","p","mem","list","entries","last","clsValue","entry","getPerformanceMetrics","restorePerformance","showFlashAnimation","flash","style","captureScreenshot","result","captureSvgForeignObject","captureWithHtml2Canvas","captureBasicCanvas","w","h","clone","sourceElements","cloneElements","i","computed","el","props","prop","img","src","html","svg","blob","url","resolve","canvas","ctx","reject","script","bodyBg","elements","rect","PRIMARY_ENDPOINT","FALLBACK_ENDPOINT","endpoint","_usingFallback","setEndpoint","url","getEndpoint","fetchWithFallback","init","err","previousEndpoint","fallbackUrl","STORAGE_KEY","getStoredAuth","raw","auth","setStoredAuth","clearStoredAuth","getCurrentUser","getAccessToken","authHeaders","res","data","login","email","password","projectId","logout","submitReport","report","headers","authHeaders","fetchWithFallback","endpoint","fetchPagePins","projectId","pathname","createPin","pin","updatePin","pinId","updates","deletePin","fetchComments","createComment","body","mentions","fetchProjectMembers","QUEUE_KEY","queueOfflineAction","action","queue","getOfflineQueue","flushOfflineQueue","flushed","remaining","result","THEMES","getThemes","getThemeById","id","getDefaultTheme","LAYOUTS","getLayouts","getLayoutById","id","l","getDefaultLayout","LAYOUT_CSS","pollTimer","lastPollTime","POLL_INTERVAL","handlers","currentProjectId","knownPinIds","connectRealtime","projectId","startPolling","poll","token","getAccessToken","endpoint","getEndpoint","pathname","res","data","pins","serverTime","pin","emit","disconnectRealtime","onRealtimeEvent","type","handler","event","h","registerKnownPins","pinIds","isConnected","pollTimer","projectId","container","pins","members","pinMode","activePopup","currentPathname","PIN_COLORS","initLivePins","projId","createOverlay","loadPins","loadMembers","setupRealtimeListeners","watchNavigation","destroyLivePins","togglePinMode","enabled","isPinModeActive","style","e","x","y","el","showNewPinForm","result","fetchPagePins","registerKnownPins","p","renderPins","fetchProjectMembers","pin","i","dot","color","showPinPopup","timeAgo","ts","diff","mins","hrs","statusColor","status","dotEl","closePopup","popup","commentsRes","fetchComments","comments","user","getCurrentUser","canManage","escapeHtml","input","body","res","createComment","commentsEl","c","queueOfflineAction","updatePin","deletePin","getSelector","selector","classes","parent","siblings","idx","getXPath","parts","current","sib","pageX","pageY","targetEl","form","rect","memberOptions","m","title","desc","priority","category","assigneeId","xpath","logs","getLogs","l","errors","getErrors","netErrors","getFailedNetworkCaptures","n","screenshot","captureScreenshot","pinData","createPin","onRealtimeEvent","event","updated","id","comment","lastPath","check","origPush","origReplace","args","str","div","config","fab","toolbar","modal","backdrop","styleEl","keyHandler","isOpen","toolbarVisible","activeTab","currentTheme","getDefaultTheme","currentLayout","getDefaultLayout","I","STYLES","tabLogin","esc","s","timeAgo","ts","fmtTime","HISTORY_KEY","getReportHistory","saveReportHistory","entries","addToHistory","entry","id","deleteFromHistory","e","updateInHistory","updates","idx","buildContext","config","autoDetect","errors","getErrors","logs","getLogs","net","getNetworkCaptures","failedNet","getFailedNetworkCaptures","crumbs","getBreadcrumbs","perf","getPerformanceMetrics","consoleErrors","l","severity","tags","tabReport","d","categories","hasIssues","c","tabConsole","lvMap","tabNetwork","caps","n","tabContext","html","errs","bars","label","val","max","pct","p","b","ctx","tabHistory","catLabels","fmtDate","diffMs","diffMin","diffH","diffD","pinsHtml","tabSettings","themes","getThemes","layouts","getLayouts","t","setupAnnotation","container","screenshotData","COLORS","currentColor","currentTool","brushSize","zoom","isDark","shapes","pins","selectedIdx","hoveredIdx","dragging","drawing","dragOffX","dragOffY","startX","startY","currentDraw","PIN_COLORS","img","wrap","viewport","canvas","toolbar","tIcons","toolNames","toolBtns","setTool","btn","color","i","sizeSlider","right","mkBtn","title","svg","zoomOut","zoomLabel","zoomIn","zoomReset","undoBtn","clearBtn","applyZoom","el","pinLayer","pinList","renderPins","pin","pctX","pctY","pinDragging","onMove","me","r","onUp","item","del","outlineColor","drawOutline","fn","lw","renderShape","preview","alpha","stroke","angle","headLen","fontSize","isSelected","isHovered","shapeBounds","handles","hx","hy","render","x","y","minX","minY","maxX","maxY","hitTest","pad","moveShape","dx","dy","scale","samplePoints","totalBrightness","sx","sy","px","coords","autoSelectDrag","hit","note","input","rx","ry","cx2","cy2","endDraw","keyHandler","bakePins","switchTab","tab","modal","activeTab","scroll","renderers","bindTabContent","card","existing","confirm","yes","no","editSev","sb","row","save","cancel","newTitle","newDesc","setTheme","layout","getLayoutById","close","open","cat","sev","annotator","titleEl","subEl","area","backdrop","captureScreenshot","form","description","category","detected","report","result","submitReport","isOpen","hideToolbar","fails","applyThemeVars","tabsHtml","user","getCurrentUser","initials","w","pinActive","isPinModeActive","headerHtml","useSidebar","useBottomTabs","contentHtml","fab","active","togglePinMode","logout","bindLoginForm","escHandler","submitBtn","emailInput","passInput","errorEl","doLogin","email","password","login","initLivePins","connectRealtime","key","themeId","theme","getThemeById","getCurrentThemeId","setLayout","layoutId","getCurrentLayoutId","initPanel","cfg","styleEl","LAYOUT_CSS","side","mod","tbButtons","shot","sub","modalBtn","newId","tb","showToolbar","related","toolbarVisible","destroyPanel","overlay","canvas","ctx","screenshotImg","currentTool","currentColor","lineWidth","shapes","currentShape","isDrawing","resolvePromise","TOOLS","COLORS","openAnnotationEditor","screenshotDataUrl","resolve","createOverlay","style","toolbar","tool","btn","b","createSep","color","undoBtn","redrawCanvas","saveBtn","saveAnnotation","cancelBtn","cleanup","canvasWrap","maxW","maxH","w","h","scale","setupCanvasEvents","sep","e","x","y","getCanvasPos","drawShape","endDraw","rect","shape","i","cx","cy","rx","ry","startX","startY","endX","endY","headLen","angle","result","initialized","detectEnvironment","host","BugStash","options","setEndpoint","initBreadcrumbs","initLogger","initNetwork","initErrors","initPerformance","initPanel","getCurrentUser","initLivePins","connectRealtime","destroyPanel","destroyLivePins","disconnectRealtime","restoreConsole","restoreNetwork","restoreErrors","restoreBreadcrumbs","restorePerformance","getLogs","clearLogs","getNetworkCaptures","getFailedNetworkCaptures","clearNetworkCaptures","getErrors","clearErrors","getBreadcrumbs","clearBreadcrumbs","getPerformanceMetrics","addBreadcrumb","getThemes","getThemeById","setTheme","getCurrentThemeId","getLayouts","getLayoutById","setLayout","getCurrentLayoutId","login","logout","togglePinMode","isPinModeActive","isConnected","openAnnotationEditor","redactString","redactObject","index_default"]}