bugstash 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +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","export async function captureScreenshot(): Promise<string | null> {\n // Try html2canvas if available (optional peer dependency)\n try {\n const html2canvas = (window as any).html2canvas ?? (await import('html2canvas')).default;\n if (html2canvas) {\n const canvas = await html2canvas(document.body, {\n logging: false,\n useCORS: true,\n scale: 0.5,\n width: window.innerWidth,\n height: window.innerHeight,\n });\n return canvas.toDataURL('image/jpeg', 0.6);\n }\n } catch {\n // html2canvas not available, skip\n }\n\n return null;\n}\n","import type { BugReport, APIResponse, AuthUser, AuthTokens, LivePin, PinComment, Member } from '@bugstash/shared';\n\nlet endpoint = 'http://localhost:4000';\n\nexport function setEndpoint(url: string) {\n endpoint = url.replace(/\\/$/, '');\n}\n\nexport function getEndpoint() {\n return endpoint;\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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 fetch(`${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 = 'Install html2canvas package for screenshot support';\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\nexport const BugStash = {\n init(options: BugStashConfig) {\n if (initialized) return;\n if (typeof window === 'undefined') return;\n\n const env = options.environment ?? 'development';\n if (env === 'production') return;\n\n initialized = true;\n\n if (options.endpoint) setEndpoint(options.endpoint);\n\n // Order matters: breadcrumbs first (other modules push to it)\n initBreadcrumbs(options.maxBreadcrumbs);\n initLogger(options.maxLogs);\n initNetwork(options.maxNetworkCaptures);\n initErrors();\n if (options.enablePerformance !== false) initPerformance();\n initPanel(options);\n\n // Init live pins if enabled and user is logged in\n if (options.enableLivePins !== false) {\n const user = getCurrentUser();\n if (user) {\n initLivePins(options.projectId);\n connectRealtime(options.projectId);\n }\n }\n },\n\n destroy() {\n if (!initialized) return;\n destroyPanel();\n destroyLivePins();\n disconnectRealtime();\n restoreConsole();\n restoreNetwork();\n restoreErrors();\n restoreBreadcrumbs();\n restorePerformance();\n initialized = false;\n },\n\n // Programmatic API\n getLogs,\n clearLogs,\n getNetworkCaptures,\n getFailedNetworkCaptures,\n clearNetworkCaptures,\n getErrors,\n clearErrors,\n getBreadcrumbs,\n clearBreadcrumbs,\n getPerformanceMetrics,\n addBreadcrumb,\n // Theme API\n getThemes,\n getThemeById,\n setTheme,\n getCurrentThemeId,\n // Layout API\n getLayouts,\n getLayoutById,\n setLayout,\n getCurrentLayoutId,\n // Auth API\n getCurrentUser,\n login,\n logout,\n // Live Pins API\n togglePinMode,\n isPinModeActive,\n // Real-time\n isConnected,\n // Annotation\n openAnnotationEditor,\n // PII Redaction\n redactString,\n redactObject,\n};\n\nexport default BugStash;\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","names":["canvas","projectId","projectId","projectId","endpoint","getSelector","logs","errors","timeAgo","errors","logs","crumbs","ctx","container","COLORS","currentColor","currentTool","shapes","pins","PIN_COLORS","canvas","renderPins","keyHandler","confirm","createOverlay"]}