bugstash 0.1.8 → 0.1.9

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 screenshot capture.\n * Serializes the DOM into an SVG foreignObject and renders it to a canvas.\n * Falls back to getDisplayMedia (screen capture API) if SVG approach fails.\n */\n\nexport async function captureScreenshot(): Promise<string | null> {\n // Try SVG foreignObject approach first (no permission needed)\n try {\n const result = await captureSvgForeignObject();\n if (result) return result;\n } catch { /* fall through */ }\n\n // Fallback: getDisplayMedia (shows browser permission popup)\n try {\n const result = await captureDisplayMedia();\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 // Copy key visual properties\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-modal, .bs-backdrop').forEach(el => el.remove());\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.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 resolve(canvas.toDataURL('image/jpeg', 0.6));\n };\n img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };\n img.src = url;\n });\n}\n\n/** Capture via Screen Capture API — requires user permission */\nasync function captureDisplayMedia(): Promise<string | null> {\n if (!navigator.mediaDevices?.getDisplayMedia) return null;\n\n const stream = await navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: 'browser' } as any });\n const track = stream.getVideoTracks()[0];\n const video = document.createElement('video');\n\n return new Promise<string | null>((resolve) => {\n video.onloadedmetadata = () => {\n video.play();\n const canvas = document.createElement('canvas');\n canvas.width = video.videoWidth * 0.5;\n canvas.height = video.videoHeight * 0.5;\n const ctx = canvas.getContext('2d');\n if (!ctx) { track.stop(); resolve(null); return; }\n ctx.scale(0.5, 0.5);\n ctx.drawImage(video, 0, 0);\n track.stop();\n resolve(canvas.toDataURL('image/jpeg', 0.6));\n };\n video.onerror = () => { track.stop(); resolve(null); };\n video.srcObject = stream;\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://api.bugstash.com';\nconst FALLBACK_ENDPOINT = 'https://bugstash-backend.azurewebsites.net';\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\n// Every theme sets these CSS custom properties.\n// The panel base styles reference them via var(--bs-xxx).\nconst THEMES: BsTheme[] = [\n // ─── 1. Midnight ─────────────────────────────────\n {\n id: 'midnight',\n name: 'Midnight',\n preview: ['#1a1d2e', '#6E9ED0'],\n vars: {\n '--bs-bg': '#1a1d2e',\n '--bs-bg2': '#222639',\n '--bs-bg3': '#2a2e42',\n '--bs-text': '#e2e5ed',\n '--bs-muted': '#7c82a0',\n '--bs-border': '#333754',\n '--bs-accent': '#6E9ED0',\n '--bs-accent2': '#8FAFD6',\n '--bs-fab1': '#6E9ED0',\n '--bs-fab2': '#8FAFD6',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 2. Deep Purple ──────────────────────────────\n {\n id: 'purple',\n name: 'Deep Purple',\n preview: ['#1c1628', '#a78bfa'],\n vars: {\n '--bs-bg': '#1c1628',\n '--bs-bg2': '#241e34',\n '--bs-bg3': '#2e2640',\n '--bs-text': '#e8e0f5',\n '--bs-muted': '#8b7faa',\n '--bs-border': '#3b3255',\n '--bs-accent': '#a78bfa',\n '--bs-accent2': '#c4b5fd',\n '--bs-fab1': '#a78bfa',\n '--bs-fab2': '#c084fc',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#fb7185',\n '--bs-green': '#6ee7b7',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 3. Cyberpunk ────────────────────────────────\n {\n id: 'cyberpunk',\n name: 'Cyberpunk',\n preview: ['#0a0a12', '#00fff0'],\n vars: {\n '--bs-bg': '#0a0a12',\n '--bs-bg2': '#12121f',\n '--bs-bg3': '#1a1a2c',\n '--bs-text': '#e0f7fa',\n '--bs-muted': '#5e7f88',\n '--bs-border': '#1e3a3f',\n '--bs-accent': '#00fff0',\n '--bs-accent2': '#00c8ff',\n '--bs-fab1': '#00fff0',\n '--bs-fab2': '#ff00c8',\n '--bs-radius': '4px',\n '--bs-radius-sm': '2px',\n '--bs-red': '#ff3860',\n '--bs-green': '#00ff88',\n '--bs-orange': '#ffaa00',\n '--bs-yellow': '#ffe600',\n },\n },\n // ─── 4. Sunset ───────────────────────────────────\n {\n id: 'sunset',\n name: 'Sunset',\n preview: ['#1f1318', '#f97316'],\n vars: {\n '--bs-bg': '#1f1318',\n '--bs-bg2': '#291a20',\n '--bs-bg3': '#33212a',\n '--bs-text': '#f5e6ea',\n '--bs-muted': '#a07880',\n '--bs-border': '#4a2a34',\n '--bs-accent': '#f97316',\n '--bs-accent2': '#fb923c',\n '--bs-fab1': '#f97316',\n '--bs-fab2': '#ef4444',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 5. Ocean ────────────────────────────────────\n {\n id: 'ocean',\n name: 'Ocean',\n preview: ['#0d1b2a', '#2dd4bf'],\n vars: {\n '--bs-bg': '#0d1b2a',\n '--bs-bg2': '#132638',\n '--bs-bg3': '#1a3146',\n '--bs-text': '#d6f0ee',\n '--bs-muted': '#5c8a8e',\n '--bs-border': '#1f4050',\n '--bs-accent': '#2dd4bf',\n '--bs-accent2': '#5eead4',\n '--bs-fab1': '#2dd4bf',\n '--bs-fab2': '#22d3ee',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#6ee7b7',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 6. Rose ─────────────────────────────────────\n {\n id: 'rose',\n name: 'Rose Gold',\n preview: ['#1f1520', '#f472b6'],\n vars: {\n '--bs-bg': '#1f1520',\n '--bs-bg2': '#2a1c2a',\n '--bs-bg3': '#352434',\n '--bs-text': '#f5e0ec',\n '--bs-muted': '#a07090',\n '--bs-border': '#4a2a44',\n '--bs-accent': '#f472b6',\n '--bs-accent2': '#f9a8d4',\n '--bs-fab1': '#f472b6',\n '--bs-fab2': '#e879f9',\n '--bs-radius': '20px',\n '--bs-radius-sm': '12px',\n '--bs-red': '#fb7185',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 7. Arctic (Light) ──────────────────────────\n {\n id: 'arctic',\n name: 'Arctic Light',\n preview: ['#f0f4f8', '#3b82f6'],\n vars: {\n '--bs-bg': '#f0f4f8',\n '--bs-bg2': '#e2e8f0',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#1e293b',\n '--bs-muted': '#64748b',\n '--bs-border': '#cbd5e1',\n '--bs-accent': '#3b82f6',\n '--bs-accent2': '#60a5fa',\n '--bs-fab1': '#3b82f6',\n '--bs-fab2': '#6366f1',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── 8. Glass ────────────────────────────────────\n {\n id: 'glass',\n name: 'Glassmorphism',\n preview: ['rgba(30,30,50,0.6)', '#a5b4fc'],\n vars: {\n '--bs-bg': 'rgba(22,22,40,0.75)',\n '--bs-bg2': 'rgba(35,35,60,0.6)',\n '--bs-bg3': 'rgba(45,45,75,0.5)',\n '--bs-text': '#e8eaff',\n '--bs-muted': '#8888bb',\n '--bs-border': 'rgba(255,255,255,0.1)',\n '--bs-accent': '#a5b4fc',\n '--bs-accent2': '#c7d2fe',\n '--bs-fab1': '#818cf8',\n '--bs-fab2': '#a78bfa',\n '--bs-radius': '20px',\n '--bs-radius-sm': '12px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 9. Neon Green ──────────────────────────────\n {\n id: 'neon',\n name: 'Neon',\n preview: ['#080c08', '#39ff14'],\n vars: {\n '--bs-bg': '#080c08',\n '--bs-bg2': '#0f150f',\n '--bs-bg3': '#161e16',\n '--bs-text': '#d0f0c0',\n '--bs-muted': '#5a7a50',\n '--bs-border': '#1e3018',\n '--bs-accent': '#39ff14',\n '--bs-accent2': '#7dff5e',\n '--bs-fab1': '#39ff14',\n '--bs-fab2': '#00ff88',\n '--bs-radius': '8px',\n '--bs-radius-sm': '4px',\n '--bs-red': '#ff4444',\n '--bs-green': '#39ff14',\n '--bs-orange': '#ffaa00',\n '--bs-yellow': '#e6ff00',\n },\n },\n // ─── 10. Forest ──────────────────────────────────\n {\n id: 'forest',\n name: 'Forest',\n preview: ['#111c15', '#34d399'],\n vars: {\n '--bs-bg': '#111c15',\n '--bs-bg2': '#18261d',\n '--bs-bg3': '#203026',\n '--bs-text': '#d1f0dd',\n '--bs-muted': '#6a9a7a',\n '--bs-border': '#2a4a33',\n '--bs-accent': '#34d399',\n '--bs-accent2': '#6ee7b7',\n '--bs-fab1': '#34d399',\n '--bs-fab2': '#2dd4bf',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 11. Minimal Dark ───────────────────────────\n {\n id: 'minimal-dark',\n name: 'Minimal Dark',\n preview: ['#18181b', '#a1a1aa'],\n vars: {\n '--bs-bg': '#18181b',\n '--bs-bg2': '#212124',\n '--bs-bg3': '#2a2a2e',\n '--bs-text': '#e4e4e7',\n '--bs-muted': '#71717a',\n '--bs-border': '#333338',\n '--bs-accent': '#a1a1aa',\n '--bs-accent2': '#d4d4d8',\n '--bs-fab1': '#52525b',\n '--bs-fab2': '#71717a',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 12. Minimal Light ──────────────────────────\n {\n id: 'minimal-light',\n name: 'Minimal Light',\n preview: ['#fafafa', '#52525b'],\n vars: {\n '--bs-bg': '#fafafa',\n '--bs-bg2': '#f0f0f0',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#18181b',\n '--bs-muted': '#71717a',\n '--bs-border': '#e4e4e7',\n '--bs-accent': '#18181b',\n '--bs-accent2': '#3f3f46',\n '--bs-fab1': '#18181b',\n '--bs-fab2': '#3f3f46',\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 // ─── 13. Dracula ─────────────────────────────────\n {\n id: 'dracula',\n name: 'Dracula',\n preview: ['#282a36', '#bd93f9'],\n vars: {\n '--bs-bg': '#282a36',\n '--bs-bg2': '#2e303e',\n '--bs-bg3': '#363848',\n '--bs-text': '#f8f8f2',\n '--bs-muted': '#6272a4',\n '--bs-border': '#44475a',\n '--bs-accent': '#bd93f9',\n '--bs-accent2': '#caa9fa',\n '--bs-fab1': '#bd93f9',\n '--bs-fab2': '#ff79c6',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ff5555',\n '--bs-green': '#50fa7b',\n '--bs-orange': '#ffb86c',\n '--bs-yellow': '#f1fa8c',\n },\n },\n // ─── 14. Nord ────────────────────────────────────\n {\n id: 'nord',\n name: 'Nord',\n preview: ['#2e3440', '#88c0d0'],\n vars: {\n '--bs-bg': '#2e3440',\n '--bs-bg2': '#3b4252',\n '--bs-bg3': '#434c5e',\n '--bs-text': '#eceff4',\n '--bs-muted': '#7b88a1',\n '--bs-border': '#4c566a',\n '--bs-accent': '#88c0d0',\n '--bs-accent2': '#8fbcbb',\n '--bs-fab1': '#88c0d0',\n '--bs-fab2': '#81a1c1',\n '--bs-radius': '10px',\n '--bs-radius-sm': '6px',\n '--bs-red': '#bf616a',\n '--bs-green': '#a3be8c',\n '--bs-orange': '#d08770',\n '--bs-yellow': '#ebcb8b',\n },\n },\n // ─── 15. Monokai ─────────────────────────────────\n {\n id: 'monokai',\n name: 'Monokai',\n preview: ['#272822', '#a6e22e'],\n vars: {\n '--bs-bg': '#272822',\n '--bs-bg2': '#2f302a',\n '--bs-bg3': '#383930',\n '--bs-text': '#f8f8f2',\n '--bs-muted': '#75715e',\n '--bs-border': '#49483e',\n '--bs-accent': '#a6e22e',\n '--bs-accent2': '#c4f060',\n '--bs-fab1': '#a6e22e',\n '--bs-fab2': '#66d9ef',\n '--bs-radius': '8px',\n '--bs-radius-sm': '4px',\n '--bs-red': '#f92672',\n '--bs-green': '#a6e22e',\n '--bs-orange': '#fd971f',\n '--bs-yellow': '#e6db74',\n },\n },\n // ─── 16. Solarized ──────────────────────────────\n {\n id: 'solarized',\n name: 'Solarized Dark',\n preview: ['#002b36', '#268bd2'],\n vars: {\n '--bs-bg': '#002b36',\n '--bs-bg2': '#073642',\n '--bs-bg3': '#0e4050',\n '--bs-text': '#eee8d5',\n '--bs-muted': '#839496',\n '--bs-border': '#1a4f5c',\n '--bs-accent': '#268bd2',\n '--bs-accent2': '#2aa198',\n '--bs-fab1': '#268bd2',\n '--bs-fab2': '#2aa198',\n '--bs-radius': '10px',\n '--bs-radius-sm': '6px',\n '--bs-red': '#dc322f',\n '--bs-green': '#859900',\n '--bs-orange': '#cb4b16',\n '--bs-yellow': '#b58900',\n },\n },\n // ─── 17. Candy ───────────────────────────────────\n {\n id: 'candy',\n name: 'Candy',\n preview: ['#fef1f8', '#ec4899'],\n vars: {\n '--bs-bg': '#fef1f8',\n '--bs-bg2': '#fce7f3',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#4a1942',\n '--bs-muted': '#9f5090',\n '--bs-border': '#f0c6e0',\n '--bs-accent': '#ec4899',\n '--bs-accent2': '#f472b6',\n '--bs-fab1': '#ec4899',\n '--bs-fab2': '#a855f7',\n '--bs-radius': '20px',\n '--bs-radius-sm': '14px',\n '--bs-red': '#e11d48',\n '--bs-green': '#059669',\n '--bs-orange': '#ea580c',\n '--bs-yellow': '#ca8a04',\n },\n },\n // ─── 18. Slate ───────────────────────────────────\n {\n id: 'slate',\n name: 'Slate',\n preview: ['#1e2432', '#94a3b8'],\n vars: {\n '--bs-bg': '#1e2432',\n '--bs-bg2': '#263040',\n '--bs-bg3': '#2e384a',\n '--bs-text': '#e2e8f0',\n '--bs-muted': '#64748b',\n '--bs-border': '#374462',\n '--bs-accent': '#94a3b8',\n '--bs-accent2': '#cbd5e1',\n '--bs-fab1': '#475569',\n '--bs-fab2': '#64748b',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 19. Ember ───────────────────────────────────\n {\n id: 'ember',\n name: 'Ember',\n preview: ['#1a0f0f', '#ef4444'],\n vars: {\n '--bs-bg': '#1a0f0f',\n '--bs-bg2': '#241515',\n '--bs-bg3': '#2e1c1c',\n '--bs-text': '#fde8e8',\n '--bs-muted': '#a06060',\n '--bs-border': '#4a2222',\n '--bs-accent': '#ef4444',\n '--bs-accent2': '#f87171',\n '--bs-fab1': '#ef4444',\n '--bs-fab2': '#f97316',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 20. Lavender ───────────────────────────────\n {\n id: 'lavender',\n name: 'Lavender',\n preview: ['#f5f0ff', '#7c3aed'],\n vars: {\n '--bs-bg': '#f5f0ff',\n '--bs-bg2': '#ede5ff',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#2e1065',\n '--bs-muted': '#7c6a9a',\n '--bs-border': '#d8c8f0',\n '--bs-accent': '#7c3aed',\n '--bs-accent2': '#8b5cf6',\n '--bs-fab1': '#7c3aed',\n '--bs-fab2': '#a855f7',\n '--bs-radius': '18px',\n '--bs-radius-sm': '12px',\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 // 1\n { id: 'classic', name: 'Classic Center', description: 'Centered modal, top tabs', tabPosition: 'top' },\n // 2\n { id: 'drawer-right', name: 'Right Drawer', description: 'Slides in from the right', tabPosition: 'top' },\n // 3\n { id: 'drawer-left', name: 'Left Drawer', description: 'Slides in from the left', tabPosition: 'top' },\n // 4\n { id: 'bottom-sheet', name: 'Bottom Sheet', description: 'Slides up from the bottom', tabPosition: 'top' },\n // 5\n { id: 'top-bar', name: 'Top Drop', description: 'Drops down from the top', tabPosition: 'top' },\n // 6\n { id: 'compact', name: 'Compact', description: 'Small centered popup', tabPosition: 'top' },\n // 7\n { id: 'wide', name: 'Wide', description: 'Wide horizontal modal', tabPosition: 'top' },\n // 8\n { id: 'fullscreen', name: 'Fullscreen', description: 'Full screen overlay', tabPosition: 'top' },\n // 9\n { id: 'corner-br', name: 'Corner Card', description: 'Bottom-right corner card', tabPosition: 'top' },\n // 10\n { id: 'corner-bl', name: 'Corner Left', description: 'Bottom-left corner card', tabPosition: 'top' },\n // 11\n { id: 'pill-tabs', name: 'Pill Tabs', description: 'Centered with pill-style tabs', tabPosition: 'top' },\n // 12\n { id: 'sidebar-tabs', name: 'Sidebar Tabs', description: 'Vertical tabs on the left', tabPosition: 'left' },\n // 13\n { id: 'segmented', name: 'Segmented', description: 'Tabs as segmented control', tabPosition: 'top' },\n // 14\n { id: 'minimal', name: 'Minimal', description: 'Ultra clean, spacious', tabPosition: 'top' },\n // 15\n { id: 'dense', name: 'Dense', description: 'Compact, tight spacing', tabPosition: 'top' },\n // 16\n { id: 'rounded', name: 'Bubble', description: 'Extra rounded, playful', tabPosition: 'top' },\n // 17\n { id: 'sharp', name: 'Sharp', description: 'Square corners, industrial', tabPosition: 'top' },\n // 18\n { id: 'split', name: 'Split View', description: 'Two-column layout', tabPosition: 'left' },\n // 19\n { id: 'floating', name: 'Floating', description: 'Heavy shadow, borderless', tabPosition: 'top' },\n // 20\n { id: 'bottom-tabs', name: 'Bottom Tabs', description: 'Tabs at the bottom', tabPosition: 'bottom' },\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// Each layout overrides the base .bs-modal / .bs-tabs etc.\n// Applied via a class on the modal: .bs-ly-{id}\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. Drawer Left ── */\n.bs-ly-drawer-left.bs-modal {\n top: 0; left: 0; right: auto; 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-left.bs-modal.bs-in {\n transform: translateX(0);\n opacity: 1;\n}\n\n/* ── 4. 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/* ── 5. Top Drop ── */\n.bs-ly-top-bar.bs-modal {\n top: 0; left: 50%; bottom: auto;\n width: 700px; max-width: 100vw;\n max-height: 75vh;\n border-radius: 0 0 var(--bs-radius) var(--bs-radius);\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-top-bar.bs-modal.bs-in {\n transform: translate(-50%, 0);\n opacity: 1;\n}\n\n/* ── 6. Compact ── */\n.bs-ly-compact.bs-modal {\n width: 380px;\n}\n.bs-ly-compact .bs-scroll { padding: 12px 16px 16px; }\n.bs-ly-compact .bs-hdr { padding: 14px 16px 0; }\n.bs-ly-compact .bs-tabs { padding: 8px 16px 0; }\n.bs-ly-compact .bs-tab { padding: 7px 10px; font-size: 11px; }\n.bs-ly-compact .bs-field { margin-bottom: 10px; }\n.bs-ly-compact .bs-input, .bs-ly-compact .bs-textarea { padding: 8px 10px; font-size: 13px; }\n.bs-ly-compact .bs-submit-btn { padding: 10px; font-size: 13px; }\n\n/* ── 7. Wide ── */\n.bs-ly-wide.bs-modal {\n width: 720px;\n}\n.bs-ly-wide .bs-scroll { padding: 20px 32px 28px; }\n.bs-ly-wide .bs-hdr { padding: 22px 32px 0; }\n.bs-ly-wide .bs-tabs { padding: 14px 32px 0; }\n\n/* ── 8. Fullscreen ── */\n.bs-ly-fullscreen.bs-modal {\n top: 0; left: 0; width: 100vw; max-width: 100vw;\n height: 100vh; max-height: 100vh;\n border-radius: 0;\n transform: scale(0.95);\n transition: transform 0.35s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-fullscreen.bs-modal.bs-in {\n transform: scale(1);\n opacity: 1;\n}\n.bs-ly-fullscreen .bs-scroll { padding: 24px 15%; }\n.bs-ly-fullscreen .bs-hdr { padding: 24px 15% 0; }\n.bs-ly-fullscreen .bs-tabs { padding: 16px 15% 0; }\n\n/* ── 9. Corner Bottom-Right ── */\n.bs-ly-corner-br.bs-modal {\n top: auto; left: auto; right: 24px; bottom: 88px;\n width: 400px;\n max-height: 70vh;\n transform: translateY(20px) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease;\n}\n.bs-ly-corner-br.bs-modal.bs-in {\n transform: translateY(0) scale(1);\n opacity: 1;\n}\n\n/* ── 10. Corner Bottom-Left ── */\n.bs-ly-corner-bl.bs-modal {\n top: auto; left: 24px; right: auto; bottom: 88px;\n width: 400px;\n max-height: 70vh;\n transform: translateY(20px) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease;\n}\n.bs-ly-corner-bl.bs-modal.bs-in {\n transform: translateY(0) scale(1);\n opacity: 1;\n}\n\n/* ── 11. Pill Tabs ── */\n.bs-ly-pill-tabs .bs-tabs {\n background: var(--bs-bg2);\n margin: 12px 22px 0;\n border-radius: 999px;\n padding: 4px;\n gap: 4px;\n}\n.bs-ly-pill-tabs .bs-tab {\n border-radius: 999px;\n padding: 8px 14px;\n justify-content: center;\n flex: 1;\n}\n.bs-ly-pill-tabs .bs-tab.bs-active {\n background: var(--bs-accent);\n color: #fff;\n}\n.bs-ly-pill-tabs .bs-tab.bs-active::after { display: none; }\n.bs-ly-pill-tabs .bs-tab.bs-active .bs-tab-badge { background: rgba(255,255,255,0.25); color: #fff; }\n.bs-ly-pill-tabs .bs-tab-divider { display: none; }\n\n/* ── 12. 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/* ── 13. Segmented ── */\n.bs-ly-segmented .bs-tabs {\n background: var(--bs-bg2);\n margin: 12px 22px 0;\n border-radius: var(--bs-radius-sm);\n padding: 3px;\n gap: 3px;\n border: 1px solid var(--bs-border);\n}\n.bs-ly-segmented .bs-tab {\n border-radius: calc(var(--bs-radius-sm) - 2px);\n padding: 8px 12px;\n justify-content: center;\n flex: 1;\n font-size: 11px;\n}\n.bs-ly-segmented .bs-tab.bs-active { background: var(--bs-bg); box-shadow: 0 1px 3px rgba(0,0,0,0.2); }\n.bs-ly-segmented .bs-tab.bs-active::after { display: none; }\n.bs-ly-segmented .bs-tab-divider { display: none; }\n\n/* ── 14. Minimal ── */\n.bs-ly-minimal.bs-modal {\n border: none;\n box-shadow: 0 40px 100px rgba(0,0,0,0.5);\n}\n.bs-ly-minimal .bs-hdr { padding: 28px 32px 0; }\n.bs-ly-minimal .bs-tabs { padding: 16px 32px 0; }\n.bs-ly-minimal .bs-scroll { padding: 24px 32px 32px; }\n.bs-ly-minimal .bs-field { margin-bottom: 22px; }\n.bs-ly-minimal .bs-input, .bs-ly-minimal .bs-textarea {\n border-color: transparent;\n background: var(--bs-bg2);\n}\n.bs-ly-minimal .bs-input:focus, .bs-ly-minimal .bs-textarea:focus { border-color: var(--bs-accent); }\n.bs-ly-minimal .bs-tab { font-weight: 400; letter-spacing: 0.5px; }\n.bs-ly-minimal .bs-tab.bs-active { font-weight: 700; }\n\n/* ── 15. Dense ── */\n.bs-ly-dense.bs-modal { width: 480px; }\n.bs-ly-dense .bs-hdr { padding: 10px 14px 0; }\n.bs-ly-dense .bs-logo { font-size: 14px; }\n.bs-ly-dense .bs-tabs { padding: 6px 14px 0; }\n.bs-ly-dense .bs-tab { padding: 6px 8px; font-size: 10px; gap: 4px; }\n.bs-ly-dense .bs-tab svg { width: 12px; height: 12px; }\n.bs-ly-dense .bs-tab-divider { margin: 0; }\n.bs-ly-dense .bs-scroll { padding: 10px 14px 14px; }\n.bs-ly-dense .bs-field { margin-bottom: 8px; }\n.bs-ly-dense .bs-field-label { font-size: 11px; margin-bottom: 4px; }\n.bs-ly-dense .bs-input, .bs-ly-dense .bs-textarea { padding: 7px 10px; font-size: 12px; }\n.bs-ly-dense .bs-textarea { min-height: 50px; }\n.bs-ly-dense .bs-sev-btn { padding: 6px 0; font-size: 10px; }\n.bs-ly-dense .bs-shot-area { padding: 8px 10px; }\n.bs-ly-dense .bs-submit-btn { padding: 10px; font-size: 13px; }\n\n/* ── 16. Bubble / Rounded ── */\n.bs-ly-rounded.bs-modal { border-radius: 28px; }\n.bs-ly-rounded .bs-hdr { padding: 22px 26px 0; }\n.bs-ly-rounded .bs-tabs { padding: 14px 26px 0; }\n.bs-ly-rounded .bs-tab { border-radius: 16px 16px 0 0; }\n.bs-ly-rounded .bs-scroll { padding: 18px 26px 26px; }\n.bs-ly-rounded .bs-input, .bs-ly-rounded .bs-textarea { border-radius: 16px; }\n.bs-ly-rounded .bs-sev-btn { border-radius: 16px; }\n.bs-ly-rounded .bs-submit-btn { border-radius: 20px; }\n.bs-ly-rounded .bs-shot-area { border-radius: 18px; }\n.bs-ly-rounded .bs-log, .bs-ly-rounded .bs-net { border-radius: 14px; }\n.bs-ly-rounded .bs-err-card { border-radius: 16px; }\n\n/* ── 17. Sharp ── */\n.bs-ly-sharp.bs-modal { border-radius: 0; }\n.bs-ly-sharp .bs-tab { border-radius: 0; }\n.bs-ly-sharp .bs-tab.bs-active::after { border-radius: 0; }\n.bs-ly-sharp .bs-input, .bs-ly-sharp .bs-textarea { border-radius: 0; }\n.bs-ly-sharp .bs-sev-btn { border-radius: 0; }\n.bs-ly-sharp .bs-submit-btn { border-radius: 0; }\n.bs-ly-sharp .bs-shot-area { border-radius: 0; }\n.bs-ly-sharp .bs-log, .bs-ly-sharp .bs-net { border-radius: 0; }\n.bs-ly-sharp .bs-err-card { border-radius: 0; }\n.bs-ly-sharp .bs-msg { border-radius: 0; }\n.bs-ly-sharp .bs-ann-wrap { border-radius: 0; }\n.bs-ly-sharp .bs-fab { border-radius: 0; }\n\n/* ── 18. Split View ── */\n.bs-ly-split.bs-modal {\n width: 700px;\n}\n.bs-ly-split .bs-body-wrap {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n.bs-ly-split .bs-tabs {\n flex-direction: column;\n padding: 16px 0 16px 16px;\n gap: 6px;\n min-width: 160px;\n border-right: 1px solid var(--bs-border);\n overflow-y: auto;\n}\n.bs-ly-split .bs-tab {\n border-radius: var(--bs-radius-sm);\n padding: 12px 14px;\n width: 100%;\n font-size: 13px;\n}\n.bs-ly-split .bs-tab.bs-active { background: var(--bs-accent); color: #fff; }\n.bs-ly-split .bs-tab.bs-active::after { display: none; }\n.bs-ly-split .bs-tab.bs-active .bs-tab-badge { background: rgba(255,255,255,0.25); color: #fff; }\n.bs-ly-split .bs-tab-divider { display: none; }\n.bs-ly-split .bs-scroll { flex: 1; }\n\n/* ── 19. Floating ── */\n.bs-ly-floating.bs-modal {\n border: none;\n box-shadow: 0 50px 120px rgba(0,0,0,0.7), 0 20px 50px rgba(0,0,0,0.4);\n border-radius: 24px;\n}\n.bs-ly-floating .bs-hdr { padding: 22px 26px 0; }\n.bs-ly-floating .bs-tabs {\n padding: 14px 26px 0;\n background: transparent;\n}\n.bs-ly-floating .bs-tab {\n background: var(--bs-bg2);\n border-radius: var(--bs-radius-sm);\n margin-right: 4px;\n}\n.bs-ly-floating .bs-tab.bs-active {\n background: var(--bs-bg3);\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n}\n.bs-ly-floating .bs-tab.bs-active::after { display: none; }\n.bs-ly-floating .bs-tab-divider { display: none; }\n.bs-ly-floating .bs-scroll { padding: 18px 26px 26px; }\n\n/* ── 20. Bottom Tabs ── */\n.bs-ly-bottom-tabs .bs-tabs {\n order: 99;\n padding: 0 22px 12px;\n border-top: 1px solid var(--bs-border);\n border-bottom: none;\n background: var(--bs-bg);\n}\n.bs-ly-bottom-tabs .bs-tab {\n border-radius: 0 0 var(--bs-radius-sm) var(--bs-radius-sm);\n flex: 1;\n justify-content: center;\n padding: 12px 8px;\n}\n.bs-ly-bottom-tabs .bs-tab.bs-active::after {\n top: 0; bottom: auto;\n border-radius: 0 0 2px 2px;\n}\n.bs-ly-bottom-tabs .bs-tab-divider { order: 98; }\n.bs-ly-bottom-tabs .bs-scroll { order: 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 socket: WebSocket | null = null;\nlet reconnectTimer: ReturnType<typeof setTimeout> | null = null;\nlet reconnectAttempts = 0;\nconst MAX_RECONNECT = 10;\nconst handlers = new Map<string, Set<EventHandler>>();\nlet currentProjectId: string | null = null;\nlet sioConnected = false;\nlet pingTimer: ReturnType<typeof setInterval> | null = null;\n\nexport function connectRealtime(projectId: string) {\n currentProjectId = projectId;\n const token = getAccessToken();\n if (!token) return;\n doConnect(projectId, token);\n}\n\nfunction doConnect(projectId: string, token: string) {\n if (socket?.readyState === WebSocket.OPEN) return;\n\n const endpoint = getEndpoint();\n sioConnected = false;\n\n try {\n const wsUrl = `${endpoint.replace(/^http/, 'ws')}/socket.io/?EIO=4&transport=websocket`;\n socket = new WebSocket(wsUrl);\n\n socket.onopen = () => {\n reconnectAttempts = 0;\n // Wait for Engine.IO open packet (0{...}) before sending Socket.IO connect\n };\n\n socket.onmessage = (e) => {\n const data = e.data as string;\n\n // Engine.IO open packet: 0{\"sid\":\"...\", \"pingInterval\":..., \"pingTimeout\":...}\n if (data.startsWith('0') && !sioConnected) {\n try {\n const payload = JSON.parse(data.slice(1));\n const interval = payload.pingInterval || 25000;\n if (pingTimer) clearInterval(pingTimer);\n pingTimer = setInterval(() => {\n if (socket?.readyState === WebSocket.OPEN) socket.send('2');\n }, interval);\n } catch { /* use defaults */ }\n // Send Socket.IO CONNECT with auth token\n socket!.send('40' + JSON.stringify({ token }));\n return;\n }\n\n // Engine.IO ping from server — respond with pong\n if (data === '2') { socket!.send('3'); return; }\n // Engine.IO pong (response to our ping)\n if (data === '3') return;\n\n // Socket.IO CONNECT ack: 40{\"sid\":\"...\"}\n if (data.startsWith('40') && !sioConnected) {\n sioConnected = true;\n // Now safe to emit events — join project room\n socket!.send('42' + JSON.stringify(['join:project', projectId]));\n return;\n }\n\n // Socket.IO ERROR: 44\"message\" or 44{...}\n if (data.startsWith('44')) {\n socket?.close();\n return;\n }\n\n // Socket.IO EVENT: 42[\"eventName\", data]\n if (data.startsWith('42')) {\n try {\n const parsed = JSON.parse(data.slice(2));\n if (Array.isArray(parsed) && parsed.length >= 2) {\n const [eventType, eventData] = parsed;\n const event: WSEvent = typeof eventData === 'object' && eventData !== null\n ? eventData\n : { type: eventType, data: eventData, projectId, userId: '', timestamp: Date.now() };\n emit(eventType, event);\n }\n } catch { /* ignore parse errors */ }\n }\n };\n\n socket.onclose = () => {\n sioConnected = false;\n if (pingTimer) { clearInterval(pingTimer); pingTimer = null; }\n scheduleReconnect(projectId, token);\n };\n\n socket.onerror = () => {\n socket?.close();\n };\n } catch {\n scheduleReconnect(projectId, token);\n }\n}\n\nfunction scheduleReconnect(projectId: string, token: string) {\n if (reconnectAttempts >= MAX_RECONNECT) return;\n reconnectAttempts++;\n const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);\n reconnectTimer = setTimeout(() => doConnect(projectId, token), delay);\n}\n\nexport function disconnectRealtime() {\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (pingTimer) clearInterval(pingTimer);\n reconnectTimer = null;\n pingTimer = null;\n reconnectAttempts = MAX_RECONNECT;\n sioConnected = false;\n if (socket) {\n socket.close();\n socket = null;\n }\n currentProjectId = null;\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\nexport function sendCursorPosition(x: number, y: number, pageUrl: string) {\n if (!socket || socket.readyState !== WebSocket.OPEN || !sioConnected || !currentProjectId) return;\n socket.send('42' + JSON.stringify(['cursor:move', { projectId: currentProjectId, x, y, pageUrl }]));\n}\n\nexport function sendPageNavigate(pageUrl: string) {\n if (!socket || socket.readyState !== WebSocket.OPEN || !sioConnected || !currentProjectId) return;\n socket.send('42' + JSON.stringify(['page:navigate', { projectId: currentProjectId, pageUrl }]));\n}\n\nexport function isConnected(): boolean {\n return sioConnected && socket?.readyState === WebSocket.OPEN;\n}\n","import type { LivePin, Member } from '@bugstash/shared';\nimport { fetchPagePins, createPin, updatePin, deletePin, fetchComments, createComment, fetchProjectMembers, getCurrentUser, queueOfflineAction } from './api';\nimport { onRealtimeEvent, sendPageNavigate } 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 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 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 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};\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 /* ── 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 .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 }[] = [\n { id: 'ui', label: 'UI Bug' },\n { id: 'functionality', label: 'Broken Feature' },\n { id: 'performance', label: 'Slow / Laggy' },\n { id: 'crash', label: 'Crash' },\n { id: 'security', label: 'Security' },\n { id: 'other', label: 'Other' },\n ];\n\n return `<div class=\"bs-view\">\n <form data-bs-form>\n <div class=\"bs-ctx-bar\">\n <div class=\"bs-ctx-chip${d.counts.logs ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.logs}</span><span class=\"bs-ctx-l\">Logs</span></div>\n <div class=\"bs-ctx-chip${d.counts.failedNet ? ' bs-alert' : d.counts.network ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.network}</span><span class=\"bs-ctx-l\">Network</span></div>\n <div class=\"bs-ctx-chip${d.counts.errors ? ' bs-alert' : ''}\"><span class=\"bs-ctx-n\">${d.counts.errors}</span><span class=\"bs-ctx-l\">Errors</span></div>\n <div class=\"bs-ctx-chip${d.counts.crumbs ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.crumbs}</span><span class=\"bs-ctx-l\">Actions</span></div>\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Bug title <span class=\"bs-field-hint\">(required)</span></div>\n <input class=\"bs-input\" name=\"title\" placeholder=\"Short summary — e.g. Checkout button unresponsive\" required autocomplete=\"off\" />\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Description</div>\n <textarea class=\"bs-textarea\" name=\"description\" placeholder=\"What were you doing? What went wrong?\"></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 <span class=\"bs-field-hint\">(suggested: ${d.severity})</span></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\">Medium</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>Captures & lets you 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\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 = `\n <div class=\"bs-hdr\">\n <div class=\"bs-logo\">BugStash</div>\n <div class=\"bs-hdr-right\">\n ${user ? `\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 ` : ''}\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>\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}\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 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[cfg.panelPosition === 'bottom-left' ? 'left' : 'right'] = '24px';\n fab.addEventListener('click', () => (isOpen ? close() : open()));\n document.body.appendChild(fab);\n\n keyHandler = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'B') {\n e.preventDefault();\n isOpen ? close() : open();\n }\n };\n document.addEventListener('keydown', keyHandler);\n}\n\nexport function destroyPanel() {\n close();\n fab?.remove();\n fab = null;\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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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","captureScreenshot","result","captureSvgForeignObject","captureDisplayMedia","w","h","clone","sourceElements","cloneElements","i","computed","el","props","prop","html","svg","blob","url","resolve","img","canvas","ctx","stream","track","video","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","socket","reconnectTimer","reconnectAttempts","MAX_RECONNECT","handlers","currentProjectId","sioConnected","pingTimer","connectRealtime","projectId","token","getAccessToken","doConnect","endpoint","getEndpoint","wsUrl","e","data","interval","parsed","eventType","eventData","event","emit","scheduleReconnect","delay","disconnectRealtime","onRealtimeEvent","type","handler","h","sendPageNavigate","pageUrl","socket","sioConnected","currentProjectId","isConnected","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","renderPins","fetchProjectMembers","pin","i","dot","color","showPinPopup","timeAgo","ts","diff","mins","hrs","statusColor","status","dotEl","closePopup","popup","commentsRes","fetchComments","comments","user","getCurrentUser","canManage","escapeHtml","c","input","body","res","createComment","commentsEl","queueOfflineAction","updatePin","deletePin","p","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","sendPageNavigate","origPush","origReplace","args","str","div","config","fab","modal","backdrop","styleEl","keyHandler","isOpen","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","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","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","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 * Zero-dependency screenshot capture.\n * Serializes the DOM into an SVG foreignObject and renders it to a canvas.\n * Falls back to getDisplayMedia (screen capture API) if SVG approach fails.\n */\n\nexport async function captureScreenshot(): Promise<string | null> {\n // Try SVG foreignObject approach first (no permission needed)\n try {\n const result = await captureSvgForeignObject();\n if (result) return result;\n } catch { /* fall through */ }\n\n // Fallback: getDisplayMedia (shows browser permission popup)\n try {\n const result = await captureDisplayMedia();\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 // Copy key visual properties\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-modal, .bs-backdrop').forEach(el => el.remove());\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.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 resolve(canvas.toDataURL('image/jpeg', 0.6));\n };\n img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };\n img.src = url;\n });\n}\n\n/** Capture via Screen Capture API — requires user permission */\nasync function captureDisplayMedia(): Promise<string | null> {\n if (!navigator.mediaDevices?.getDisplayMedia) return null;\n\n const stream = await navigator.mediaDevices.getDisplayMedia({ video: { displaySurface: 'browser' } as any });\n const track = stream.getVideoTracks()[0];\n const video = document.createElement('video');\n\n return new Promise<string | null>((resolve) => {\n video.onloadedmetadata = () => {\n video.play();\n const canvas = document.createElement('canvas');\n canvas.width = video.videoWidth * 0.5;\n canvas.height = video.videoHeight * 0.5;\n const ctx = canvas.getContext('2d');\n if (!ctx) { track.stop(); resolve(null); return; }\n ctx.scale(0.5, 0.5);\n ctx.drawImage(video, 0, 0);\n track.stop();\n resolve(canvas.toDataURL('image/jpeg', 0.6));\n };\n video.onerror = () => { track.stop(); resolve(null); };\n video.srcObject = stream;\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://api.bugstash.com';\nconst FALLBACK_ENDPOINT = 'https://bugstash-backend.azurewebsites.net';\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\n// Every theme sets these CSS custom properties.\n// The panel base styles reference them via var(--bs-xxx).\nconst THEMES: BsTheme[] = [\n // ─── 1. Midnight ─────────────────────────────────\n {\n id: 'midnight',\n name: 'Midnight',\n preview: ['#1a1d2e', '#6E9ED0'],\n vars: {\n '--bs-bg': '#1a1d2e',\n '--bs-bg2': '#222639',\n '--bs-bg3': '#2a2e42',\n '--bs-text': '#e2e5ed',\n '--bs-muted': '#7c82a0',\n '--bs-border': '#333754',\n '--bs-accent': '#6E9ED0',\n '--bs-accent2': '#8FAFD6',\n '--bs-fab1': '#6E9ED0',\n '--bs-fab2': '#8FAFD6',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 2. Deep Purple ──────────────────────────────\n {\n id: 'purple',\n name: 'Deep Purple',\n preview: ['#1c1628', '#a78bfa'],\n vars: {\n '--bs-bg': '#1c1628',\n '--bs-bg2': '#241e34',\n '--bs-bg3': '#2e2640',\n '--bs-text': '#e8e0f5',\n '--bs-muted': '#8b7faa',\n '--bs-border': '#3b3255',\n '--bs-accent': '#a78bfa',\n '--bs-accent2': '#c4b5fd',\n '--bs-fab1': '#a78bfa',\n '--bs-fab2': '#c084fc',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#fb7185',\n '--bs-green': '#6ee7b7',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 3. Cyberpunk ────────────────────────────────\n {\n id: 'cyberpunk',\n name: 'Cyberpunk',\n preview: ['#0a0a12', '#00fff0'],\n vars: {\n '--bs-bg': '#0a0a12',\n '--bs-bg2': '#12121f',\n '--bs-bg3': '#1a1a2c',\n '--bs-text': '#e0f7fa',\n '--bs-muted': '#5e7f88',\n '--bs-border': '#1e3a3f',\n '--bs-accent': '#00fff0',\n '--bs-accent2': '#00c8ff',\n '--bs-fab1': '#00fff0',\n '--bs-fab2': '#ff00c8',\n '--bs-radius': '4px',\n '--bs-radius-sm': '2px',\n '--bs-red': '#ff3860',\n '--bs-green': '#00ff88',\n '--bs-orange': '#ffaa00',\n '--bs-yellow': '#ffe600',\n },\n },\n // ─── 4. Sunset ───────────────────────────────────\n {\n id: 'sunset',\n name: 'Sunset',\n preview: ['#1f1318', '#f97316'],\n vars: {\n '--bs-bg': '#1f1318',\n '--bs-bg2': '#291a20',\n '--bs-bg3': '#33212a',\n '--bs-text': '#f5e6ea',\n '--bs-muted': '#a07880',\n '--bs-border': '#4a2a34',\n '--bs-accent': '#f97316',\n '--bs-accent2': '#fb923c',\n '--bs-fab1': '#f97316',\n '--bs-fab2': '#ef4444',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ef4444',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 5. Ocean ────────────────────────────────────\n {\n id: 'ocean',\n name: 'Ocean',\n preview: ['#0d1b2a', '#2dd4bf'],\n vars: {\n '--bs-bg': '#0d1b2a',\n '--bs-bg2': '#132638',\n '--bs-bg3': '#1a3146',\n '--bs-text': '#d6f0ee',\n '--bs-muted': '#5c8a8e',\n '--bs-border': '#1f4050',\n '--bs-accent': '#2dd4bf',\n '--bs-accent2': '#5eead4',\n '--bs-fab1': '#2dd4bf',\n '--bs-fab2': '#22d3ee',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#6ee7b7',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 6. Rose ─────────────────────────────────────\n {\n id: 'rose',\n name: 'Rose Gold',\n preview: ['#1f1520', '#f472b6'],\n vars: {\n '--bs-bg': '#1f1520',\n '--bs-bg2': '#2a1c2a',\n '--bs-bg3': '#352434',\n '--bs-text': '#f5e0ec',\n '--bs-muted': '#a07090',\n '--bs-border': '#4a2a44',\n '--bs-accent': '#f472b6',\n '--bs-accent2': '#f9a8d4',\n '--bs-fab1': '#f472b6',\n '--bs-fab2': '#e879f9',\n '--bs-radius': '20px',\n '--bs-radius-sm': '12px',\n '--bs-red': '#fb7185',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 7. Arctic (Light) ──────────────────────────\n {\n id: 'arctic',\n name: 'Arctic Light',\n preview: ['#f0f4f8', '#3b82f6'],\n vars: {\n '--bs-bg': '#f0f4f8',\n '--bs-bg2': '#e2e8f0',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#1e293b',\n '--bs-muted': '#64748b',\n '--bs-border': '#cbd5e1',\n '--bs-accent': '#3b82f6',\n '--bs-accent2': '#60a5fa',\n '--bs-fab1': '#3b82f6',\n '--bs-fab2': '#6366f1',\n '--bs-radius': '16px',\n '--bs-radius-sm': '10px',\n '--bs-red': '#ef4444',\n '--bs-green': '#22c55e',\n '--bs-orange': '#f97316',\n '--bs-yellow': '#eab308',\n },\n },\n // ─── 8. Glass ────────────────────────────────────\n {\n id: 'glass',\n name: 'Glassmorphism',\n preview: ['rgba(30,30,50,0.6)', '#a5b4fc'],\n vars: {\n '--bs-bg': 'rgba(22,22,40,0.75)',\n '--bs-bg2': 'rgba(35,35,60,0.6)',\n '--bs-bg3': 'rgba(45,45,75,0.5)',\n '--bs-text': '#e8eaff',\n '--bs-muted': '#8888bb',\n '--bs-border': 'rgba(255,255,255,0.1)',\n '--bs-accent': '#a5b4fc',\n '--bs-accent2': '#c7d2fe',\n '--bs-fab1': '#818cf8',\n '--bs-fab2': '#a78bfa',\n '--bs-radius': '20px',\n '--bs-radius-sm': '12px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 9. Neon Green ──────────────────────────────\n {\n id: 'neon',\n name: 'Neon',\n preview: ['#080c08', '#39ff14'],\n vars: {\n '--bs-bg': '#080c08',\n '--bs-bg2': '#0f150f',\n '--bs-bg3': '#161e16',\n '--bs-text': '#d0f0c0',\n '--bs-muted': '#5a7a50',\n '--bs-border': '#1e3018',\n '--bs-accent': '#39ff14',\n '--bs-accent2': '#7dff5e',\n '--bs-fab1': '#39ff14',\n '--bs-fab2': '#00ff88',\n '--bs-radius': '8px',\n '--bs-radius-sm': '4px',\n '--bs-red': '#ff4444',\n '--bs-green': '#39ff14',\n '--bs-orange': '#ffaa00',\n '--bs-yellow': '#e6ff00',\n },\n },\n // ─── 10. Forest ──────────────────────────────────\n {\n id: 'forest',\n name: 'Forest',\n preview: ['#111c15', '#34d399'],\n vars: {\n '--bs-bg': '#111c15',\n '--bs-bg2': '#18261d',\n '--bs-bg3': '#203026',\n '--bs-text': '#d1f0dd',\n '--bs-muted': '#6a9a7a',\n '--bs-border': '#2a4a33',\n '--bs-accent': '#34d399',\n '--bs-accent2': '#6ee7b7',\n '--bs-fab1': '#34d399',\n '--bs-fab2': '#2dd4bf',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 11. Minimal Dark ───────────────────────────\n {\n id: 'minimal-dark',\n name: 'Minimal Dark',\n preview: ['#18181b', '#a1a1aa'],\n vars: {\n '--bs-bg': '#18181b',\n '--bs-bg2': '#212124',\n '--bs-bg3': '#2a2a2e',\n '--bs-text': '#e4e4e7',\n '--bs-muted': '#71717a',\n '--bs-border': '#333338',\n '--bs-accent': '#a1a1aa',\n '--bs-accent2': '#d4d4d8',\n '--bs-fab1': '#52525b',\n '--bs-fab2': '#71717a',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 12. Minimal Light ──────────────────────────\n {\n id: 'minimal-light',\n name: 'Minimal Light',\n preview: ['#fafafa', '#52525b'],\n vars: {\n '--bs-bg': '#fafafa',\n '--bs-bg2': '#f0f0f0',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#18181b',\n '--bs-muted': '#71717a',\n '--bs-border': '#e4e4e7',\n '--bs-accent': '#18181b',\n '--bs-accent2': '#3f3f46',\n '--bs-fab1': '#18181b',\n '--bs-fab2': '#3f3f46',\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 // ─── 13. Dracula ─────────────────────────────────\n {\n id: 'dracula',\n name: 'Dracula',\n preview: ['#282a36', '#bd93f9'],\n vars: {\n '--bs-bg': '#282a36',\n '--bs-bg2': '#2e303e',\n '--bs-bg3': '#363848',\n '--bs-text': '#f8f8f2',\n '--bs-muted': '#6272a4',\n '--bs-border': '#44475a',\n '--bs-accent': '#bd93f9',\n '--bs-accent2': '#caa9fa',\n '--bs-fab1': '#bd93f9',\n '--bs-fab2': '#ff79c6',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#ff5555',\n '--bs-green': '#50fa7b',\n '--bs-orange': '#ffb86c',\n '--bs-yellow': '#f1fa8c',\n },\n },\n // ─── 14. Nord ────────────────────────────────────\n {\n id: 'nord',\n name: 'Nord',\n preview: ['#2e3440', '#88c0d0'],\n vars: {\n '--bs-bg': '#2e3440',\n '--bs-bg2': '#3b4252',\n '--bs-bg3': '#434c5e',\n '--bs-text': '#eceff4',\n '--bs-muted': '#7b88a1',\n '--bs-border': '#4c566a',\n '--bs-accent': '#88c0d0',\n '--bs-accent2': '#8fbcbb',\n '--bs-fab1': '#88c0d0',\n '--bs-fab2': '#81a1c1',\n '--bs-radius': '10px',\n '--bs-radius-sm': '6px',\n '--bs-red': '#bf616a',\n '--bs-green': '#a3be8c',\n '--bs-orange': '#d08770',\n '--bs-yellow': '#ebcb8b',\n },\n },\n // ─── 15. Monokai ─────────────────────────────────\n {\n id: 'monokai',\n name: 'Monokai',\n preview: ['#272822', '#a6e22e'],\n vars: {\n '--bs-bg': '#272822',\n '--bs-bg2': '#2f302a',\n '--bs-bg3': '#383930',\n '--bs-text': '#f8f8f2',\n '--bs-muted': '#75715e',\n '--bs-border': '#49483e',\n '--bs-accent': '#a6e22e',\n '--bs-accent2': '#c4f060',\n '--bs-fab1': '#a6e22e',\n '--bs-fab2': '#66d9ef',\n '--bs-radius': '8px',\n '--bs-radius-sm': '4px',\n '--bs-red': '#f92672',\n '--bs-green': '#a6e22e',\n '--bs-orange': '#fd971f',\n '--bs-yellow': '#e6db74',\n },\n },\n // ─── 16. Solarized ──────────────────────────────\n {\n id: 'solarized',\n name: 'Solarized Dark',\n preview: ['#002b36', '#268bd2'],\n vars: {\n '--bs-bg': '#002b36',\n '--bs-bg2': '#073642',\n '--bs-bg3': '#0e4050',\n '--bs-text': '#eee8d5',\n '--bs-muted': '#839496',\n '--bs-border': '#1a4f5c',\n '--bs-accent': '#268bd2',\n '--bs-accent2': '#2aa198',\n '--bs-fab1': '#268bd2',\n '--bs-fab2': '#2aa198',\n '--bs-radius': '10px',\n '--bs-radius-sm': '6px',\n '--bs-red': '#dc322f',\n '--bs-green': '#859900',\n '--bs-orange': '#cb4b16',\n '--bs-yellow': '#b58900',\n },\n },\n // ─── 17. Candy ───────────────────────────────────\n {\n id: 'candy',\n name: 'Candy',\n preview: ['#fef1f8', '#ec4899'],\n vars: {\n '--bs-bg': '#fef1f8',\n '--bs-bg2': '#fce7f3',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#4a1942',\n '--bs-muted': '#9f5090',\n '--bs-border': '#f0c6e0',\n '--bs-accent': '#ec4899',\n '--bs-accent2': '#f472b6',\n '--bs-fab1': '#ec4899',\n '--bs-fab2': '#a855f7',\n '--bs-radius': '20px',\n '--bs-radius-sm': '14px',\n '--bs-red': '#e11d48',\n '--bs-green': '#059669',\n '--bs-orange': '#ea580c',\n '--bs-yellow': '#ca8a04',\n },\n },\n // ─── 18. Slate ───────────────────────────────────\n {\n id: 'slate',\n name: 'Slate',\n preview: ['#1e2432', '#94a3b8'],\n vars: {\n '--bs-bg': '#1e2432',\n '--bs-bg2': '#263040',\n '--bs-bg3': '#2e384a',\n '--bs-text': '#e2e8f0',\n '--bs-muted': '#64748b',\n '--bs-border': '#374462',\n '--bs-accent': '#94a3b8',\n '--bs-accent2': '#cbd5e1',\n '--bs-fab1': '#475569',\n '--bs-fab2': '#64748b',\n '--bs-radius': '14px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#f87171',\n '--bs-green': '#4ade80',\n '--bs-orange': '#fb923c',\n '--bs-yellow': '#fbbf24',\n },\n },\n // ─── 19. Ember ───────────────────────────────────\n {\n id: 'ember',\n name: 'Ember',\n preview: ['#1a0f0f', '#ef4444'],\n vars: {\n '--bs-bg': '#1a0f0f',\n '--bs-bg2': '#241515',\n '--bs-bg3': '#2e1c1c',\n '--bs-text': '#fde8e8',\n '--bs-muted': '#a06060',\n '--bs-border': '#4a2222',\n '--bs-accent': '#ef4444',\n '--bs-accent2': '#f87171',\n '--bs-fab1': '#ef4444',\n '--bs-fab2': '#f97316',\n '--bs-radius': '12px',\n '--bs-radius-sm': '8px',\n '--bs-red': '#fca5a5',\n '--bs-green': '#86efac',\n '--bs-orange': '#fdba74',\n '--bs-yellow': '#fde68a',\n },\n },\n // ─── 20. Lavender ───────────────────────────────\n {\n id: 'lavender',\n name: 'Lavender',\n preview: ['#f5f0ff', '#7c3aed'],\n vars: {\n '--bs-bg': '#f5f0ff',\n '--bs-bg2': '#ede5ff',\n '--bs-bg3': '#ffffff',\n '--bs-text': '#2e1065',\n '--bs-muted': '#7c6a9a',\n '--bs-border': '#d8c8f0',\n '--bs-accent': '#7c3aed',\n '--bs-accent2': '#8b5cf6',\n '--bs-fab1': '#7c3aed',\n '--bs-fab2': '#a855f7',\n '--bs-radius': '18px',\n '--bs-radius-sm': '12px',\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 // 1\n { id: 'classic', name: 'Classic Center', description: 'Centered modal, top tabs', tabPosition: 'top' },\n // 2\n { id: 'drawer-right', name: 'Right Drawer', description: 'Slides in from the right', tabPosition: 'top' },\n // 3\n { id: 'drawer-left', name: 'Left Drawer', description: 'Slides in from the left', tabPosition: 'top' },\n // 4\n { id: 'bottom-sheet', name: 'Bottom Sheet', description: 'Slides up from the bottom', tabPosition: 'top' },\n // 5\n { id: 'top-bar', name: 'Top Drop', description: 'Drops down from the top', tabPosition: 'top' },\n // 6\n { id: 'compact', name: 'Compact', description: 'Small centered popup', tabPosition: 'top' },\n // 7\n { id: 'wide', name: 'Wide', description: 'Wide horizontal modal', tabPosition: 'top' },\n // 8\n { id: 'fullscreen', name: 'Fullscreen', description: 'Full screen overlay', tabPosition: 'top' },\n // 9\n { id: 'corner-br', name: 'Corner Card', description: 'Bottom-right corner card', tabPosition: 'top' },\n // 10\n { id: 'corner-bl', name: 'Corner Left', description: 'Bottom-left corner card', tabPosition: 'top' },\n // 11\n { id: 'pill-tabs', name: 'Pill Tabs', description: 'Centered with pill-style tabs', tabPosition: 'top' },\n // 12\n { id: 'sidebar-tabs', name: 'Sidebar Tabs', description: 'Vertical tabs on the left', tabPosition: 'left' },\n // 13\n { id: 'segmented', name: 'Segmented', description: 'Tabs as segmented control', tabPosition: 'top' },\n // 14\n { id: 'minimal', name: 'Minimal', description: 'Ultra clean, spacious', tabPosition: 'top' },\n // 15\n { id: 'dense', name: 'Dense', description: 'Compact, tight spacing', tabPosition: 'top' },\n // 16\n { id: 'rounded', name: 'Bubble', description: 'Extra rounded, playful', tabPosition: 'top' },\n // 17\n { id: 'sharp', name: 'Sharp', description: 'Square corners, industrial', tabPosition: 'top' },\n // 18\n { id: 'split', name: 'Split View', description: 'Two-column layout', tabPosition: 'left' },\n // 19\n { id: 'floating', name: 'Floating', description: 'Heavy shadow, borderless', tabPosition: 'top' },\n // 20\n { id: 'bottom-tabs', name: 'Bottom Tabs', description: 'Tabs at the bottom', tabPosition: 'bottom' },\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// Each layout overrides the base .bs-modal / .bs-tabs etc.\n// Applied via a class on the modal: .bs-ly-{id}\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. Drawer Left ── */\n.bs-ly-drawer-left.bs-modal {\n top: 0; left: 0; right: auto; 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-left.bs-modal.bs-in {\n transform: translateX(0);\n opacity: 1;\n}\n\n/* ── 4. 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/* ── 5. Top Drop ── */\n.bs-ly-top-bar.bs-modal {\n top: 0; left: 50%; bottom: auto;\n width: 700px; max-width: 100vw;\n max-height: 75vh;\n border-radius: 0 0 var(--bs-radius) var(--bs-radius);\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-top-bar.bs-modal.bs-in {\n transform: translate(-50%, 0);\n opacity: 1;\n}\n\n/* ── 6. Compact ── */\n.bs-ly-compact.bs-modal {\n width: 380px;\n}\n.bs-ly-compact .bs-scroll { padding: 12px 16px 16px; }\n.bs-ly-compact .bs-hdr { padding: 14px 16px 0; }\n.bs-ly-compact .bs-tabs { padding: 8px 16px 0; }\n.bs-ly-compact .bs-tab { padding: 7px 10px; font-size: 11px; }\n.bs-ly-compact .bs-field { margin-bottom: 10px; }\n.bs-ly-compact .bs-input, .bs-ly-compact .bs-textarea { padding: 8px 10px; font-size: 13px; }\n.bs-ly-compact .bs-submit-btn { padding: 10px; font-size: 13px; }\n\n/* ── 7. Wide ── */\n.bs-ly-wide.bs-modal {\n width: 720px;\n}\n.bs-ly-wide .bs-scroll { padding: 20px 32px 28px; }\n.bs-ly-wide .bs-hdr { padding: 22px 32px 0; }\n.bs-ly-wide .bs-tabs { padding: 14px 32px 0; }\n\n/* ── 8. Fullscreen ── */\n.bs-ly-fullscreen.bs-modal {\n top: 0; left: 0; width: 100vw; max-width: 100vw;\n height: 100vh; max-height: 100vh;\n border-radius: 0;\n transform: scale(0.95);\n transition: transform 0.35s cubic-bezier(0.22,1,0.36,1), opacity 0.3s ease;\n}\n.bs-ly-fullscreen.bs-modal.bs-in {\n transform: scale(1);\n opacity: 1;\n}\n.bs-ly-fullscreen .bs-scroll { padding: 24px 15%; }\n.bs-ly-fullscreen .bs-hdr { padding: 24px 15% 0; }\n.bs-ly-fullscreen .bs-tabs { padding: 16px 15% 0; }\n\n/* ── 9. Corner Bottom-Right ── */\n.bs-ly-corner-br.bs-modal {\n top: auto; left: auto; right: 24px; bottom: 88px;\n width: 400px;\n max-height: 70vh;\n transform: translateY(20px) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease;\n}\n.bs-ly-corner-br.bs-modal.bs-in {\n transform: translateY(0) scale(1);\n opacity: 1;\n}\n\n/* ── 10. Corner Bottom-Left ── */\n.bs-ly-corner-bl.bs-modal {\n top: auto; left: 24px; right: auto; bottom: 88px;\n width: 400px;\n max-height: 70vh;\n transform: translateY(20px) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease;\n}\n.bs-ly-corner-bl.bs-modal.bs-in {\n transform: translateY(0) scale(1);\n opacity: 1;\n}\n\n/* ── 11. Pill Tabs ── */\n.bs-ly-pill-tabs .bs-tabs {\n background: var(--bs-bg2);\n margin: 12px 22px 0;\n border-radius: 999px;\n padding: 4px;\n gap: 4px;\n}\n.bs-ly-pill-tabs .bs-tab {\n border-radius: 999px;\n padding: 8px 14px;\n justify-content: center;\n flex: 1;\n}\n.bs-ly-pill-tabs .bs-tab.bs-active {\n background: var(--bs-accent);\n color: #fff;\n}\n.bs-ly-pill-tabs .bs-tab.bs-active::after { display: none; }\n.bs-ly-pill-tabs .bs-tab.bs-active .bs-tab-badge { background: rgba(255,255,255,0.25); color: #fff; }\n.bs-ly-pill-tabs .bs-tab-divider { display: none; }\n\n/* ── 12. 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/* ── 13. Segmented ── */\n.bs-ly-segmented .bs-tabs {\n background: var(--bs-bg2);\n margin: 12px 22px 0;\n border-radius: var(--bs-radius-sm);\n padding: 3px;\n gap: 3px;\n border: 1px solid var(--bs-border);\n}\n.bs-ly-segmented .bs-tab {\n border-radius: calc(var(--bs-radius-sm) - 2px);\n padding: 8px 12px;\n justify-content: center;\n flex: 1;\n font-size: 11px;\n}\n.bs-ly-segmented .bs-tab.bs-active { background: var(--bs-bg); box-shadow: 0 1px 3px rgba(0,0,0,0.2); }\n.bs-ly-segmented .bs-tab.bs-active::after { display: none; }\n.bs-ly-segmented .bs-tab-divider { display: none; }\n\n/* ── 14. Minimal ── */\n.bs-ly-minimal.bs-modal {\n border: none;\n box-shadow: 0 40px 100px rgba(0,0,0,0.5);\n}\n.bs-ly-minimal .bs-hdr { padding: 28px 32px 0; }\n.bs-ly-minimal .bs-tabs { padding: 16px 32px 0; }\n.bs-ly-minimal .bs-scroll { padding: 24px 32px 32px; }\n.bs-ly-minimal .bs-field { margin-bottom: 22px; }\n.bs-ly-minimal .bs-input, .bs-ly-minimal .bs-textarea {\n border-color: transparent;\n background: var(--bs-bg2);\n}\n.bs-ly-minimal .bs-input:focus, .bs-ly-minimal .bs-textarea:focus { border-color: var(--bs-accent); }\n.bs-ly-minimal .bs-tab { font-weight: 400; letter-spacing: 0.5px; }\n.bs-ly-minimal .bs-tab.bs-active { font-weight: 700; }\n\n/* ── 15. Dense ── */\n.bs-ly-dense.bs-modal { width: 480px; }\n.bs-ly-dense .bs-hdr { padding: 10px 14px 0; }\n.bs-ly-dense .bs-logo { font-size: 14px; }\n.bs-ly-dense .bs-tabs { padding: 6px 14px 0; }\n.bs-ly-dense .bs-tab { padding: 6px 8px; font-size: 10px; gap: 4px; }\n.bs-ly-dense .bs-tab svg { width: 12px; height: 12px; }\n.bs-ly-dense .bs-tab-divider { margin: 0; }\n.bs-ly-dense .bs-scroll { padding: 10px 14px 14px; }\n.bs-ly-dense .bs-field { margin-bottom: 8px; }\n.bs-ly-dense .bs-field-label { font-size: 11px; margin-bottom: 4px; }\n.bs-ly-dense .bs-input, .bs-ly-dense .bs-textarea { padding: 7px 10px; font-size: 12px; }\n.bs-ly-dense .bs-textarea { min-height: 50px; }\n.bs-ly-dense .bs-sev-btn { padding: 6px 0; font-size: 10px; }\n.bs-ly-dense .bs-shot-area { padding: 8px 10px; }\n.bs-ly-dense .bs-submit-btn { padding: 10px; font-size: 13px; }\n\n/* ── 16. Bubble / Rounded ── */\n.bs-ly-rounded.bs-modal { border-radius: 28px; }\n.bs-ly-rounded .bs-hdr { padding: 22px 26px 0; }\n.bs-ly-rounded .bs-tabs { padding: 14px 26px 0; }\n.bs-ly-rounded .bs-tab { border-radius: 16px 16px 0 0; }\n.bs-ly-rounded .bs-scroll { padding: 18px 26px 26px; }\n.bs-ly-rounded .bs-input, .bs-ly-rounded .bs-textarea { border-radius: 16px; }\n.bs-ly-rounded .bs-sev-btn { border-radius: 16px; }\n.bs-ly-rounded .bs-submit-btn { border-radius: 20px; }\n.bs-ly-rounded .bs-shot-area { border-radius: 18px; }\n.bs-ly-rounded .bs-log, .bs-ly-rounded .bs-net { border-radius: 14px; }\n.bs-ly-rounded .bs-err-card { border-radius: 16px; }\n\n/* ── 17. Sharp ── */\n.bs-ly-sharp.bs-modal { border-radius: 0; }\n.bs-ly-sharp .bs-tab { border-radius: 0; }\n.bs-ly-sharp .bs-tab.bs-active::after { border-radius: 0; }\n.bs-ly-sharp .bs-input, .bs-ly-sharp .bs-textarea { border-radius: 0; }\n.bs-ly-sharp .bs-sev-btn { border-radius: 0; }\n.bs-ly-sharp .bs-submit-btn { border-radius: 0; }\n.bs-ly-sharp .bs-shot-area { border-radius: 0; }\n.bs-ly-sharp .bs-log, .bs-ly-sharp .bs-net { border-radius: 0; }\n.bs-ly-sharp .bs-err-card { border-radius: 0; }\n.bs-ly-sharp .bs-msg { border-radius: 0; }\n.bs-ly-sharp .bs-ann-wrap { border-radius: 0; }\n.bs-ly-sharp .bs-fab { border-radius: 0; }\n\n/* ── 18. Split View ── */\n.bs-ly-split.bs-modal {\n width: 700px;\n}\n.bs-ly-split .bs-body-wrap {\n display: flex;\n flex: 1;\n overflow: hidden;\n}\n.bs-ly-split .bs-tabs {\n flex-direction: column;\n padding: 16px 0 16px 16px;\n gap: 6px;\n min-width: 160px;\n border-right: 1px solid var(--bs-border);\n overflow-y: auto;\n}\n.bs-ly-split .bs-tab {\n border-radius: var(--bs-radius-sm);\n padding: 12px 14px;\n width: 100%;\n font-size: 13px;\n}\n.bs-ly-split .bs-tab.bs-active { background: var(--bs-accent); color: #fff; }\n.bs-ly-split .bs-tab.bs-active::after { display: none; }\n.bs-ly-split .bs-tab.bs-active .bs-tab-badge { background: rgba(255,255,255,0.25); color: #fff; }\n.bs-ly-split .bs-tab-divider { display: none; }\n.bs-ly-split .bs-scroll { flex: 1; }\n\n/* ── 19. Floating ── */\n.bs-ly-floating.bs-modal {\n border: none;\n box-shadow: 0 50px 120px rgba(0,0,0,0.7), 0 20px 50px rgba(0,0,0,0.4);\n border-radius: 24px;\n}\n.bs-ly-floating .bs-hdr { padding: 22px 26px 0; }\n.bs-ly-floating .bs-tabs {\n padding: 14px 26px 0;\n background: transparent;\n}\n.bs-ly-floating .bs-tab {\n background: var(--bs-bg2);\n border-radius: var(--bs-radius-sm);\n margin-right: 4px;\n}\n.bs-ly-floating .bs-tab.bs-active {\n background: var(--bs-bg3);\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n}\n.bs-ly-floating .bs-tab.bs-active::after { display: none; }\n.bs-ly-floating .bs-tab-divider { display: none; }\n.bs-ly-floating .bs-scroll { padding: 18px 26px 26px; }\n\n/* ── 20. Bottom Tabs ── */\n.bs-ly-bottom-tabs .bs-tabs {\n order: 99;\n padding: 0 22px 12px;\n border-top: 1px solid var(--bs-border);\n border-bottom: none;\n background: var(--bs-bg);\n}\n.bs-ly-bottom-tabs .bs-tab {\n border-radius: 0 0 var(--bs-radius-sm) var(--bs-radius-sm);\n flex: 1;\n justify-content: center;\n padding: 12px 8px;\n}\n.bs-ly-bottom-tabs .bs-tab.bs-active::after {\n top: 0; bottom: auto;\n border-radius: 0 0 2px 2px;\n}\n.bs-ly-bottom-tabs .bs-tab-divider { order: 98; }\n.bs-ly-bottom-tabs .bs-scroll { order: 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 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 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};\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 /* ── 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 .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 }[] = [\n { id: 'ui', label: 'UI Bug' },\n { id: 'functionality', label: 'Broken Feature' },\n { id: 'performance', label: 'Slow / Laggy' },\n { id: 'crash', label: 'Crash' },\n { id: 'security', label: 'Security' },\n { id: 'other', label: 'Other' },\n ];\n\n return `<div class=\"bs-view\">\n <form data-bs-form>\n <div class=\"bs-ctx-bar\">\n <div class=\"bs-ctx-chip${d.counts.logs ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.logs}</span><span class=\"bs-ctx-l\">Logs</span></div>\n <div class=\"bs-ctx-chip${d.counts.failedNet ? ' bs-alert' : d.counts.network ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.network}</span><span class=\"bs-ctx-l\">Network</span></div>\n <div class=\"bs-ctx-chip${d.counts.errors ? ' bs-alert' : ''}\"><span class=\"bs-ctx-n\">${d.counts.errors}</span><span class=\"bs-ctx-l\">Errors</span></div>\n <div class=\"bs-ctx-chip${d.counts.crumbs ? ' bs-has' : ''}\"><span class=\"bs-ctx-n\">${d.counts.crumbs}</span><span class=\"bs-ctx-l\">Actions</span></div>\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Bug title <span class=\"bs-field-hint\">(required)</span></div>\n <input class=\"bs-input\" name=\"title\" placeholder=\"Short summary — e.g. Checkout button unresponsive\" required autocomplete=\"off\" />\n </div>\n <div class=\"bs-field\">\n <div class=\"bs-field-label\">Description</div>\n <textarea class=\"bs-textarea\" name=\"description\" placeholder=\"What were you doing? What went wrong?\"></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 <span class=\"bs-field-hint\">(suggested: ${d.severity})</span></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\">Medium</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>Captures & lets you 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\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 = `\n <div class=\"bs-hdr\">\n <div class=\"bs-logo\">BugStash</div>\n <div class=\"bs-hdr-right\">\n ${user ? `\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 ` : ''}\n <button class=\"bs-close-btn\" data-bs-close title=\"Close\">${I.x}</button>\n </div>\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}\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 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[cfg.panelPosition === 'bottom-left' ? 'left' : 'right'] = '24px';\n fab.addEventListener('click', () => (isOpen ? close() : open()));\n document.body.appendChild(fab);\n\n keyHandler = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'B') {\n e.preventDefault();\n isOpen ? close() : open();\n }\n };\n document.addEventListener('keydown', keyHandler);\n}\n\nexport function destroyPanel() {\n close();\n fab?.remove();\n fab = null;\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":"AAEA,IAAIA,GAAuB,CAAC,EACxBC,GAAY,GACZC,GAAiD,KACjDC,GAA4C,KAC5CC,GAAuC,KACvCC,GAAmC,KAEvC,SAASC,GAAYC,EAAqB,CACxC,GAAIA,EAAG,GAAI,MAAO,IAAIA,EAAG,EAAE,GAC3B,IAAMC,EAAMD,EAAG,QAAQ,YAAY,EAC7BE,EAAMF,EAAG,WAAa,OAAOA,EAAG,WAAc,SAChD,IAAMA,EAAG,UAAU,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,EAAG,CAAC,EAAE,KAAK,GAAG,EAC3D,GACEG,GAAQH,EAAG,aAAe,IAAI,KAAK,EAAE,MAAM,EAAG,EAAE,EAChDI,EAAQD,EAAO,KAAKA,CAAI,IAAM,GACpC,MAAO,GAAGF,CAAG,GAAGC,CAAG,GAAGE,CAAK,EAC7B,CAEO,SAASC,EAAcC,EAAmB,CAC/Cb,GAAO,KAAKa,CAAK,EACbb,GAAO,OAASC,IAAWD,GAAO,MAAM,CAC9C,CAEO,SAASc,GAAgBC,EAAc,CACxCA,IAAKd,GAAYc,GAGrBb,GAAgBc,GAAkB,CAChC,IAAMC,EAASD,EAAE,OACb,CAACC,GAAU,CAACA,EAAO,SACvBL,EAAc,CACZ,KAAM,QACN,SAAU,KACV,QAAS,WAAWN,GAAYW,CAAM,CAAC,GACvC,UAAW,KAAK,IAAI,EACpB,KAAM,CAAE,EAAGD,EAAE,QAAS,EAAGA,EAAE,QAAS,SAAUV,GAAYW,CAAM,CAAE,CACpE,CAAC,CACH,EACA,SAAS,iBAAiB,QAASf,GAAc,EAAI,EAGrD,IAAMgB,EAAc,IAAI,QACxBf,GAAgBa,GAAa,CAC3B,IAAMC,EAASD,EAAE,OACjB,GAAI,CAACC,GAAU,CAACA,EAAO,QAAS,OAChC,IAAMT,EAAMS,EAAO,QAAQ,YAAY,EACvC,GAAIT,IAAQ,SAAWA,IAAQ,YAAcA,IAAQ,SAAU,OAG/D,IAAMW,EAAWD,EAAY,IAAID,CAAM,EACnCE,GAAU,aAAaA,CAAQ,EACnCD,EAAY,IACVD,EACA,OAAO,WAAW,IAAM,CACtB,IAAMG,EAAaH,aAAkB,kBAAoBA,EAAO,OAAS,WACzEL,EAAc,CACZ,KAAM,QACN,SAAU,KACV,QAAS,SAASN,GAAYW,CAAM,CAAC,GACrC,UAAW,KAAK,IAAI,EACpB,KAAM,CACJ,SAAUX,GAAYW,CAAM,EAC5B,MAAOG,EAAa,aAAe,MACrC,CACF,CAAC,CACH,EAAG,GAAG,CACR,CACF,EACA,SAAS,iBAAiB,QAASjB,GAAc,EAAI,EAGrDC,GAAkB,IAAM,CACtBQ,EAAc,CACZ,KAAM,aACN,SAAU,aACV,QAAS,gBAAgB,OAAO,SAAS,QAAQ,GACjD,UAAW,KAAK,IAAI,EACpB,KAAM,CAAE,IAAK,OAAO,SAAS,IAAK,CACpC,CAAC,CACH,EACA,OAAO,iBAAiB,WAAYR,EAAe,EAEnDC,GAAc,IAAM,CAClBO,EAAc,CACZ,KAAM,aACN,SAAU,aACV,QAAS,mBAAmB,OAAO,SAAS,IAAI,GAChD,UAAW,KAAK,IAAI,EACpB,KAAM,CAAE,IAAK,OAAO,SAAS,IAAK,CACpC,CAAC,CACH,EACA,OAAO,iBAAiB,aAAcP,EAAW,EAGjDO,EAAc,CACZ,KAAM,aACN,SAAU,aACV,QAAS,gBAAgB,OAAO,SAAS,QAAQ,GACjD,UAAW,KAAK,IAAI,EACpB,KAAM,CAAE,IAAK,OAAO,SAAS,IAAK,CACpC,CAAC,CACH,CAEO,SAASS,IAA+B,CAC7C,MAAO,CAAC,GAAGrB,EAAM,CACnB,CAEO,SAASsB,IAAmB,CACjCtB,GAAS,CAAC,CACZ,CAEO,SAASuB,IAAqB,CAC/BrB,IAAc,SAAS,oBAAoB,QAASA,GAAc,EAAI,EACtEC,IAAc,SAAS,oBAAoB,QAASA,GAAc,EAAI,EACtEC,IAAiB,OAAO,oBAAoB,WAAYA,EAAe,EACvEC,IAAa,OAAO,oBAAoB,aAAcA,EAAW,EACrEH,GAAe,KACfC,GAAe,KACfC,GAAkB,KAClBC,GAAc,IAChB,CCrHA,IAAMmB,GAAqB,aAGrBC,GAA6D,CAEjE,CAAC,2BAA4B,eAAe,EAE5C,CAAC,yBAA0B,gBAAgB,EAI3C,CAAC,kCAAmC,yBAAyB,EAE7D,CAAC,wDAAyD,gBAAgB,EAE1E,CAAC,kHAAoHC,GAAU,CAC7H,IAAMC,EAAQD,EAAM,OAAO,MAAM,EACjC,OAAOA,EAAM,MAAM,EAAGC,EAAQ,CAAC,EAAI,IAAMH,EAC3C,CAAC,EAED,CAAC,oBAAqB,oBAAoB,EAE1C,CAAC,wGAA0GE,GAAU,CACnH,IAAME,EAAWF,EAAM,QAAQ,GAAG,EAClC,OAAOA,EAAM,MAAM,EAAGE,EAAW,CAAC,EAAI,KAAOJ,GAAqB,GACpE,CAAC,CACH,EAcO,SAASK,GAAaC,EAAuB,CAClD,IAAIC,EAASD,EACb,OAAW,CAACE,EAASC,CAAW,IAAKC,GAEjCH,EAASA,EAAO,QAAQC,EAASC,CAAkB,EAKvD,OAAOF,CACT,CAiBO,SAASI,GAAcC,EAA0B,CACtD,OAAOA,EAAK,IAAIC,EAAY,CAC9B,CAGO,SAASC,GAAaC,EAAe,CAC1C,GAAI,OAAOA,GAAQ,SAAU,OAAOF,GAAaE,CAAG,EACpD,GAAI,MAAM,QAAQA,CAAG,EAAG,OAAOA,EAAI,IAAID,EAAY,EACnD,GAAIC,GAAO,OAAOA,GAAQ,SAAU,CAClC,IAAMC,EAAc,CAAC,EACrB,OAAW,CAACC,EAAKC,CAAK,IAAK,OAAO,QAAQH,CAAG,EAAG,CAC9C,IAAMI,EAAKF,EAAI,YAAY,EACvBE,EAAG,SAAS,UAAU,GAAKA,EAAG,SAAS,QAAQ,GAAKA,EAAG,SAAS,OAAO,GACvEA,EAAG,SAAS,QAAQ,GAAKA,EAAG,SAAS,SAAS,GAAKA,EAAG,SAAS,SAAS,EAC1EH,EAAOC,CAAG,EAAIG,GAEdJ,EAAOC,CAAG,EAAIH,GAAaI,CAAK,CAEpC,CACA,OAAOF,CACT,CACA,OAAOD,CACT,CC1FA,IAAMM,GAAY,CAChB,IAAK,QAAQ,IACb,KAAM,QAAQ,KACd,MAAO,QAAQ,MACf,MAAO,QAAQ,MACf,KAAM,QAAQ,IAChB,EAEIC,GAAmB,CAAC,EACpBC,GAAU,GAEd,SAASC,GAAUC,EAAuB,CACxC,OAAOA,EAAK,IAAKC,GAAM,CACrB,GAAIA,aAAa,MAAO,MAAO,GAAGA,EAAE,IAAI,KAAKA,EAAE,OAAO;AAAA,EAAKA,EAAE,OAAS,EAAE,GACxE,GAAI,OAAOA,GAAM,SACf,GAAI,CACF,OAAO,KAAK,UAAUA,EAAG,KAAM,CAAC,CAClC,MAAQ,CACN,OAAO,OAAOA,CAAC,CACjB,CAEF,OAAO,OAAOA,CAAC,CACjB,CAAC,CACH,CAEA,SAASC,GAAQC,EAA0BH,EAAa,CACtD,IAAMI,EAAkB,CACtB,MAAAD,EACA,KAAME,GAAcN,GAAUC,CAAI,CAAC,EACnC,UAAW,KAAK,IAAI,CACtB,EACIG,IAAU,UACZC,EAAM,MAAQ,IAAI,MAAM,EAAE,OAAO,MAAM;AAAA,CAAI,EAAE,MAAM,CAAC,EAAE,KAAK;AAAA,CAAI,GAEjEP,GAAK,KAAKO,CAAK,EACXP,GAAK,OAASC,IAASD,GAAK,MAAM,EAEtCS,EAAc,CACZ,KAAM,UACN,SAAU,WAAWH,CAAK,GAC1B,QAASC,EAAM,KAAK,KAAK,GAAG,EAAE,MAAM,EAAG,GAAG,EAC1C,UAAWA,EAAM,SACnB,CAAC,CACH,CAEO,SAASG,GAAWC,EAAc,CACnCA,IAAKV,GAAUU,GAEnB,QAAWL,KAAS,OAAO,KAAKP,EAAS,EACvC,QAAQO,CAAK,EAAI,YAAaH,EAAa,CACzCE,GAAQC,EAAOH,CAAI,EACnBJ,GAAUO,CAAK,EAAE,MAAM,QAASH,CAAI,CACtC,CAEJ,CAEO,SAASS,GAAsB,CACpC,MAAO,CAAC,GAAGZ,EAAI,CACjB,CAEO,SAASa,IAAY,CAC1Bb,GAAO,CAAC,CACV,CAEO,SAASc,IAAiB,CAC/B,QAAWR,KAAS,OAAO,KAAKP,EAAS,EACvC,QAAQO,CAAK,EAAIP,GAAUO,CAAK,CAEpC,CCpEA,IAAIS,GAA2B,CAAC,EAC5BC,GAAc,GACdC,GACAC,GACAC,GAEJ,SAASC,GAAOC,EAAqB,CACnCN,GAAS,KAAKM,CAAK,EACfN,GAAS,OAASC,IAAaD,GAAS,MAAM,EAElDO,EAAc,CACZ,KAAM,UACN,SAAUD,EAAM,OAAS,gBAAkB,aAC3C,QAAS,GAAGA,EAAM,MAAM,IAAIA,EAAM,GAAG,WAAMA,EAAM,MAAM,KAAKA,EAAM,QAAQ,MAC1E,UAAWA,EAAM,UACjB,KAAM,CAAE,OAAQA,EAAM,OAAQ,SAAUA,EAAM,QAAS,CACzD,CAAC,CACH,CAEA,SAASE,GAAWC,EAAqB,CACvC,GAAI,CACF,IAAMC,EAAI,IAAI,IAAID,EAAK,OAAO,SAAS,MAAM,EAEvCE,EAAS,IAAI,gBAAgBD,EAAE,MAAM,EAC3C,QAAWE,KAAOD,EAAO,KAAK,EAAG,CAC/B,IAAME,EAAKD,EAAI,YAAY,GACvBC,EAAG,SAAS,OAAO,GAAKA,EAAG,SAAS,KAAK,GAAKA,EAAG,SAAS,QAAQ,GAAKA,EAAG,SAAS,UAAU,GAAKA,EAAG,SAAS,MAAM,IACtHF,EAAO,IAAIC,EAAK,YAAY,CAEhC,CACA,IAAME,EAAKH,EAAO,SAAS,EAC3B,OAAOD,EAAE,UAAYI,EAAK,IAAMA,EAAK,GACvC,MAAQ,CACN,OAAOC,GAAaN,CAAG,CACzB,CACF,CAEA,SAASO,IAAa,CACpBd,GAAgB,OAAO,MAEvB,OAAO,MAAQ,eAAgBe,EAAYC,EAAY,CACrD,IAAMC,EAASD,GAAM,QAAQ,YAAY,GAAK,MACxCE,EAAS,OAAOH,GAAU,SAAWA,EAAQA,aAAiB,IAAMA,EAAM,KAAOA,EAAM,IACvFR,EAAMD,GAAWY,CAAM,EACvBC,EAAQ,KAAK,IAAI,EAEvB,GAAI,CACF,IAAMC,EAAW,MAAMpB,GAAc,KAAK,OAAQe,EAAOC,CAAI,EAC7D,OAAAb,GAAO,CACL,OAAAc,EACA,IAAAV,EACA,OAAQa,EAAS,OACjB,WAAYA,EAAS,WACrB,SAAU,KAAK,IAAI,EAAID,EACvB,aAAcC,EAAS,QAAQ,IAAI,cAAc,GAAK,OACtD,UAAWD,EACX,OAAQC,EAAS,QAAU,GAC7B,CAAC,EACMA,CACT,OAASC,EAAK,CACZ,MAAAlB,GAAO,CACL,OAAAc,EACA,IAAAV,EACA,OAAQ,EACR,WAAY,gBACZ,SAAU,KAAK,IAAI,EAAIY,EACvB,UAAWA,EACX,OAAQ,EACV,CAAC,EACKE,CACR,CACF,CACF,CAEA,SAASC,IAAW,CAClBrB,GAAkB,eAAe,UAAU,KAC3CC,GAAkB,eAAe,UAAU,KAE3C,eAAe,UAAU,KAAO,SAAUe,EAAgBV,KAAsBgB,EAAa,CAC3F,OAAC,KAAa,YAAcN,EAAO,YAAY,EAC9C,KAAa,SAAWX,GAAW,OAAOC,GAAQ,SAAWA,EAAMA,EAAI,IAAI,EACrEN,GAAgB,MAAM,KAAM,CAACgB,EAAQV,EAAK,GAAGgB,CAAI,CAAQ,CAClE,EAEA,eAAe,UAAU,KAAO,SAAUC,EAAY,CACpD,IAAML,EAAQ,KAAK,IAAI,EAEvB,YAAK,iBAAiB,UAAW,UAAY,CAC3ChB,GAAO,CACL,OAAS,KAAa,aAAe,MACrC,IAAM,KAAa,UAAY,GAC/B,OAAQ,KAAK,OACb,WAAY,KAAK,WACjB,SAAU,KAAK,IAAI,EAAIgB,EACvB,aAAc,KAAK,kBAAkB,cAAc,GAAK,OACxD,UAAWA,EACX,OAAQ,KAAK,QAAU,KAAO,KAAK,SAAW,CAChD,CAAC,CACH,CAAC,EAEMjB,GAAgB,KAAK,KAAMsB,CAAI,CACxC,CACF,CAEO,SAASC,GAAYC,EAAc,CACpCA,IAAK3B,GAAc2B,GACvBZ,GAAW,EACXQ,GAAS,CACX,CAEO,SAASK,IAAqC,CACnD,MAAO,CAAC,GAAG7B,EAAQ,CACrB,CAEO,SAAS8B,IAA2C,CACzD,OAAO9B,GAAS,OAAQ+B,GAAMA,EAAE,MAAM,CACxC,CAEO,SAASC,IAAuB,CACrChC,GAAW,CAAC,CACd,CAEO,SAASiC,IAAiB,CAC3B/B,KAAe,OAAO,MAAQA,IAC9BC,KAAiB,eAAe,UAAU,KAAOA,IACjDC,KAAiB,eAAe,UAAU,KAAOA,GACvD,CC/HA,IAAI8B,GAAuB,CAAC,EACxBC,GAAmD,KACnDC,GAAkE,KAE/D,SAASC,IAAa,CAC3BF,GAAkBG,GAAsB,CACtC,IAAMC,EAAoB,CACxB,QAASD,EAAM,SAAW,gBAC1B,OAAQA,EAAM,SACd,OAAQA,EAAM,OACd,MAAOA,EAAM,MACb,MAAOA,EAAM,OAAO,MACpB,KAAM,QACN,UAAW,KAAK,IAAI,CACtB,EACAJ,GAAO,KAAKK,CAAK,EACjBC,EAAc,CACZ,KAAM,QACN,SAAU,YACV,QAASD,EAAM,QACf,UAAWA,EAAM,UACjB,KAAM,CAAE,OAAQA,EAAM,OAAQ,OAAQA,EAAM,MAAO,CACrD,CAAC,CACH,EAEAH,GAAsBE,GAAiC,CACrD,IAAMG,EAASH,EAAM,OACfI,EACJD,aAAkB,MAAQA,EAAO,QAAU,OAAOA,GAAW,SAAWA,EAAS,8BAC7EF,EAAoB,CACxB,QAAAG,EACA,MAAOD,aAAkB,MAAQA,EAAO,MAAQ,OAChD,KAAM,qBACN,UAAW,KAAK,IAAI,CACtB,EACAP,GAAO,KAAKK,CAAK,EACjBC,EAAc,CACZ,KAAM,QACN,SAAU,UACV,QAAAE,EACA,UAAWH,EAAM,SACnB,CAAC,CACH,EAEA,OAAO,iBAAiB,QAASJ,EAAc,EAC/C,OAAO,iBAAiB,qBAAsBC,EAAkB,CAClE,CAEO,SAASO,IAA0B,CACxC,MAAO,CAAC,GAAGT,EAAM,CACnB,CAEO,SAASU,IAAc,CAC5BV,GAAS,CAAC,CACZ,CAEO,SAASW,IAAgB,CAC1BV,IAAgB,OAAO,oBAAoB,QAASA,EAAc,EAClEC,IAAoB,OAAO,oBAAoB,qBAAsBA,EAAkB,EAC3FD,GAAiB,KACjBC,GAAqB,IACvB,CC9DA,IAAIU,EAAqC,KACrCC,GAA0C,KAC1CC,GAA0C,KAC1CC,GAA0C,KAEvC,SAASC,IAAkB,CAIhC,GAHAJ,EAAU,CAAE,UAAW,KAAK,IAAI,CAAE,EAG9B,YAAY,iBAAkB,CAChC,IAAMK,EAAS,IAAM,CACnB,GAAM,CAACC,CAAG,EAAI,YAAY,iBAAiB,YAAY,EACnDA,GAAON,IACTA,EAAQ,aAAe,KAAK,MAAMM,EAAI,aAAeA,EAAI,SAAS,EAClEN,EAAQ,iBAAmB,KAAK,MAAMM,EAAI,yBAA2BA,EAAI,SAAS,GAIpF,IAAMC,EAAS,YAAY,iBAAiB,OAAO,EACnD,QAAWC,KAAKD,EACVC,EAAE,OAAS,eAAiBR,IAASA,EAAQ,WAAa,KAAK,MAAMQ,EAAE,SAAS,GAChFA,EAAE,OAAS,0BAA4BR,IAASA,EAAQ,qBAAuB,KAAK,MAAMQ,EAAE,SAAS,GAIvGR,IACFA,EAAQ,cAAgB,YAAY,iBAAiB,UAAU,EAAE,QAInE,IAAMS,EAAO,YAAoB,OAC7BA,GAAOT,IACTA,EAAQ,YAAc,CACpB,eAAgBS,EAAI,eACpB,gBAAiBA,EAAI,eACvB,EAEJ,EAEI,SAAS,aAAe,WAC1B,WAAWJ,EAAQ,CAAC,EAEpB,OAAO,iBAAiB,OAAQ,IAAM,WAAWA,EAAQ,GAAG,CAAC,CAEjE,CAGA,GAAI,OAAO,oBAAwB,IAAa,CAC9C,GAAI,CACFJ,GAAc,IAAI,oBAAqBS,GAAS,CAC9C,IAAMC,EAAUD,EAAK,WAAW,EAC1BE,EAAOD,EAAQA,EAAQ,OAAS,CAAC,EACnCC,GAAQZ,IAASA,EAAQ,uBAAyB,KAAK,MAAMY,EAAK,SAAS,EACjF,CAAC,EACDX,GAAY,QAAQ,CAAE,KAAM,2BAA4B,SAAU,EAAK,CAAC,CAC1E,MAAQ,CAAC,CAGT,GAAI,CACF,IAAIY,EAAW,EACfX,GAAc,IAAI,oBAAqBQ,GAAS,CAC9C,QAAWI,KAASJ,EAAK,WAAW,EAC5BI,EAAc,iBAClBD,GAAaC,EAAc,OAG3Bd,IAASA,EAAQ,sBAAwB,KAAK,MAAMa,EAAW,GAAI,EAAI,IAC7E,CAAC,EACDX,GAAY,QAAQ,CAAE,KAAM,eAAgB,SAAU,EAAK,CAAC,CAC9D,MAAQ,CAAC,CAGT,GAAI,CACFC,GAAc,IAAI,oBAAqBO,GAAS,CAC9C,GAAM,CAACI,CAAK,EAAIJ,EAAK,WAAW,EAC5BI,GAASd,IAASA,EAAQ,gBAAkB,KAAK,MAAOc,EAAc,gBAAkBA,EAAM,SAAS,EAC7G,CAAC,EACDX,GAAY,QAAQ,CAAE,KAAM,cAAe,SAAU,EAAK,CAAC,CAC7D,MAAQ,CAAC,CACX,CACF,CAEO,SAASY,IAAmD,CACjE,OAAIf,IAASA,EAAQ,UAAY,KAAK,IAAI,GACnCA,EAAU,CAAE,GAAGA,CAAQ,EAAI,IACpC,CAEO,SAASgB,IAAqB,CACnCf,IAAa,WAAW,EACxBC,IAAa,WAAW,EACxBC,IAAa,WAAW,EACxBF,GAAc,KACdC,GAAc,KACdC,GAAc,KACdH,EAAU,IACZ,CC3FA,eAAsBiB,IAA4C,CAEhE,GAAI,CACF,IAAMC,EAAS,MAAMC,GAAwB,EAC7C,GAAID,EAAQ,OAAOA,CACrB,MAAQ,CAAqB,CAG7B,GAAI,CACF,IAAMA,EAAS,MAAME,GAAoB,EACzC,GAAIF,EAAQ,OAAOA,CACrB,MAAQ,CAAqB,CAE7B,OAAO,IACT,CAGA,eAAeC,IAAkD,CAC/D,IAAME,EAAI,OAAO,WACXC,EAAI,OAAO,YAGXC,EAAQ,SAAS,gBAAgB,UAAU,EAAI,EAG/CC,EAAiB,SAAS,gBAAgB,iBAAiB,GAAG,EAC9DC,EAAgBF,EAAM,iBAAiB,GAAG,EAEhD,QAASG,EAAI,EAAGA,EAAIF,EAAe,QAAUE,EAAID,EAAc,OAAQC,IAAK,CAC1E,IAAMC,EAAW,OAAO,iBAAiBH,EAAeE,CAAC,CAAC,EACpDE,EAAKH,EAAcC,CAAC,EAC1B,GAAIE,EAAG,MAAO,CAEZ,IAAMC,EAAQ,CACZ,aAAc,mBAAoB,mBAClC,QAAS,OAAQ,YAAa,cAAe,cAC7C,SAAU,gBAAiB,UAAW,SACtC,UAAW,iBAAkB,cAAe,kBAC5C,MAAO,QAAS,SAAU,YAAa,aACvC,WAAY,WAAY,MAAO,OAAQ,QAAS,SAChD,aAAc,cAAe,UAAW,YACxC,aAAc,cAAe,iBAC7B,kBAAmB,aAAc,UACjC,wBAAyB,qBACzB,YACF,EACA,QAAWC,MAAQD,EACjB,GAAI,CAAED,EAAG,MAAM,YAAYE,GAAMH,EAAS,iBAAiBG,EAAI,CAAC,CAAG,MAAQ,CAAC,CAEhF,CACF,CAGAP,EAAM,iBAAiB,2DAA2D,EAAE,QAAQK,GAAMA,EAAG,OAAO,CAAC,EAG7G,IAAMG,EADa,IAAI,cAAc,EACb,kBAAkBR,CAAK,EAEzCS,EAAM;AAAA,qDACuCX,CAAC,aAAaC,CAAC;AAAA;AAAA,UAE1DS,CAAI;AAAA;AAAA;AAAA,IAKNE,EAAO,IAAI,KAAK,CAACD,CAAG,EAAG,CAAE,KAAM,6BAA8B,CAAC,EAC9DE,EAAM,IAAI,gBAAgBD,CAAI,EAEpC,OAAO,IAAI,QAAwBE,GAAY,CAC7C,IAAMC,EAAM,IAAI,MAChBA,EAAI,OAAS,IAAM,CACjB,IAAMC,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQhB,EAAI,GACnBgB,EAAO,OAASf,EAAI,GACpB,IAAMgB,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,CAAE,IAAI,gBAAgBJ,CAAG,EAAGC,EAAQ,IAAI,EAAG,MAAQ,CAC7DG,EAAI,MAAM,GAAK,EAAG,EAClBA,EAAI,UAAUF,EAAK,EAAG,CAAC,EACvB,IAAI,gBAAgBF,CAAG,EACvBC,EAAQE,EAAO,UAAU,aAAc,EAAG,CAAC,CAC7C,EACAD,EAAI,QAAU,IAAM,CAAE,IAAI,gBAAgBF,CAAG,EAAGC,EAAQ,IAAI,CAAG,EAC/DC,EAAI,IAAMF,CACZ,CAAC,CACH,CAGA,eAAed,IAA8C,CAC3D,GAAI,CAAC,UAAU,cAAc,gBAAiB,OAAO,KAErD,IAAMmB,EAAS,MAAM,UAAU,aAAa,gBAAgB,CAAE,MAAO,CAAE,eAAgB,SAAU,CAAS,CAAC,EACrGC,EAAQD,EAAO,eAAe,EAAE,CAAC,EACjCE,EAAQ,SAAS,cAAc,OAAO,EAE5C,OAAO,IAAI,QAAwBN,GAAY,CAC7CM,EAAM,iBAAmB,IAAM,CAC7BA,EAAM,KAAK,EACX,IAAMJ,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQI,EAAM,WAAa,GAClCJ,EAAO,OAASI,EAAM,YAAc,GACpC,IAAMH,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,CAAEE,EAAM,KAAK,EAAGL,EAAQ,IAAI,EAAG,MAAQ,CACjDG,EAAI,MAAM,GAAK,EAAG,EAClBA,EAAI,UAAUG,EAAO,EAAG,CAAC,EACzBD,EAAM,KAAK,EACXL,EAAQE,EAAO,UAAU,aAAc,EAAG,CAAC,CAC7C,EACAI,EAAM,QAAU,IAAM,CAAED,EAAM,KAAK,EAAGL,EAAQ,IAAI,CAAG,EACrDM,EAAM,UAAYF,CACpB,CAAC,CACH,CCjHA,IAAMG,GAAmB,2BACnBC,GAAoB,6CAEtBC,EAAWF,GACXG,GAAiB,GAEd,SAASC,GAAYC,EAAa,CACvCH,EAAWG,EAAI,QAAQ,MAAO,EAAE,EAChCF,GAAiB,EACnB,CAEO,SAASG,IAAc,CAC5B,OAAOJ,CACT,CAOA,eAAeK,EAAkBF,EAAaG,EAAuC,CACnF,GAAI,CAEF,OADY,MAAM,MAAMH,EAAKG,CAAI,CAEnC,OAASC,EAAK,CAEZ,GAAIN,GAAgB,MAAMM,EAG1BN,GAAiB,GACjB,IAAMO,EAAmBR,EACzBA,EAAWD,GACX,IAAMU,EAAcN,EAAI,QAAQK,EAAkBT,EAAiB,EACnE,OAAO,MAAMU,EAAaH,CAAI,CAChC,CACF,CAIA,IAAMI,GAAc,gBAOpB,SAASC,IAAmC,CAC1C,GAAI,CACF,IAAMC,EAAM,aAAa,QAAQF,EAAW,EAC5C,GAAI,CAACE,EAAK,OAAO,KACjB,IAAMC,EAAO,KAAK,MAAMD,CAAG,EAE3B,OAAIC,EAAK,OAAO,UAAY,KAAK,IAAI,EAE5BA,CAGX,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAASC,GAAcD,EAAkB,CACvC,aAAa,QAAQH,GAAa,KAAK,UAAUG,CAAI,CAAC,CACxD,CAEO,SAASE,IAAkB,CAChC,aAAa,WAAWL,EAAW,CACrC,CAEO,SAASM,GAAkC,CAChD,OAAOL,GAAc,GAAG,MAAQ,IAClC,CAEO,SAASM,IAAgC,CAC9C,OAAON,GAAc,GAAG,OAAO,aAAe,IAChD,CAEA,eAAeO,IAA+C,CAC5D,IAAML,EAAOF,GAAc,EAC3B,GAAI,CAACE,EAAM,MAAO,CAAE,eAAgB,kBAAmB,EAGvD,GAAIA,EAAK,OAAO,UAAY,KAAK,IAAI,EAAI,IACvC,GAAI,CACF,IAAMM,EAAM,MAAMd,EAAkB,GAAGL,CAAQ,oBAAqB,CAClE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,aAAca,EAAK,OAAO,YAAa,CAAC,CACjE,CAAC,EACD,GAAIM,EAAI,GAAI,CACV,IAAMC,EAAO,MAAMD,EAAI,KAAK,EACxBC,EAAK,UACPP,EAAK,OAASO,EAAK,KACnBN,GAAcD,CAAI,EAEtB,CACF,MAAQ,CAA2B,CAGrC,MAAO,CACL,eAAgB,mBAChB,cAAiB,UAAUA,EAAK,OAAO,WAAW,EACpD,CACF,CAIA,eAAsBQ,GAAMC,EAAeC,EAAkBC,EAAiF,CAC5I,GAAI,CAMF,IAAMJ,EAAO,MALD,MAAMf,EAAkB,GAAGL,CAAQ,kBAAmB,CAChE,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,MAAAsB,EAAO,SAAAC,EAAU,UAAAC,CAAU,CAAC,CACrD,CAAC,GACsB,KAAK,EAC5B,OAAIJ,EAAK,SACPN,GAAc,CAAE,KAAMM,EAAK,KAAK,KAAM,OAAQA,EAAK,KAAK,MAAO,CAAC,EAE3DA,CACT,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAEA,eAAsBK,IAAS,CAC7BV,GAAgB,CAClB,CAcA,eAAsBW,GAAaC,EAAyD,CAC1F,GAAI,CACF,IAAMC,EAAU,MAAMC,GAAY,EAMlC,OAAO,MALK,MAAMC,EAAkB,GAAGC,CAAQ,eAAgB,CAC7D,OAAQ,OACR,QAAAH,EACA,KAAM,KAAK,UAAUD,CAAM,CAC7B,CAAC,GACgB,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,0CAA2C,CAC7E,CACF,CAIA,eAAsBK,GAAcC,EAAmBC,EAAmD,CACxG,GAAI,CACF,IAAMN,EAAU,MAAMC,GAAY,EAElC,OAAO,MADK,MAAMC,EAAkB,GAAGC,CAAQ,+BAA+BE,CAAS,aAAa,mBAAmBC,CAAQ,CAAC,GAAI,CAAE,QAAAN,CAAQ,CAAC,GAC9H,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAEA,eAAsBO,GAAUC,EAAsD,CACpF,GAAI,CACF,IAAMR,EAAU,MAAMC,GAAY,EAMlC,OAAO,MALK,MAAMC,EAAkB,GAAGC,CAAQ,YAAa,CAC1D,OAAQ,OACR,QAAAH,EACA,KAAM,KAAK,UAAUQ,CAAG,CAC1B,CAAC,GACgB,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAEA,eAAsBC,GAAUC,EAAeC,EAA0D,CACvG,GAAI,CACF,IAAMX,EAAU,MAAMC,GAAY,EAMlC,OAAO,MALK,MAAMC,EAAkB,GAAGC,CAAQ,aAAaO,CAAK,GAAI,CACnE,OAAQ,MACR,QAAAV,EACA,KAAM,KAAK,UAAUW,CAAO,CAC9B,CAAC,GACgB,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAEA,eAAsBC,GAAUF,EAA2C,CACzE,GAAI,CACF,IAAMV,EAAU,MAAMC,GAAY,EAKlC,OAAO,MAJK,MAAMC,EAAkB,GAAGC,CAAQ,aAAaO,CAAK,GAAI,CACnE,OAAQ,SACR,QAAAV,CACF,CAAC,GACgB,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAIA,eAAsBa,GAAcH,EAAmD,CACrF,GAAI,CACF,IAAMV,EAAU,MAAMC,GAAY,EAElC,OAAO,MADK,MAAMC,EAAkB,GAAGC,CAAQ,aAAaO,CAAK,YAAa,CAAE,QAAAV,CAAQ,CAAC,GACxE,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAEA,eAAsBc,GAAcJ,EAAeK,EAAcC,EAAqB,CAAC,EAAqC,CAC1H,GAAI,CACF,IAAMhB,EAAU,MAAMC,GAAY,EAMlC,OAAO,MALK,MAAMC,EAAkB,GAAGC,CAAQ,aAAaO,CAAK,YAAa,CAC5E,OAAQ,OACR,QAAAV,EACA,KAAM,KAAK,UAAU,CAAE,KAAAe,EAAM,SAAAC,CAAS,CAAC,CACzC,CAAC,GACgB,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAIA,eAAsBC,GAAoBZ,EAAmD,CAC3F,GAAI,CACF,IAAML,EAAU,MAAMC,GAAY,EAElC,OAAO,MADK,MAAMC,EAAkB,GAAGC,CAAQ,4BAA4BE,CAAS,GAAI,CAAE,QAAAL,CAAQ,CAAC,GAClF,KAAK,CACxB,MAAQ,CACN,MAAO,CAAE,QAAS,GAAO,MAAO,eAAgB,CAClD,CACF,CAIA,IAAMkB,GAAY,yBASX,SAASC,GAAmBC,EAAgD,CACjF,IAAMC,EAAQC,GAAgB,EAC9BD,EAAM,KAAK,CACT,GAAGD,EACH,GAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,EACtC,UAAW,KAAK,IAAI,CACtB,CAAC,EACD,aAAa,QAAQF,GAAW,KAAK,UAAUG,CAAK,CAAC,CACvD,CAEO,SAASC,IAAkC,CAChD,GAAI,CACF,OAAO,KAAK,MAAM,aAAa,QAAQJ,EAAS,GAAK,IAAI,CAC3D,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CAEA,eAAsBK,IAAqC,CACzD,IAAMF,EAAQC,GAAgB,EAC9B,GAAID,EAAM,SAAW,EAAG,MAAO,GAE/B,IAAIG,EAAU,EACRC,EAA4B,CAAC,EAEnC,QAAWL,KAAUC,EACnB,GAAI,CACF,IAAIK,EACJ,OAAQN,EAAO,KAAM,CACnB,IAAK,aACHM,EAAS,MAAMnB,GAAUa,EAAO,IAAI,EACpC,MACF,IAAK,iBACHM,EAAS,MAAMZ,GAAcM,EAAO,KAAK,MAAOA,EAAO,KAAK,KAAMA,EAAO,KAAK,QAAQ,EACtF,MACF,IAAK,aACHM,EAAS,MAAMjB,GAAUW,EAAO,KAAK,MAAOA,EAAO,KAAK,OAAO,EAC/D,MACF,IAAK,gBACHM,EAAS,MAAM5B,GAAasB,EAAO,IAAI,EACvC,MACF,QACEM,EAAS,CAAE,QAAS,GAAO,MAAO,gBAAiB,CACvD,CACIA,EAAO,QACTF,IAEAC,EAAU,KAAKL,CAAM,CAEzB,MAAQ,CACNK,EAAU,KAAKL,CAAM,CACvB,CAGF,oBAAa,QAAQF,GAAW,KAAK,UAAUO,CAAS,CAAC,EAClDD,CACT,CAGI,OAAO,OAAW,KACpB,OAAO,iBAAiB,SAAU,IAAM,CACtCD,GAAkB,EAAE,MAAM,IAAM,CAAC,CAAC,CACpC,CAAC,EC1TH,IAAMI,GAAoB,CAExB,CACE,GAAI,WACJ,KAAM,WACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,SACJ,KAAM,cACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,YACJ,KAAM,YACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,MACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,SACJ,KAAM,SACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,QACJ,KAAM,QACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,OACJ,KAAM,YACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,SACJ,KAAM,eACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,QACJ,KAAM,gBACN,QAAS,CAAC,qBAAsB,SAAS,EACzC,KAAM,CACJ,UAAW,sBACX,WAAY,qBACZ,WAAY,qBACZ,YAAa,UACb,aAAc,UACd,cAAe,wBACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,OACJ,KAAM,OACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,MACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,SACJ,KAAM,SACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,eACJ,KAAM,eACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,gBACJ,KAAM,gBACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,UACJ,KAAM,UACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,OACJ,KAAM,OACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,UACJ,KAAM,UACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,MACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,YACJ,KAAM,iBACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,QACJ,KAAM,QACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,QACJ,KAAM,QACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,QACJ,KAAM,QACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,MAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,EAEA,CACE,GAAI,WACJ,KAAM,WACN,QAAS,CAAC,UAAW,SAAS,EAC9B,KAAM,CACJ,UAAW,UACX,WAAY,UACZ,WAAY,UACZ,YAAa,UACb,aAAc,UACd,cAAe,UACf,cAAe,UACf,eAAgB,UAChB,YAAa,UACb,YAAa,UACb,cAAe,OACf,iBAAkB,OAClB,WAAY,UACZ,aAAc,UACd,cAAe,UACf,cAAe,SACjB,CACF,CACF,EAEO,SAASC,IAAuB,CACrC,OAAOD,EACT,CAEO,SAASE,GAAaC,EAAiC,CAC5D,OAAOH,GAAO,KAAM,GAAM,EAAE,KAAOG,CAAE,CACvC,CAEO,SAASC,IAA2B,CACzC,OAAOJ,GAAO,CAAC,CACjB,CC/eA,IAAMK,GAAsB,CAE1B,CAAE,GAAI,UAAW,KAAM,iBAAkB,YAAa,2BAA4B,YAAa,KAAM,EAErG,CAAE,GAAI,eAAgB,KAAM,eAAgB,YAAa,2BAA4B,YAAa,KAAM,EAExG,CAAE,GAAI,cAAe,KAAM,cAAe,YAAa,0BAA2B,YAAa,KAAM,EAErG,CAAE,GAAI,eAAgB,KAAM,eAAgB,YAAa,4BAA6B,YAAa,KAAM,EAEzG,CAAE,GAAI,UAAW,KAAM,WAAY,YAAa,0BAA2B,YAAa,KAAM,EAE9F,CAAE,GAAI,UAAW,KAAM,UAAW,YAAa,uBAAwB,YAAa,KAAM,EAE1F,CAAE,GAAI,OAAQ,KAAM,OAAQ,YAAa,wBAAyB,YAAa,KAAM,EAErF,CAAE,GAAI,aAAc,KAAM,aAAc,YAAa,sBAAuB,YAAa,KAAM,EAE/F,CAAE,GAAI,YAAa,KAAM,cAAe,YAAa,2BAA4B,YAAa,KAAM,EAEpG,CAAE,GAAI,YAAa,KAAM,cAAe,YAAa,0BAA2B,YAAa,KAAM,EAEnG,CAAE,GAAI,YAAa,KAAM,YAAa,YAAa,gCAAiC,YAAa,KAAM,EAEvG,CAAE,GAAI,eAAgB,KAAM,eAAgB,YAAa,4BAA6B,YAAa,MAAO,EAE1G,CAAE,GAAI,YAAa,KAAM,YAAa,YAAa,4BAA6B,YAAa,KAAM,EAEnG,CAAE,GAAI,UAAW,KAAM,UAAW,YAAa,wBAAyB,YAAa,KAAM,EAE3F,CAAE,GAAI,QAAS,KAAM,QAAS,YAAa,yBAA0B,YAAa,KAAM,EAExF,CAAE,GAAI,UAAW,KAAM,SAAU,YAAa,yBAA0B,YAAa,KAAM,EAE3F,CAAE,GAAI,QAAS,KAAM,QAAS,YAAa,6BAA8B,YAAa,KAAM,EAE5F,CAAE,GAAI,QAAS,KAAM,aAAc,YAAa,oBAAqB,YAAa,MAAO,EAEzF,CAAE,GAAI,WAAY,KAAM,WAAY,YAAa,2BAA4B,YAAa,KAAM,EAEhG,CAAE,GAAI,cAAe,KAAM,cAAe,YAAa,qBAAsB,YAAa,QAAS,CACrG,EAEO,SAASC,IAAyB,CACvC,OAAOD,EACT,CAEO,SAASE,GAAcC,EAAkC,CAC9D,OAAOH,GAAQ,KAAMI,GAAMA,EAAE,KAAOD,CAAE,CACxC,CAEO,SAASE,IAA6B,CAC3C,OAAOL,GAAQ,CAAC,CAClB,CAMO,IAAMM,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","captureScreenshot","result","captureSvgForeignObject","captureDisplayMedia","w","h","clone","sourceElements","cloneElements","i","computed","el","props","prop","html","svg","blob","url","resolve","img","canvas","ctx","stream","track","video","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","c","input","body","res","createComment","commentsEl","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","modal","backdrop","styleEl","keyHandler","isOpen","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","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","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","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"]}