@siteping/widget 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../../node_modules/.bun/@medv+finder@3.2.0/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/dom-utils.ts","../src/icons.ts","../src/styles/theme.ts","../src/popup.ts","../src/annotator.ts","../src/api-client.ts","../src/events.ts","../src/fab.ts","../src/i18n/de.ts","../src/i18n/en.ts","../src/i18n/es.ts","../src/i18n/fr.ts","../src/i18n/it.ts","../src/i18n/pt.ts","../src/i18n/ru.ts","../src/i18n/index.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/resolver.ts","../src/markers.ts","../src/export-utils.ts","../src/panel-bulk.ts","../src/panel-detail.ts","../src/panel-sort.ts","../src/panel-stats.ts","../src/shortcuts.ts","../src/panel.ts","../../core/src/types.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts"],"sourcesContent":["import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n FeedbackPayload,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEvents,\n SitepingStore,\n} from \"@siteping/core\";\n\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n","// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nlet config;\nlet rootDocument;\nlet start;\nexport function finder(input, options) {\n start = new Date();\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if ('html' === input.tagName.toLowerCase()) {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: (name) => true,\n className: (name) => true,\n tagName: (name) => true,\n attr: (name, value) => false,\n seedMinLength: 1,\n optimizedMinLength: 2,\n threshold: 1000,\n maxNumberOfTries: 10000,\n timeoutMs: undefined,\n };\n config = { ...defaults, ...options };\n rootDocument = findRootDocument(config.root, defaults);\n let path = bottomUpSearch(input, 'all', () => bottomUpSearch(input, 'two', () => bottomUpSearch(input, 'one', () => bottomUpSearch(input, 'none'))));\n if (path) {\n const optimized = sort(optimize(path, input));\n if (optimized.length > 0) {\n path = optimized[0];\n }\n return selector(path);\n }\n else {\n throw new Error(`Selector was not found.`);\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction bottomUpSearch(input, limit, fallback) {\n let path = null;\n let stack = [];\n let current = input;\n let i = 0;\n while (current) {\n const elapsedTime = new Date().getTime() - start.getTime();\n if (config.timeoutMs !== undefined && elapsedTime > config.timeoutMs) {\n throw new Error(`Timeout: Can't find a unique selector after ${elapsedTime}ms`);\n }\n let level = maybe(id(current)) ||\n maybe(...attr(current)) ||\n maybe(...classNames(current)) ||\n maybe(tagName(current)) || [any()];\n const nth = index(current);\n if (limit == 'all') {\n if (nth) {\n level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));\n }\n }\n else if (limit == 'two') {\n level = level.slice(0, 1);\n if (nth) {\n level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));\n }\n }\n else if (limit == 'one') {\n const [node] = (level = level.slice(0, 1));\n if (nth && dispensableNth(node)) {\n level = [nthChild(node, nth)];\n }\n }\n else if (limit == 'none') {\n level = [any()];\n if (nth) {\n level = [nthChild(level[0], nth)];\n }\n }\n for (let node of level) {\n node.level = i;\n }\n stack.push(level);\n if (stack.length >= config.seedMinLength) {\n path = findUniquePath(stack, fallback);\n if (path) {\n break;\n }\n }\n current = current.parentElement;\n i++;\n }\n if (!path) {\n path = findUniquePath(stack, fallback);\n }\n if (!path && fallback) {\n return fallback();\n }\n return path;\n}\nfunction findUniquePath(stack, fallback) {\n const paths = sort(combinations(stack));\n if (paths.length > config.threshold) {\n return fallback ? fallback() : null;\n }\n for (let candidate of paths) {\n if (unique(candidate)) {\n return candidate;\n }\n }\n return null;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction unique(path) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction id(input) {\n const elementId = input.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n return {\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n };\n }\n return null;\n}\nfunction attr(input) {\n const attrs = Array.from(input.attributes).filter((attr) => config.attr(attr.name, attr.value));\n return attrs.map((attr) => ({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 0.5,\n }));\n}\nfunction classNames(input) {\n const names = Array.from(input.classList).filter(config.className);\n return names.map((name) => ({\n name: '.' + CSS.escape(name),\n penalty: 1,\n }));\n}\nfunction tagName(input) {\n const name = input.tagName.toLowerCase();\n if (config.tagName(name)) {\n return {\n name,\n penalty: 2,\n };\n }\n return null;\n}\nfunction any() {\n return {\n name: '*',\n penalty: 3,\n };\n}\nfunction index(input) {\n const parent = input.parentNode;\n if (!parent) {\n return null;\n }\n let child = parent.firstChild;\n if (!child) {\n return null;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction nthChild(node, i) {\n return {\n name: node.name + `:nth-child(${i})`,\n penalty: node.penalty + 1,\n };\n}\nfunction dispensableNth(node) {\n return node.name !== 'html' && !node.name.startsWith('#');\n}\nfunction maybe(...level) {\n const list = level.filter(notEmpty);\n if (list.length > 0) {\n return list;\n }\n return null;\n}\nfunction notEmpty(value) {\n return value !== null && value !== undefined;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction sort(paths) {\n return [...paths].sort((a, b) => penalty(a) - penalty(b));\n}\nfunction* optimize(path, input, scope = {\n counter: 0,\n visited: new Map(),\n}) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n if (scope.counter > config.maxNumberOfTries) {\n return; // Okay At least I tried!\n }\n scope.counter += 1;\n const newPath = [...path];\n newPath.splice(i, 1);\n const newPathKey = selector(newPath);\n if (scope.visited.has(newPathKey)) {\n return;\n }\n if (unique(newPath) && same(newPath, input)) {\n yield newPath;\n scope.visited.set(newPathKey, true);\n yield* optimize(newPath, input, scope);\n }\n }\n }\n}\nfunction same(path, input) {\n return rootDocument.querySelector(selector(path)) === input;\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n // Hash stable attributes\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n const attrHash = attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n\n return `${childCount}:${siblingIdx}:${attrHash}`;\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling: Element | null = element[prop];\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text = sibling.textContent?.trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = sibling[prop];\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate siblings for disambiguation context. */\nexport function neighborText(element: Element): string {\n const prev = element.previousElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n const next = element.nextElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short\n */\nexport function generateXPath(element: Element): string {\n if (element.id) {\n const safeId = element.id.includes(\"'\") ? `concat('${element.id.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${element.id}'`;\n return `//${element.localName}[@id=${safeId}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n const safeId = current.id.includes(\"'\")\n ? `concat('${current.id.replace(/'/g, \"',\\\"'\\\",'\")}')`\n : `'${current.id}'`;\n segments.unshift(`/${tag}[@id=${safeId}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n return \"/html/body\" + segments.join(\"\");\n}\n","import { finder } from \"@medv/finder\";\nimport type { AnchorData, RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Uses three complementary strategies (Hypothesis-inspired):\n * 1. CSS selector via @medv/finder (primary — fast, compact)\n * 2. XPath (fallback — survives class changes)\n * 3. Text snippet (fallback — survives structural changes)\n */\nexport function generateAnchor(element: Element): AnchorData {\n const cssSelector = finder(element, {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n });\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName,\n elementId: element.id || undefined,\n };\n}\n\n/**\n * Find the smallest DOM element whose bounding box fully contains the drawn rectangle.\n *\n * Walks up from the element at the rect's center until an ancestor contains the\n * full rectangle. Falls back to `document.body` when no ancestor matches — without\n * this fallback, callers compute percentages against a too-small anchor and produce\n * out-of-range values (negative / > 1).\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const centerX = rect.x + rect.width / 2;\n const centerY = rect.y + rect.height / 2;\n\n const elementAtCenter = document.elementFromPoint(centerX, centerY);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n const bounds = current.getBoundingClientRect();\n if (\n bounds.left <= rect.x &&\n bounds.top <= rect.y &&\n bounds.right >= rect.x + rect.width &&\n bounds.bottom >= rect.y + rect.height\n ) {\n return current;\n }\n current = current.parentElement;\n }\n\n return document.body;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","/**\n * Safe DOM creation utilities.\n * All user content is set via textContent (never innerHTML).\n * SVG icons use a DOMParser for trusted static strings.\n */\n\n/**\n * Parse a trusted SVG string into an SVGElement.\n * Only use with hardcoded icon constants — never with user input.\n * Uses createContextualFragment for native document-context parsing\n * (DOMParser creates nodes in a foreign document that don't render in Shadow DOM).\n */\nexport function parseSvg(svgString: string): SVGSVGElement {\n const range = document.createRange();\n const fragment = range.createContextualFragment(svgString);\n const svg = fragment.firstElementChild;\n if (!svg || svg.nodeName.toLowerCase() !== \"svg\") {\n throw new Error(\"[siteping] Invalid SVG string\");\n }\n // Safety: strip any event handlers in case of accidental misuse\n for (const attr of [...svg.attributes]) {\n if (attr.name.startsWith(\"on\")) svg.removeAttribute(attr.name);\n }\n // Also strip from all descendants\n for (const el of svg.querySelectorAll(\"*\")) {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith(\"on\")) el.removeAttribute(attr.name);\n }\n }\n return svg as SVGSVGElement;\n}\n\n/** Create an element with optional class and style */\nexport function el(tag: string, attrs?: Record<string, string>): HTMLElement {\n const element = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (key === \"class\") {\n element.className = value;\n } else if (key === \"style\") {\n element.style.cssText = value;\n } else {\n element.setAttribute(key, value);\n }\n }\n }\n return element;\n}\n\n/** Set text content safely (no HTML injection possible) */\nexport function setText(element: HTMLElement | SVGElement, text: string): void {\n element.textContent = text;\n}\n\n/** Format a relative date string using Intl.RelativeTimeFormat for locale support */\nexport function formatRelativeDate(isoString: string, locale = \"en\"): string {\n const diff = Date.now() - new Date(isoString).getTime();\n const seconds = Math.floor(diff / 1000);\n\n if (seconds < 60) {\n return new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" }).format(0, \"second\");\n }\n\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: \"always\", style: \"narrow\" });\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, \"minute\");\n\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return rtf.format(-hours, \"hour\");\n\n const days = Math.floor(hours / 24);\n if (days < 7) return rtf.format(-days, \"day\");\n\n return new Date(isoString).toLocaleDateString(locale);\n}\n","/** SVG icon strings for the widget UI. Kept as template strings to avoid DOM parsing overhead. */\n\nexport const ICON_SITEPING = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/><circle cx=\"12\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"8\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"16\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/></svg>`;\n\nexport const ICON_CHAT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>`;\n\nexport const ICON_ANNOTATE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><path d=\"M3 9h18\"/><path d=\"M9 3v18\"/></svg>`;\n\nexport const ICON_EYE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`;\n\nexport const ICON_EYE_OFF = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\"/><path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\"/><line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/></svg>`;\n\nexport const ICON_CLOSE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\nexport const ICON_SEARCH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>`;\n\nexport const ICON_CHECK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n\nexport const ICON_QUESTION = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/></svg>`;\n\nexport const ICON_CHANGE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`;\n\nexport const ICON_BUG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"8\" y=\"6\" width=\"8\" height=\"14\" rx=\"4\"/><path d=\"M19 9h2\"/><path d=\"M3 9h2\"/><path d=\"M19 13h2\"/><path d=\"M3 13h2\"/><path d=\"M19 17h2\"/><path d=\"M3 17h2\"/><path d=\"M10 2h4\"/></svg>`;\n\nexport const ICON_OTHER = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"19\" cy=\"12\" r=\"1\"/><circle cx=\"5\" cy=\"12\" r=\"1\"/></svg>`;\n\nexport const ICON_LAYERS = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/></svg>`;\n\nexport const ICON_DOT_OPEN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"currentColor\" stroke=\"none\"/></svg>`;\n\nexport const ICON_CHEVRON_DOWN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"6 9 12 15 18 9\"/></svg>`;\n\nexport const ICON_UNDO = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>`;\n\nexport const ICON_TRASH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/></svg>`;\n","/** Color palette and glassmorphism tokens derived from the accent color */\nexport interface ThemeColors {\n accent: string;\n accentLight: string;\n accentDark: string;\n accentGlow: string;\n accentGradient: string;\n bg: string;\n bgHover: string;\n text: string;\n textSecondary: string;\n textTertiary: string;\n border: string;\n shadow: string;\n // Glass tokens\n glassBg: string;\n glassBgHeavy: string;\n glassBorder: string;\n glassBorderSubtle: string;\n // Feedback type colors\n typeQuestion: string;\n typeChange: string;\n typeBug: string;\n typeOther: string;\n // Soft type backgrounds (pastel)\n typeQuestionBg: string;\n typeChangeBg: string;\n typeBugBg: string;\n typeOtherBg: string;\n // Status filter colors\n statusOpen: string;\n statusOpenBg: string;\n statusResolved: string;\n statusResolvedBg: string;\n}\n\nconst DEFAULT_ACCENT = \"#0066ff\";\nconst HEX6_RE = /^#[0-9a-fA-F]{6}$/;\nconst HEX3_RE = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/;\nconst HEX8_RE = /^#[0-9a-fA-F]{8}$/;\n\n/**\n * Normalize an accent color to a 6-digit hex string.\n *\n * **Only hex formats are accepted:**\n * - `#RGB` (3-digit shorthand, expanded to 6-digit)\n * - `#RRGGBB` (standard 6-digit)\n * - `#RRGGBBAA` (8-digit with alpha, alpha is stripped)\n *\n * Any other CSS color format (named colors like `\"red\"`, `hsl()`, `rgb()`,\n * `oklch()`, etc.) is **not** supported and will fall back to the default\n * accent color with a console warning.\n */\nfunction normalizeHex(raw: string): string {\n if (HEX6_RE.test(raw)) return raw;\n const short = HEX3_RE.test(raw) ? raw.match(HEX3_RE) : null;\n if (short) return `#${short[1]}${short[1]}${short[2]}${short[2]}${short[3]}${short[3]}`;\n if (HEX8_RE.test(raw)) return raw.slice(0, 7);\n\n console.warn(\n `[siteping] Invalid accentColor \"${raw}\" — only hex colors (#RGB, #RRGGBB, #RRGGBBAA) are supported. Using default.`,\n );\n return DEFAULT_ACCENT;\n}\n\n/** Darken a hex color by a percentage (0-1) */\nfunction darkenHex(hex: string, amount: number): string {\n const r = Math.max(0, Math.round(parseInt(hex.slice(1, 3), 16) * (1 - amount)));\n const g = Math.max(0, Math.round(parseInt(hex.slice(3, 5), 16) * (1 - amount)));\n const b = Math.max(0, Math.round(parseInt(hex.slice(5, 7), 16) * (1 - amount)));\n return `#${r.toString(16).padStart(2, \"0\")}${g.toString(16).padStart(2, \"0\")}${b.toString(16).padStart(2, \"0\")}`;\n}\n\n/** Detect if user prefers dark mode via media query */\nfunction prefersDark(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\n/** Resolve 'auto' theme to 'light' or 'dark' based on system preference */\nexport function resolveTheme(theme?: \"light\" | \"dark\" | \"auto\"): \"light\" | \"dark\" {\n if (theme === \"dark\") return \"dark\";\n if (theme === \"auto\") return prefersDark() ? \"dark\" : \"light\";\n return \"light\";\n}\n\nexport function buildThemeColors(accent: string = DEFAULT_ACCENT, theme?: \"light\" | \"dark\" | \"auto\"): ThemeColors {\n const hex = normalizeHex(accent);\n const dark = darkenHex(hex, 0.15);\n const resolved = resolveTheme(theme);\n\n if (resolved === \"dark\") {\n return {\n accent: hex,\n accentLight: hex + \"22\", // slightly more visible on dark bg\n accentDark: dark,\n accentGlow: hex + \"44\",\n accentGradient: `linear-gradient(135deg, ${hex}, ${dark})`,\n bg: \"#0f172a\",\n bgHover: \"#1e293b\",\n text: \"#f1f5f9\",\n textSecondary: \"#94a3b8\",\n textTertiary: \"#64748b\",\n border: \"#334155\",\n shadow: \"rgba(0, 0, 0, 0.3)\",\n // Glass tokens — dark frosted glass\n glassBg: \"rgba(15, 23, 42, 0.78)\",\n glassBgHeavy: \"rgba(15, 23, 42, 0.88)\",\n glassBorder: \"rgba(51, 65, 85, 0.5)\",\n glassBorderSubtle: \"rgba(51, 65, 85, 0.3)\",\n // Type colors stay vibrant on dark\n typeQuestion: \"#60a5fa\",\n typeChange: \"#fbbf24\",\n typeBug: \"#f87171\",\n typeOther: \"#94a3b8\",\n // Dark pastel backgrounds\n typeQuestionBg: \"rgba(59, 130, 246, 0.15)\",\n typeChangeBg: \"rgba(245, 158, 11, 0.15)\",\n typeBugBg: \"rgba(239, 68, 68, 0.15)\",\n typeOtherBg: \"rgba(100, 116, 139, 0.15)\",\n // Status colors — vivid green / cool gray on dark\n statusOpen: \"#4ade80\",\n statusOpenBg: \"rgba(74, 222, 128, 0.15)\",\n statusResolved: \"#94a3b8\",\n statusResolvedBg: \"rgba(148, 163, 184, 0.15)\",\n };\n }\n\n return {\n accent: hex,\n accentLight: hex + \"14\", // 8% opacity\n accentDark: dark,\n accentGlow: hex + \"33\", // 20% opacity\n accentGradient: `linear-gradient(135deg, ${hex}, ${dark})`,\n bg: \"#ffffff\",\n bgHover: \"#f8f9fb\",\n text: \"#0f172a\",\n textSecondary: \"#475569\",\n textTertiary: \"#64748b\",\n border: \"#e2e8f0\",\n shadow: \"rgba(0, 0, 0, 0.06)\",\n // Glass tokens\n glassBg: \"rgba(255, 255, 255, 0.72)\",\n glassBgHeavy: \"rgba(255, 255, 255, 0.85)\",\n glassBorder: \"rgba(255, 255, 255, 0.35)\",\n glassBorderSubtle: \"rgba(255, 255, 255, 0.18)\",\n // Vibrant type colors\n typeQuestion: \"#3b82f6\",\n typeChange: \"#b45309\",\n typeBug: \"#ef4444\",\n typeOther: \"#64748b\",\n // Pastel backgrounds\n typeQuestionBg: \"#eff6ff\",\n typeChangeBg: \"#fffbeb\",\n typeBugBg: \"#fef2f2\",\n typeOtherBg: \"#f8fafc\",\n // Status colors — saturated green / cool gray on light\n statusOpen: \"#16a34a\",\n statusOpenBg: \"#f0fdf4\",\n statusResolved: \"#64748b\",\n statusResolvedBg: \"#f1f5f9\",\n };\n}\n\nexport function getTypeColor(type: string, colors: ThemeColors): string {\n switch (type) {\n case \"question\":\n return colors.typeQuestion;\n case \"change\":\n return colors.typeChange;\n case \"bug\":\n return colors.typeBug;\n default:\n return colors.typeOther;\n }\n}\n\nexport function getTypeBgColor(type: string, colors: ThemeColors): string {\n switch (type) {\n case \"question\":\n return colors.typeQuestionBg;\n case \"change\":\n return colors.typeChangeBg;\n case \"bug\":\n return colors.typeBugBg;\n default:\n return colors.typeOtherBg;\n }\n}\n\nexport function cssVariables(colors: ThemeColors): string {\n return `\n --sp-accent: ${colors.accent};\n --sp-accent-light: ${colors.accentLight};\n --sp-accent-dark: ${colors.accentDark};\n --sp-accent-glow: ${colors.accentGlow};\n --sp-accent-gradient: ${colors.accentGradient};\n --sp-bg: ${colors.bg};\n --sp-bg-hover: ${colors.bgHover};\n --sp-text: ${colors.text};\n --sp-text-secondary: ${colors.textSecondary};\n --sp-text-tertiary: ${colors.textTertiary};\n --sp-border: ${colors.border};\n --sp-shadow: ${colors.shadow};\n --sp-glass-bg: ${colors.glassBg};\n --sp-glass-bg-heavy: ${colors.glassBgHeavy};\n --sp-glass-border: ${colors.glassBorder};\n --sp-glass-border-subtle: ${colors.glassBorderSubtle};\n --sp-type-question: ${colors.typeQuestion};\n --sp-type-change: ${colors.typeChange};\n --sp-type-bug: ${colors.typeBug};\n --sp-type-other: ${colors.typeOther};\n --sp-type-question-bg: ${colors.typeQuestionBg};\n --sp-type-change-bg: ${colors.typeChangeBg};\n --sp-type-bug-bg: ${colors.typeBugBg};\n --sp-type-other-bg: ${colors.typeOtherBg};\n --sp-radius: 12px;\n --sp-radius-lg: 16px;\n --sp-radius-xl: 20px;\n --sp-radius-full: 9999px;\n --sp-blur: 20px;\n --sp-blur-heavy: 32px;\n --sp-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);\n --sp-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.04);\n --sp-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04);\n --sp-shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.04);\n --sp-shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.12), 0 8px 16px rgba(0, 0, 0, 0.06);\n --sp-font: \"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n `;\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n label: string;\n icon: string;\n}\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: `\n position:fixed;\n z-index:${Z_INDEX_MAX};\n width:300px;\n padding:16px;\n border-radius:16px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border:1px solid ${this.colors.glassBorder};\n box-shadow:0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n opacity:0;\n transform:translateY(8px) scale(0.98);\n transition:opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n display:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n // Type selector grid (2x2)\n const typeOptions: TypeOption[] = [\n { type: \"question\", label: this.t(\"type.question\"), icon: ICON_QUESTION },\n { type: \"change\", label: this.t(\"type.change\"), icon: ICON_CHANGE },\n { type: \"bug\", label: this.t(\"type.bug\"), icon: ICON_BUG },\n { type: \"other\", label: this.t(\"type.other\"), icon: ICON_OTHER },\n ];\n const typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n height:44px;\n border-radius:9999px;border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};cursor:pointer;\n display:flex;align-items:center;justify-content:center;gap:5px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;color:${this.colors.textTertiary};\n transition:all 0.2s ease;\n padding:0 12px;\n `;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n const labelSpan = document.createElement(\"span\");\n setText(labelSpan, option.label);\n btn.appendChild(labelSpan);\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n this.selectType(option.type, typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = `\n width:100%;min-height:72px;max-height:152px;\n padding:10px 12px;border-radius:12px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBgHeavy};\n color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;line-height:1.5;resize:vertical;\n outline:none;transition:all 0.2s ease;\n box-sizing:border-box;\n `;\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.maxLength = 5000;\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n // Keyboard shortcut hint\n const hint = el(\"div\", {\n style: `\n font-size:11px;color:${this.colors.textTertiary};\n text-align:right;margin-top:4px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n letter-spacing:0.01em;\n `,\n });\n // navigator.userAgentData is preferred; navigator.platform is deprecated\n // but still needed as fallback. If both are unavailable, fall back to user agent string parsing.\n const uaData = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData;\n const isMac = uaData\n ? uaData.platform === \"macOS\"\n : (navigator.platform?.includes(\"Mac\") ?? /Macintosh|Mac OS X/i.test(navigator.userAgent));\n setText(hint, isMac ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n\n this.textarea.addEventListener(\"focus\", () => {\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n this.cancel();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 16px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"popup.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.cancel());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.accent;\n cancelBtn.style.color = this.colors.accent;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:none;background:${this.colors.accentGradient};\n color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:600;cursor:pointer;\n opacity:0.35;pointer-events:none;\n transition:all 0.2s ease;\n box-shadow:0 2px 8px ${this.colors.accentGlow};\n `;\n setText(this.submitBtn, this.t(\"popup.submit\"));\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(hint);\n this.root.appendChild(btnRow);\n document.body.appendChild(this.root);\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n */\n show(rectBounds: DOMRect): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.resolve = resolve;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n // Position: bottom-left of rect, 8px below\n let top = rectBounds.bottom + 8;\n let left = rectBounds.left;\n\n // Collision: flip up if not enough space below\n if (top + 220 > window.innerHeight) {\n top = rectBounds.top - 220 - 8;\n }\n // Collision: flip right if not enough space on left\n if (left + 300 > window.innerWidth) {\n left = rectBounds.right - 300;\n }\n left = Math.max(8, left);\n top = Math.max(8, top);\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n this.root.style.display = \"block\";\n\n // Install focus trap\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea, input, [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n // Trigger animation\n requestAnimationFrame(() => {\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n this.textarea.focus();\n });\n });\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n }\n }\n\n private updateSubmitState(): void {\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (!this.selectedType || !this.textarea.value.trim()) return;\n this.resolve?.({ type: this.selectedType, message: this.textarea.value.trim() });\n this.resolve = null;\n this.hideElement();\n }\n\n private cancel(): void {\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n private hideElement(): void {\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(8px) scale(0.98)\";\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n setTimeout(() => {\n this.root.style.display = \"none\";\n }, 250);\n }\n\n destroy(): void {\n this.root.remove();\n }\n}\n","import type { AnnotationPayload, FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth\n this.overlay = el(\"div\", {\n style: `\n position:fixed;inset:0;\n z-index:${Z_INDEX_MAX - 1};\n background:rgba(15, 23, 42, 0.04);\n cursor:crosshair;\n `,\n });\n this.overlay.setAttribute(\"aria-hidden\", \"true\");\n\n // Toolbar — glassmorphism bar\n this.toolbar = el(\"div\", {\n style: `\n position:fixed;top:0;left:0;right:0;\n z-index:${Z_INDEX_MAX};\n height:52px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border-bottom:1px solid ${this.colors.glassBorder};\n display:flex;align-items:center;justify-content:center;gap:16px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:14px;color:${this.colors.text};\n box-shadow:0 4px 16px ${this.colors.shadow};\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n const dot = el(\"span\", {\n style: `\n width:8px;height:8px;border-radius:50%;\n background:${this.colors.accent};\n box-shadow:0 0 8px ${this.colors.accentGlow};\n animation:pulse 1.5s ease-in-out infinite;\n `,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instruction = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;\" });\n setText(instruction, this.t(\"annotator.instruction\"));\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.deactivate());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instruction);\n this.toolbar.appendChild(cancelBtn);\n\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the pre-activation focused element\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n document.body.appendChild(this.overlay);\n document.body.appendChild(this.toolbar);\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.preActiveFocusElement = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.deactivate();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the element that was focused before activation and creates a full-bounds\n * annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n\n const target = this.preActiveFocusElement;\n if (!target || !(target instanceof HTMLElement)) return;\n\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n const result = await this.popup.show(rectBounds);\n if (!result) return;\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n this.deactivate();\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: result.type,\n message: result.message,\n });\n };\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n transition:box-shadow 0.15s ease;\n `,\n });\n this.overlay?.appendChild(this.drawingRect);\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (touch) await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < 10 || h < 10) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Show popup for type + message\n const result = await this.popup.show(rectBounds);\n\n if (!result) {\n this.drawingRect?.remove();\n this.drawingRect = null;\n return;\n }\n\n // Build annotation payload BEFORE deactivating (needs overlay for elementFromPoint)\n const annotation = this.buildAnnotation(rectBounds);\n this.drawingRect?.remove();\n this.drawingRect = null;\n this.deactivate();\n\n // Emit via event bus (not DOM — overlay is already null after deactivate)\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: result.type,\n message: result.message,\n });\n };\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): AnnotationPayload {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n return {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n }\n destroy(): void {\n this.deactivate();\n this.popup.destroy();\n }\n}\n","import type { FeedbackPayload, FeedbackResponse, FeedbackStatus, FeedbackType } from \"@siteping/core\";\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(\n projectName: string,\n options?: { page?: number; limit?: number; type?: FeedbackType; status?: FeedbackStatus; search?: string },\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\nasync function resilientFetch(url: string, init: RequestInit, retries = MAX_RETRIES): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n\n if (attempt === retries) return response;\n } catch (error) {\n clearTimeout(timeout);\n if (attempt === retries) throw error;\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n\n throw new Error(\"Max retries exceeded\");\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ntype RetryEntry = { endpoint: string; payload: FeedbackPayload };\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n const parsed: unknown = raw ? JSON.parse(raw) : [];\n const queue: RetryEntry[] = Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n } catch {\n // localStorage full or unavailable — silently drop\n }\n });\n}\n\nexport async function flushRetryQueue(endpoint: string): Promise<void> {\n await withRetryLock(async () => {\n try {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return;\n\n const parsed: unknown = JSON.parse(raw);\n const queue: RetryEntry[] = Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n\n const toRetry = queue.filter((e) => e.endpoint === endpoint);\n if (toRetry.length === 0) return;\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n for (const entry of toRetry) {\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(entry.payload),\n });\n if (!res.ok) {\n failed.push(entry);\n }\n } catch {\n failed.push(entry);\n }\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = queue.filter((e) => e.endpoint !== endpoint).concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\nexport class ApiClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n try {\n const response = await resilientFetch(this.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"Unknown error\");\n throw new Error(`Failed to send feedback: ${response.status} ${text}`);\n }\n\n return (await response.json()) as FeedbackResponse; // Server validates via Zod\n } catch (error) {\n queueForRetry(this.endpoint, payload);\n throw error;\n }\n }\n\n async getFeedbacks(\n projectName: string,\n options?: {\n page?: number;\n limit?: number;\n type?: FeedbackType;\n status?: FeedbackStatus;\n search?: string;\n },\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }> {\n const params = new URLSearchParams({ projectName });\n if (options?.page) params.set(\"page\", String(options.page));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.type) params.set(\"type\", options.type);\n if (options?.status) params.set(\"status\", options.status);\n if (options?.search) params.set(\"search\", options.search);\n\n const response = await resilientFetch(`${this.endpoint}?${params.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch feedbacks: ${response.status}`);\n }\n\n return (await response.json()) as { feedbacks: FeedbackResponse[]; total: number }; // Server validates via Zod\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const response = await resilientFetch(this.endpoint, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to update feedback: ${response.status}`);\n }\n\n return (await response.json()) as FeedbackResponse; // Server validates via Zod\n }\n\n async deleteFeedback(id: string): Promise<void> {\n const response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to delete feedback: ${response.status}`);\n }\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n const response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ projectName, deleteAll: true }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to delete all feedbacks: ${response.status}`);\n }\n }\n}\n","type Listener = (...args: unknown[]) => void;\n\n/**\n * Lightweight typed EventEmitter — zero dependencies.\n */\nexport class EventBus<E extends { [K in keyof E]: unknown[] }> {\n private listeners = new Map<keyof E, Set<Listener>>();\n\n on<K extends keyof E>(event: K, listener: (...args: E[K]) => void): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n const set = this.listeners.get(event)!;\n set.add(listener as Listener);\n\n return () => {\n set.delete(listener as Listener);\n };\n }\n\n off<K extends keyof E>(event: K, listener: (...args: E[K]) => void): void {\n const set = this.listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n }\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n fn(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [import(\"@siteping/core\").FeedbackResponse];\n \"feedback:deleted\": [string];\n \"feedback:all-deleted\": [];\n \"feedback:error\": [Error];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [import(\"./annotator.js\").AnnotationComplete];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n/** Subset of WidgetEvents exposed to consumers via SitepingInstance */\nexport interface PublicWidgetEvents {\n \"feedback:sent\": [import(\"@siteping/core\").FeedbackResponse];\n \"feedback:deleted\": [string];\n \"panel:open\": [];\n \"panel:close\": [];\n}\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { ICON_ANNOTATE, ICON_CHAT, ICON_CLOSE, ICON_EYE, ICON_EYE_OFF, ICON_SITEPING } from \"./icons.js\";\n\ninterface RadialItem {\n id: string;\n icon: string;\n iconAlt?: string;\n label: string;\n}\n\nconst ITEM_GAP = 54;\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n const isRight = position === \"bottom-right\";\n\n // Vertical stack above the FAB\n this.items = [\n { id: \"chat\", icon: ICON_CHAT, label: t(\"fab.messages\") },\n { id: \"annotate\", icon: ICON_ANNOTATE, label: t(\"fab.annotate\") },\n { id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF, label: t(\"fab.annotations\") },\n ];\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-label\", t(\"fab.aria\"));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.setAttribute(\"aria-label\", item.label);\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n label.textContent = item.label;\n label.style.cssText = isRight\n ? \"position:absolute; right:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\"\n : \"position:absolute; left:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Close radial menu on click outside.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", this.t(\"fab.badge\").replace(\"{count}\", String(count)));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + ITEM_GAP * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: string): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\":\n this.bus.emit(\"annotation:start\");\n break;\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n if (btn) {\n btn.replaceChildren(parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF));\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick);\n this.root.remove();\n }\n}\n","import type { Translations } from \"./types.js\";\n\nexport const de: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Siteping-Feedback-Panel\",\n \"panel.feedbackList\": \"Feedbackliste\",\n \"panel.loading\": \"Feedbacks werden geladen\",\n \"panel.close\": \"Panel schließen\",\n \"panel.deleteAll\": \"Alle löschen\",\n \"panel.deleteAllConfirmTitle\": \"Alle löschen\",\n \"panel.deleteAllConfirmMessage\":\n \"Alle Feedbacks für dieses Projekt löschen? Diese Aktion kann nicht rückgängig gemacht werden.\",\n \"panel.search\": \"Suchen...\",\n \"panel.searchAria\": \"Feedbacks suchen\",\n \"panel.filterAll\": \"Alle\",\n \"panel.loadError\": \"Laden fehlgeschlagen\",\n \"panel.retry\": \"Erneut versuchen\",\n \"panel.empty\": \"Noch kein Feedback\",\n \"panel.showMore\": \"Mehr anzeigen\",\n \"panel.showLess\": \"Weniger anzeigen\",\n \"panel.resolve\": \"Erledigen\",\n \"panel.reopen\": \"Wieder öffnen\",\n \"panel.delete\": \"Löschen\",\n \"panel.cancel\": \"Abbrechen\",\n \"panel.confirmDelete\": \"Löschen\",\n \"panel.loadMore\": \"Mehr laden ({remaining} verbleibend)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Alle\",\n \"panel.statusOpen\": \"Offen\",\n \"panel.statusResolved\": \"Erledigt\",\n\n // Feedback type labels\n \"type.label\": \"Typ\",\n \"type.question\": \"Frage\",\n \"type.change\": \"Änderung\",\n \"type.bug\": \"Fehler\",\n \"type.other\": \"Sonstiges\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Feedback-Menü\",\n \"fab.messages\": \"Nachrichten\",\n \"fab.annotate\": \"Kommentieren\",\n \"fab.annotations\": \"Anmerkungen\",\n\n // Annotator\n \"annotator.instruction\": \"Zeichne ein Rechteck um den Bereich, den du kommentieren möchtest\",\n \"annotator.cancel\": \"Abbrechen\",\n\n // Popup\n \"popup.ariaLabel\": \"Feedbackformular\",\n \"popup.placeholder\": \"Beschreibe dein Feedback...\",\n \"popup.textareaAria\": \"Feedbacknachricht\",\n \"popup.submitHintMac\": \"⌘+Enter zum Senden\",\n \"popup.submitHintOther\": \"Strg+Enter zum Senden\",\n \"popup.cancel\": \"Abbrechen\",\n \"popup.submit\": \"Senden\",\n\n // Identity modal\n \"identity.title\": \"Identifiziere dich\",\n \"identity.nameLabel\": \"Name\",\n \"identity.namePlaceholder\": \"Dein Name\",\n \"identity.emailLabel\": \"E-Mail\",\n \"identity.emailPlaceholder\": \"deine@email.de\",\n \"identity.cancel\": \"Abbrechen\",\n \"identity.submit\": \"Fortfahren\",\n\n // Markers\n \"marker.approximate\": \"Ungefähre Position (Konfidenz: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} unerledigte Feedbacks\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback erfolgreich gesendet\",\n \"feedback.error.message\": \"Feedback konnte nicht gesendet werden\",\n \"feedback.deleted.confirmation\": \"Feedback gelöscht\",\n\n // Badge\n \"badge.count\": \"{count} unerledigte Feedbacks\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const en: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Siteping feedback panel\",\n \"panel.feedbackList\": \"Feedback list\",\n \"panel.loading\": \"Loading feedbacks\",\n \"panel.close\": \"Close panel\",\n \"panel.deleteAll\": \"Delete all\",\n \"panel.deleteAllConfirmTitle\": \"Delete all\",\n \"panel.deleteAllConfirmMessage\": \"Delete all feedbacks for this project? This action cannot be undone.\",\n \"panel.search\": \"Search...\",\n \"panel.searchAria\": \"Search feedbacks\",\n \"panel.filterAll\": \"All\",\n \"panel.loadError\": \"Failed to load\",\n \"panel.retry\": \"Retry\",\n \"panel.empty\": \"No feedback yet\",\n \"panel.showMore\": \"Show more\",\n \"panel.showLess\": \"Show less\",\n \"panel.resolve\": \"Resolve\",\n \"panel.reopen\": \"Reopen\",\n \"panel.delete\": \"Delete\",\n \"panel.cancel\": \"Cancel\",\n \"panel.confirmDelete\": \"Delete\",\n \"panel.loadMore\": \"Load more ({remaining} remaining)\",\n\n // Status filter labels\n \"panel.statusAll\": \"All\",\n \"panel.statusOpen\": \"Open\",\n \"panel.statusResolved\": \"Resolved\",\n\n // Feedback type labels\n \"type.label\": \"Type\",\n \"type.question\": \"Question\",\n \"type.change\": \"Change\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Other\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // FAB menu\n \"fab.aria\": \"Siteping \\u2014 Feedback menu\",\n \"fab.messages\": \"Messages\",\n \"fab.annotate\": \"Annotate\",\n \"fab.annotations\": \"Annotations\",\n\n // Annotator\n \"annotator.instruction\": \"Draw a rectangle on the area to comment\",\n \"annotator.cancel\": \"Cancel\",\n\n // Popup\n \"popup.ariaLabel\": \"Feedback form\",\n \"popup.placeholder\": \"Describe your feedback...\",\n \"popup.textareaAria\": \"Feedback message\",\n \"popup.submitHintMac\": \"\\u2318+Enter to send\",\n \"popup.submitHintOther\": \"Ctrl+Enter to send\",\n \"popup.cancel\": \"Cancel\",\n \"popup.submit\": \"Send\",\n\n // Identity modal\n \"identity.title\": \"Identify yourself\",\n \"identity.nameLabel\": \"Name\",\n \"identity.namePlaceholder\": \"Your name\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"your@email.com\",\n \"identity.cancel\": \"Cancel\",\n \"identity.submit\": \"Continue\",\n\n // Markers\n \"marker.approximate\": \"Approximate position (confidence: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} unresolved feedbacks\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback sent successfully\",\n \"feedback.error.message\": \"Failed to send feedback\",\n \"feedback.deleted.confirmation\": \"Feedback deleted\",\n\n // Badge\n \"badge.count\": \"{count} unresolved feedbacks\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const es: Translations = {\n // Panel\n \"panel.title\": \"Comentarios\",\n \"panel.ariaLabel\": \"Panel de comentarios de Siteping\",\n \"panel.feedbackList\": \"Lista de comentarios\",\n \"panel.loading\": \"Cargando comentarios\",\n \"panel.close\": \"Cerrar panel\",\n \"panel.deleteAll\": \"Eliminar todo\",\n \"panel.deleteAllConfirmTitle\": \"Eliminar todo\",\n \"panel.deleteAllConfirmMessage\":\n \"¿Eliminar todos los comentarios de este proyecto? Esta acción no se puede deshacer.\",\n \"panel.search\": \"Buscar...\",\n \"panel.searchAria\": \"Buscar comentarios\",\n \"panel.filterAll\": \"Todos\",\n \"panel.loadError\": \"No se pudo cargar\",\n \"panel.retry\": \"Reintentar\",\n \"panel.empty\": \"Aún no hay comentarios\",\n \"panel.showMore\": \"Mostrar más\",\n \"panel.showLess\": \"Mostrar menos\",\n \"panel.resolve\": \"Resolver\",\n \"panel.reopen\": \"Reabrir\",\n \"panel.delete\": \"Eliminar\",\n \"panel.cancel\": \"Cancelar\",\n \"panel.confirmDelete\": \"Eliminar\",\n \"panel.loadMore\": \"Cargar más ({remaining} restantes)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Todos\",\n \"panel.statusOpen\": \"Abiertos\",\n \"panel.statusResolved\": \"Resueltos\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Pregunta\",\n \"type.change\": \"Cambio\",\n \"type.bug\": \"Error\",\n \"type.other\": \"Otro\",\n\n // Status segmented control label\n \"status.label\": \"Estado\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menú de comentarios\",\n \"fab.messages\": \"Mensajes\",\n \"fab.annotate\": \"Anotar\",\n \"fab.annotations\": \"Anotaciones\",\n\n // Annotator\n \"annotator.instruction\": \"Dibuja un rectángulo sobre el área que quieres comentar\",\n \"annotator.cancel\": \"Cancelar\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulario de comentarios\",\n \"popup.placeholder\": \"Describe tu comentario...\",\n \"popup.textareaAria\": \"Mensaje de comentario\",\n \"popup.submitHintMac\": \"⌘+Enter para enviar\",\n \"popup.submitHintOther\": \"Ctrl+Enter para enviar\",\n \"popup.cancel\": \"Cancelar\",\n \"popup.submit\": \"Enviar\",\n\n // Identity modal\n \"identity.title\": \"Identifícate\",\n \"identity.nameLabel\": \"Nombre\",\n \"identity.namePlaceholder\": \"Tu nombre\",\n \"identity.emailLabel\": \"Correo electrónico\",\n \"identity.emailPlaceholder\": \"tu@email.com\",\n \"identity.cancel\": \"Cancelar\",\n \"identity.submit\": \"Continuar\",\n\n // Markers\n \"marker.approximate\": \"Posición aproximada (confianza: {confidence}%)\",\n \"marker.aria\": \"Comentario #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} comentarios sin resolver\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Comentario enviado correctamente\",\n \"feedback.error.message\": \"No se pudo enviar el comentario\",\n \"feedback.deleted.confirmation\": \"Comentario eliminado\",\n\n // Badge\n \"badge.count\": \"{count} comentarios sin resolver\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const fr: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Panneau de feedback Siteping\",\n \"panel.feedbackList\": \"Liste des feedbacks\",\n \"panel.loading\": \"Chargement des feedbacks\",\n \"panel.close\": \"Fermer le panneau\",\n \"panel.deleteAll\": \"Tout supprimer\",\n \"panel.deleteAllConfirmTitle\": \"Tout supprimer\",\n \"panel.deleteAllConfirmMessage\": \"Supprimer tous les feedbacks de ce projet ? Cette action est irr\\u00e9versible.\",\n \"panel.search\": \"Rechercher...\",\n \"panel.searchAria\": \"Rechercher dans les feedbacks\",\n \"panel.filterAll\": \"Tous\",\n \"panel.loadError\": \"Erreur de chargement\",\n \"panel.retry\": \"R\\u00e9essayer\",\n \"panel.empty\": \"Aucun feedback pour le moment\",\n \"panel.showMore\": \"Voir plus\",\n \"panel.showLess\": \"Voir moins\",\n \"panel.resolve\": \"R\\u00e9soudre\",\n \"panel.reopen\": \"Rouvrir\",\n \"panel.delete\": \"Supprimer\",\n \"panel.cancel\": \"Annuler\",\n \"panel.confirmDelete\": \"Supprimer\",\n \"panel.loadMore\": \"Voir plus ({remaining} restants)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Tous\",\n \"panel.statusOpen\": \"Ouvert\",\n \"panel.statusResolved\": \"Résolu\",\n\n // Feedback type labels\n \"type.label\": \"Type\",\n \"type.question\": \"Question\",\n \"type.change\": \"Changement\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Autre\",\n\n // Status segmented control label\n \"status.label\": \"Statut\",\n\n // FAB menu\n \"fab.aria\": \"Siteping \\u2014 Menu feedback\",\n \"fab.messages\": \"Messages\",\n \"fab.annotate\": \"Annoter\",\n \"fab.annotations\": \"Annotations\",\n\n // Annotator\n \"annotator.instruction\": \"Tracez un rectangle sur la zone \\u00e0 commenter\",\n \"annotator.cancel\": \"Annuler\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulaire de feedback\",\n \"popup.placeholder\": \"D\\u00e9crivez votre retour...\",\n \"popup.textareaAria\": \"Message de feedback\",\n \"popup.submitHintMac\": \"\\u2318+Entr\\u00e9e pour envoyer\",\n \"popup.submitHintOther\": \"Ctrl+Entr\\u00e9e pour envoyer\",\n \"popup.cancel\": \"Annuler\",\n \"popup.submit\": \"Envoyer\",\n\n // Identity modal\n \"identity.title\": \"Identifiez-vous\",\n \"identity.nameLabel\": \"Nom\",\n \"identity.namePlaceholder\": \"Votre nom\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"votre@email.com\",\n \"identity.cancel\": \"Annuler\",\n \"identity.submit\": \"Continuer\",\n\n // Markers\n \"marker.approximate\": \"Position approximative (confiance : {confidence}%)\",\n \"marker.aria\": \"Feedback n°{number} : {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedbacks non résolus\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback envoyé avec succès\",\n \"feedback.error.message\": \"Échec de l'envoi du feedback\",\n \"feedback.deleted.confirmation\": \"Feedback supprimé\",\n\n // Badge\n \"badge.count\": \"{count} feedbacks non résolus\",\n};\n","import type { Translations } from \"./types.js\";\n\n/** Italian translations (it-IT). */\nexport const it: Translations = {\n // Panel\n \"panel.title\": \"Feedback\",\n \"panel.ariaLabel\": \"Pannello feedback di Siteping\",\n \"panel.feedbackList\": \"Elenco feedback\",\n \"panel.loading\": \"Caricamento feedback\",\n \"panel.close\": \"Chiudi pannello\",\n \"panel.deleteAll\": \"Elimina tutto\",\n \"panel.deleteAllConfirmTitle\": \"Elimina tutto\",\n \"panel.deleteAllConfirmMessage\":\n \"Eliminare tutti i feedback per questo progetto? Questa azione non può essere annullata.\",\n \"panel.search\": \"Cerca...\",\n \"panel.searchAria\": \"Cerca feedback\",\n \"panel.filterAll\": \"Tutti\",\n \"panel.loadError\": \"Caricamento non riuscito\",\n \"panel.retry\": \"Riprova\",\n \"panel.empty\": \"Nessun feedback ancora\",\n \"panel.showMore\": \"Mostra di più\",\n \"panel.showLess\": \"Mostra meno\",\n \"panel.resolve\": \"Risolvi\",\n \"panel.reopen\": \"Riapri\",\n \"panel.delete\": \"Elimina\",\n \"panel.cancel\": \"Annulla\",\n \"panel.confirmDelete\": \"Elimina\",\n \"panel.loadMore\": \"Carica altro ({remaining} rimanenti)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Tutti\",\n \"panel.statusOpen\": \"Aperti\",\n \"panel.statusResolved\": \"Risolti\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Domanda\",\n \"type.change\": \"Modifica\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Altro\",\n\n // Status segmented control label\n \"status.label\": \"Stato\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menu feedback\",\n \"fab.messages\": \"Messaggi\",\n \"fab.annotate\": \"Annota\",\n \"fab.annotations\": \"Annotazioni\",\n\n // Annotator\n \"annotator.instruction\": \"Disegna un rettangolo sull'area da commentare\",\n \"annotator.cancel\": \"Annulla\",\n\n // Popup\n \"popup.ariaLabel\": \"Modulo feedback\",\n \"popup.placeholder\": \"Descrivi il tuo feedback...\",\n \"popup.textareaAria\": \"Messaggio di feedback\",\n \"popup.submitHintMac\": \"⌘+Invio per inviare\",\n \"popup.submitHintOther\": \"Ctrl+Invio per inviare\",\n \"popup.cancel\": \"Annulla\",\n \"popup.submit\": \"Invia\",\n\n // Identity modal\n \"identity.title\": \"Identificati\",\n \"identity.nameLabel\": \"Nome\",\n \"identity.namePlaceholder\": \"Il tuo nome\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"tua@email.com\",\n \"identity.cancel\": \"Annulla\",\n \"identity.submit\": \"Continua\",\n\n // Markers\n \"marker.approximate\": \"Posizione approssimativa (confidenza: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedback non risolti\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback inviato con successo\",\n \"feedback.error.message\": \"Invio del feedback non riuscito\",\n \"feedback.deleted.confirmation\": \"Feedback eliminato\",\n\n // Badge\n \"badge.count\": \"{count} feedback non risolti\",\n};\n","import type { Translations } from \"./types.js\";\n\n/** Brazilian Portuguese translations (pt-BR). */\nexport const pt: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Painel de feedback do Siteping\",\n \"panel.feedbackList\": \"Lista de feedbacks\",\n \"panel.loading\": \"Carregando feedbacks\",\n \"panel.close\": \"Fechar painel\",\n \"panel.deleteAll\": \"Excluir tudo\",\n \"panel.deleteAllConfirmTitle\": \"Excluir tudo\",\n \"panel.deleteAllConfirmMessage\": \"Excluir todos os feedbacks deste projeto? Esta ação não pode ser desfeita.\",\n \"panel.search\": \"Pesquisar...\",\n \"panel.searchAria\": \"Pesquisar feedbacks\",\n \"panel.filterAll\": \"Todos\",\n \"panel.loadError\": \"Falha ao carregar\",\n \"panel.retry\": \"Tentar novamente\",\n \"panel.empty\": \"Nenhum feedback ainda\",\n \"panel.showMore\": \"Mostrar mais\",\n \"panel.showLess\": \"Mostrar menos\",\n \"panel.resolve\": \"Resolver\",\n \"panel.reopen\": \"Reabrir\",\n \"panel.delete\": \"Excluir\",\n \"panel.cancel\": \"Cancelar\",\n \"panel.confirmDelete\": \"Excluir\",\n \"panel.loadMore\": \"Carregar mais ({remaining} restantes)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Todos\",\n \"panel.statusOpen\": \"Abertos\",\n \"panel.statusResolved\": \"Resolvidos\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Pergunta\",\n \"type.change\": \"Alteração\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Outro\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menu de feedback\",\n \"fab.messages\": \"Mensagens\",\n \"fab.annotate\": \"Anotar\",\n \"fab.annotations\": \"Anotações\",\n\n // Annotator\n \"annotator.instruction\": \"Desenhe um retângulo na área que deseja comentar\",\n \"annotator.cancel\": \"Cancelar\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulário de feedback\",\n \"popup.placeholder\": \"Descreva seu feedback...\",\n \"popup.textareaAria\": \"Mensagem de feedback\",\n \"popup.submitHintMac\": \"⌘+Enter para enviar\",\n \"popup.submitHintOther\": \"Ctrl+Enter para enviar\",\n \"popup.cancel\": \"Cancelar\",\n \"popup.submit\": \"Enviar\",\n\n // Identity modal\n \"identity.title\": \"Identifique-se\",\n \"identity.nameLabel\": \"Nome\",\n \"identity.namePlaceholder\": \"Seu nome\",\n \"identity.emailLabel\": \"E-mail\",\n \"identity.emailPlaceholder\": \"seu@email.com\",\n \"identity.cancel\": \"Cancelar\",\n \"identity.submit\": \"Continuar\",\n\n // Markers\n \"marker.approximate\": \"Posição aproximada (confiança: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedbacks não resolvidos\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback enviado com sucesso\",\n \"feedback.error.message\": \"Falha ao enviar feedback\",\n \"feedback.deleted.confirmation\": \"Feedback excluído\",\n\n // Badge\n \"badge.count\": \"{count} feedbacks não resolvidos\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const ru: Translations = {\n // Panel\n \"panel.title\": \"Обратная связь\",\n \"panel.ariaLabel\": \"Панель обратной связи Siteping\",\n \"panel.feedbackList\": \"Список отзывов\",\n \"panel.loading\": \"Загрузка отзывов\",\n \"panel.close\": \"Закрыть панель\",\n \"panel.deleteAll\": \"Удалить всё\",\n \"panel.deleteAllConfirmTitle\": \"Удалить всё\",\n \"panel.deleteAllConfirmMessage\": \"Удалить все отзывы этого проекта? Это действие необратимо.\",\n \"panel.search\": \"Поиск...\",\n \"panel.searchAria\": \"Поиск по отзывам\",\n \"panel.filterAll\": \"Все\",\n \"panel.loadError\": \"Ошибка загрузки\",\n \"panel.retry\": \"Повторить\",\n \"panel.empty\": \"Пока нет отзывов\",\n \"panel.showMore\": \"Показать больше\",\n \"panel.showLess\": \"Показать меньше\",\n \"panel.resolve\": \"Решено\",\n \"panel.reopen\": \"Открыть заново\",\n \"panel.delete\": \"Удалить\",\n \"panel.cancel\": \"Отмена\",\n \"panel.confirmDelete\": \"Удалить\",\n \"panel.loadMore\": \"Показать ещё ({remaining} осталось)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Все\",\n \"panel.statusOpen\": \"Открытые\",\n \"panel.statusResolved\": \"Решённые\",\n\n // Feedback type labels\n \"type.label\": \"Тип\",\n \"type.question\": \"Вопрос\",\n \"type.change\": \"Улучшение\",\n \"type.bug\": \"Баг\",\n \"type.other\": \"Другое\",\n\n // Status segmented control label\n \"status.label\": \"Статус\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Меню обратной связи\",\n \"fab.messages\": \"Сообщения\",\n \"fab.annotate\": \"Аннотация\",\n \"fab.annotations\": \"Аннотации\",\n\n // Annotator\n \"annotator.instruction\": \"Выделите область для комментария\",\n \"annotator.cancel\": \"Отмена\",\n\n // Popup\n \"popup.ariaLabel\": \"Форма обратной связи\",\n \"popup.placeholder\": \"Опишите проблему или предложение...\",\n \"popup.textareaAria\": \"Сообщение\",\n \"popup.submitHintMac\": \"⌘+Enter — отправить\",\n \"popup.submitHintOther\": \"Ctrl+Enter — отправить\",\n \"popup.cancel\": \"Отмена\",\n \"popup.submit\": \"Отправить\",\n\n // Identity modal\n \"identity.title\": \"Представьтесь\",\n \"identity.nameLabel\": \"Имя\",\n \"identity.namePlaceholder\": \"Ваше имя\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"ваш@email.com\",\n \"identity.cancel\": \"Отмена\",\n \"identity.submit\": \"Продолжить\",\n\n // Markers\n \"marker.approximate\": \"Приблизительная позиция (точность: {confidence}%)\",\n \"marker.aria\": \"Отзыв #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"Нерешённых отзывов: {count}\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Отзыв успешно отправлен\",\n \"feedback.error.message\": \"Не удалось отправить отзыв\",\n \"feedback.deleted.confirmation\": \"Отзыв удалён\",\n\n // Badge\n \"badge.count\": \"Нерешённых отзывов: {count}\",\n};\n","import type { TFunction, Translations } from \"./types.js\";\n\nexport type { TFunction, Translations } from \"./types.js\";\n\n// Static imports — bundler (tsup) will include them all.\n// For tree-shaking in consumer apps, use dynamic import() with a bundler plugin.\nimport { de } from \"./de.js\";\nimport { en } from \"./en.js\";\nimport { es } from \"./es.js\";\nimport { fr } from \"./fr.js\";\nimport { it } from \"./it.js\";\nimport { pt } from \"./pt.js\";\nimport { ru } from \"./ru.js\";\n\nconst LOCALES: Record<string, Translations> = { de, en, es, fr, it, pt, ru };\n\n/** Register a custom locale at runtime. */\nexport function registerLocale(code: string, translations: Translations): void {\n LOCALES[code] = translations;\n}\n\n/**\n * Create a translation function for the given locale.\n *\n * Locale resolution: exact match > language prefix > English fallback.\n */\nexport function createT(locale: string): TFunction {\n const lang = (locale.split(\"-\")[0] ?? locale).toLowerCase();\n if (!LOCALES[lang]) {\n console.warn(`[siteping] Unknown locale \"${locale}\", falling back to \"en\"`);\n }\n const dict = LOCALES[lang] ?? LOCALES.en ?? ({} as Translations);\n return (key) => dict[key] ?? key;\n}\n\n/**\n * Returns the type label for a FeedbackType value.\n * Maps API enum values (english) to localized display labels.\n */\nexport function getTypeLabel(type: string, t: TFunction): string {\n switch (type) {\n case \"question\":\n return t(\"type.question\");\n case \"change\":\n return t(\"type.change\");\n case \"bug\":\n return t(\"type.bug\");\n case \"other\":\n return t(\"type.other\");\n default:\n return type;\n }\n}\n","const STORAGE_KEY = \"siteping_identity\";\n\nexport interface Identity {\n name: string;\n email: string;\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"name\" in parsed &&\n typeof (parsed as Record<string, unknown>).name === \"string\" &&\n \"email\" in parsed &&\n typeof (parsed as Record<string, unknown>).email === \"string\"\n ) {\n const identity = parsed as Identity;\n if (identity.name && identity.email) return identity;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n * Uses Levenshtein distance, optimized for short strings (~50 chars).\n */\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are valid: i-1 in [0, aLen-1], j-1 in [0, bLen-1], loop bounds guarantee access\n const prevDiag = prev[i - 1] ?? 0;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] ?? 0, curr[i - 1] ?? 0);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] ?? 0; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Slides a window of `needle.length` over the haystack and returns the best\n * similarity score found. Returns 0 if below `minScore`.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const nLen = needle.length;\n\n // If needle is longer than haystack, compare directly\n if (nLen > haystack.length) {\n const score = similarity(haystack, needle);\n return score >= minScore ? score : 0;\n }\n\n let best = 0;\n\n // Cap haystack to avoid O(n²) on huge text nodes\n const capped = haystack.length > 500 ? haystack.slice(0, 500) : haystack;\n const limit = capped.length - nLen;\n\n for (let i = 0; i <= limit; i++) {\n const window = capped.slice(i, i + nLen);\n const score = similarity(window, needle);\n if (score > best) best = score;\n if (best >= 0.95) break;\n }\n\n return best >= minScore ? best : 0;\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { scoreFingerprint } from \"./fingerprint.js\";\nimport { fuzzyIncludes, similarity } from \"./fuzzy.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\n\nexport type ResolutionStrategy = \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/** Max elements to scan during smart fallback. */\nconst MAX_SCAN_CANDIDATES = 300;\n\n/** Minimum fuzzy text match score for CSS/XPath verification. */\nconst TEXT_MATCH_THRESHOLD = 0.3;\n\n/**\n * Verify that a resolved element's text content matches the stored snippet.\n * If no snippet is stored, returns true (no verification possible).\n * Uses fuzzy matching to tolerate minor text changes.\n */\nfunction textMatches(el: Element, anchor: AnchorData): boolean {\n if (!anchor.textSnippet) return true;\n const text = (el.textContent?.trim() ?? \"\").slice(0, 500);\n return fuzzyIncludes(text, anchor.textSnippet, 0.5) > TEXT_MATCH_THRESHOLD;\n}\n\n/**\n * Re-anchor an annotation using a multi-level fallback strategy\n * with text verification and confidence scoring.\n *\n * Resolution order:\n * 1. getElementById + text verification — confidence 1.0\n * 2. CSS selector + text verification — confidence 0.95\n * 3. XPath + text verification — confidence 0.9\n * 4. Smart scan (fingerprint + text + prefix/suffix + neighbor) — up to 0.85\n *\n * Text verification prevents false matches when DOM elements are reordered.\n * Returns null if all strategies fail (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData): AnchorResolution | null {\n // Level 1: Element ID (most stable, still verify text)\n if (anchor.elementId) {\n const el = document.getElementById(anchor.elementId);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 1.0, strategy: \"id\" };\n }\n }\n\n // Level 2: CSS Selector (with text verification)\n try {\n const el = document.querySelector(anchor.cssSelector);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.95, strategy: \"css\" };\n }\n } catch {\n // Invalid selector — skip\n }\n\n // Level 3: XPath (with text verification)\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n const el = result.singleNodeValue;\n if (el instanceof Element && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.9, strategy: \"xpath\" };\n }\n } catch {\n // Invalid XPath — skip\n }\n\n // Level 4: Smart scan — combine all available signals\n return smartScan(anchor);\n}\n\n/**\n * Scan DOM elements by tag and score each candidate using multiple signals:\n * fingerprint, text similarity, prefix/suffix context, neighbor text.\n *\n * Returns the best candidate above a 0.4 threshold, capped at 0.85 confidence\n * (smart scan is never 100% certain).\n */\nfunction smartScan(anchor: AnchorData): AnchorResolution | null {\n const tag = anchor.elementTag.toLowerCase();\n const candidates = document.querySelectorAll(tag);\n if (candidates.length === 0) return null;\n\n let bestElement: Element | null = null;\n let bestScore = 0;\n\n const limit = Math.min(candidates.length, MAX_SCAN_CANDIDATES);\n\n for (let i = 0; i < limit; i++) {\n const el = candidates[i];\n if (!el) continue;\n const score = scoreCandidate(el, anchor);\n if (score > bestScore) {\n bestScore = score;\n bestElement = el;\n if (bestScore >= 0.85) break;\n }\n }\n\n if (!bestElement || bestScore < 0.4) return null;\n\n return {\n element: bestElement,\n confidence: Math.min(bestScore, 0.85),\n strategy: \"scan\",\n };\n}\n\n/**\n * Score a candidate element against all stored anchor signals.\n *\n * Dynamic weighting — only active signals contribute, then normalized:\n * - Text snippet (fuzzy substring match): weight 40 (most reliable for reordering)\n * - Fingerprint (structural match): weight 20\n * - Prefix/suffix context: weight 20\n * - Neighbor text: weight 20\n */\nfunction scoreCandidate(candidate: Element, anchor: AnchorData): number {\n let score = 0;\n let totalWeight = 0;\n\n // Truncate to avoid O(n*m) explosion on huge text nodes\n const candidateText = (candidate.textContent?.trim() ?? \"\").slice(0, 500);\n\n // --- Text snippet (weight 40 — most important for reordered elements) ---\n if (anchor.textSnippet) {\n totalWeight += 40;\n score += fuzzyIncludes(candidateText, anchor.textSnippet, 0.5) * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (anchor.fingerprint) {\n totalWeight += 20;\n score += scoreFingerprint(candidate, anchor.fingerprint) * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (anchor.textPrefix || anchor.textSuffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (anchor.textPrefix) {\n const prevText = adjacentText(candidate, \"before\");\n contextScore += prevText ? similarity(prevText, anchor.textPrefix) : 0;\n contextParts++;\n }\n\n if (anchor.textSuffix) {\n const nextText = adjacentText(candidate, \"after\");\n contextScore += nextText ? similarity(nextText, anchor.textSuffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n score += (contextScore / contextParts) * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (anchor.neighborText) {\n totalWeight += 20;\n const candidateNeighbor = neighborText(candidate);\n score += candidateNeighbor ? similarity(candidateNeighbor, anchor.neighborText) * 20 : 0;\n }\n\n return totalWeight > 0 ? score / totalWeight : 0;\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(anchor: AnchorData, rect: RectData): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import type { AnchorData, FeedbackResponse, RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): { top: number; left: number } {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n elements: HTMLElement[];\n baseTop: number;\n baseLeft: number;\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n\n get count(): number {\n return this.entries.length;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition();\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition();\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant changes.\n // Fast-path: large batches (>20 mutations) skip per-record filtering.\n this.mutationObserver = new MutationObserver((mutations) => {\n if (mutations.length > 20) {\n this.scheduleReposition();\n return;\n }\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition();\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters);\n }\n\n private scheduleReposition(): void {\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n if (cachedEl?.isConnected) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else {\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n }\n\n if (!resolved) {\n markerEl.style.display = \"none\";\n continue;\n }\n\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n\n this.applyClusterPositions();\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], baseTop: 0, baseLeft: 0 };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n const marker = this.createMarker(index, feedback, pos);\n this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n this.container.appendChild(marker);\n entry.elements.push(marker);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n const allItems: { entry: MarkerEntry; elIdx: number }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n allItems.push({ entry, elIdx: i });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.entry;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.entry;\n const dist = Math.sqrt((a.baseLeft - b.baseLeft) ** 2 + (a.baseTop - b.baseTop) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(b);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: `\n position:absolute;top:-6px;right:-6px;\n min-width:16px;height:16px;padding:0 4px;\n border-radius:9999px;\n background:${this.colors.accent};color:#fff;\n font-size:10px;font-weight:700;\n display:flex;align-items:center;justify-content:center;\n border:1.5px solid #fff;\n pointer-events:none;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n line-height:1;\n `,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = feedback.status === \"resolved\";\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = this.t(\"marker.approximate\").replace(\"{confidence}\", String(Math.round(confidence * 100)));\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n const isResolved = feedback.status === \"resolved\";\n\n const marker = el(\"div\", {\n style: `\n position:absolute;\n top:${pos.top}px;\n left:${pos.left}px;\n width:26px;height:26px;\n border-radius:50%;\n background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};\n border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};\n display:flex;align-items:center;justify-content:center;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:11px;font-weight:700;\n color:${isResolved ? \"#94a3b8\" : typeColor};\n cursor:pointer;pointer-events:auto;\n box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};\n transition:top 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.15s ease, box-shadow 0.15s ease;\n user-select:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = this.t(\"marker.aria\")\n .replace(\"{number}\", String(number))\n .replace(\"{type}\", getTypeLabel(feedback.type, this.t))\n .replace(\"{message}\", truncatedMessage);\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: `\n position:absolute;\n top:${rect.top + window.scrollY}px;\n left:${rect.left + window.scrollX}px;\n width:${rect.width}px;height:${rect.height}px;\n border:2px solid ${typeColor};\n background:${typeColor}0c;\n border-radius:8px;\n pointer-events:none;z-index:-1;\n opacity:0;\n box-shadow:0 0 16px ${typeColor}20;\n transition:opacity ${HIGHLIGHT_FADE}ms ease;\n `,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_EXPORT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>`;\n\nconst ICON_CSV = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`;\n\nconst ICON_JSON = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 3H6a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2 2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h2\"/><path d=\"M16 3h2a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2 2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// i18n\n// ---------------------------------------------------------------------------\n\nexport const EXPORT_I18N_EN = {\n \"export.label\": \"Export\",\n \"export.csv\": \"Export CSV\",\n \"export.json\": \"Export JSON\",\n};\n\nexport const EXPORT_I18N_FR = {\n \"export.label\": \"Exporter\",\n \"export.csv\": \"Exporter CSV\",\n \"export.json\": \"Exporter JSON\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const EXPORT_CSS = `\n /* ============================\n Export Button & Menu\n ============================ */\n\n .sp-export-btn {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .sp-export-btn svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-export-btn:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-export-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-export-menu {\n position: absolute;\n top: calc(100% + 6px);\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-lg);\n z-index: 10;\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n transition: opacity 0.15s ease, transform 0.15s ease;\n pointer-events: none;\n }\n\n .sp-export-menu--open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .sp-export-option {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 16px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n }\n\n .sp-export-option:hover,\n .sp-export-option:focus-visible {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n .sp-export-option-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .sp-export-option-icon svg {\n width: 16px;\n height: 16px;\n }\n\n .sp-export-option-label {\n flex: 1;\n }\n\n @media (forced-colors: active) {\n .sp-export-btn,\n .sp-export-option,\n .sp-export-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-export-btn:focus-visible,\n .sp-export-option:focus-visible {\n outline: 3px solid Highlight !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// CSV / JSON conversion\n// ---------------------------------------------------------------------------\n\nconst CSV_COLUMNS = [\n \"id\",\n \"type\",\n \"status\",\n \"message\",\n \"url\",\n \"authorName\",\n \"authorEmail\",\n \"createdAt\",\n \"resolvedAt\",\n \"viewport\",\n] as const;\n\n/** Escape a value for CSV: wrap in double-quotes if it contains commas, newlines, or quotes. */\nfunction escapeCsvField(value: string): string {\n if (value.includes('\"') || value.includes(\",\") || value.includes(\"\\n\") || value.includes(\"\\r\")) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n/** Convert feedbacks to CSV string */\nexport function feedbacksToCsv(feedbacks: FeedbackResponse[]): string {\n const header = CSV_COLUMNS.join(\",\");\n const rows = feedbacks.map((fb) =>\n CSV_COLUMNS.map((col) => {\n const raw = fb[col];\n return escapeCsvField(raw == null ? \"\" : String(raw));\n }).join(\",\"),\n );\n return [header, ...rows].join(\"\\n\");\n}\n\n/** Convert feedbacks to formatted JSON string */\nexport function feedbacksToJson(feedbacks: FeedbackResponse[]): string {\n return JSON.stringify(feedbacks, null, 2);\n}\n\n// ---------------------------------------------------------------------------\n// Download helper\n// ---------------------------------------------------------------------------\n\n/** Trigger browser download of a string as file */\nexport function downloadFile(content: string, filename: string, mimeType: string): void {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = filename;\n anchor.style.display = \"none\";\n document.body.appendChild(anchor);\n anchor.click();\n // Clean up after a tick to ensure the download starts\n requestAnimationFrame(() => {\n URL.revokeObjectURL(url);\n anchor.remove();\n });\n}\n\n// ---------------------------------------------------------------------------\n// ExportButton component\n// ---------------------------------------------------------------------------\n\nexport class ExportButton {\n readonly element: HTMLElement;\n\n private menu: HTMLElement;\n private isOpen = false;\n private onDocumentClick: (e: MouseEvent) => void;\n\n constructor(\n _colors: ThemeColors,\n private readonly getFeedbacks: () => FeedbackResponse[],\n ) {\n // Wrapper for relative positioning of the menu\n this.element = el(\"div\", { style: \"position: relative; display: inline-flex;\" });\n\n // Trigger button — matches .sp-btn-delete-all pill style\n const btn = document.createElement(\"button\");\n btn.className = \"sp-export-btn\";\n btn.setAttribute(\"aria-haspopup\", \"true\");\n btn.setAttribute(\"aria-expanded\", \"false\");\n btn.appendChild(parseSvg(ICON_EXPORT));\n const label = document.createElement(\"span\");\n setText(label, EXPORT_I18N_EN[\"export.label\"]);\n btn.appendChild(label);\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggle();\n });\n\n // Dropdown menu\n this.menu = el(\"div\", { class: \"sp-export-menu\" });\n this.menu.setAttribute(\"role\", \"menu\");\n\n // CSV option\n const csvOption = this.createOption(ICON_CSV, EXPORT_I18N_EN[\"export.csv\"], () => {\n this.exportAs(\"csv\");\n });\n\n // JSON option\n const jsonOption = this.createOption(ICON_JSON, EXPORT_I18N_EN[\"export.json\"], () => {\n this.exportAs(\"json\");\n });\n\n this.menu.appendChild(csvOption);\n this.menu.appendChild(jsonOption);\n\n this.element.appendChild(btn);\n this.element.appendChild(this.menu);\n\n // Close on outside click\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !this.element.contains(e.target as Node)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick, true);\n }\n\n /** Update the button label (used for i18n switching) */\n setLabels(labels: typeof EXPORT_I18N_EN): void {\n const btn = this.element.querySelector<HTMLElement>(\".sp-export-btn\");\n if (btn) {\n const span = btn.querySelector(\"span\");\n if (span) setText(span, labels[\"export.label\"]);\n }\n\n const options = this.menu.querySelectorAll<HTMLElement>(\".sp-export-option-label\");\n if (options[0]) setText(options[0], labels[\"export.csv\"]);\n if (options[1]) setText(options[1], labels[\"export.json\"]);\n }\n\n private createOption(iconSvg: string, labelText: string, onClick: () => void): HTMLButtonElement {\n const option = document.createElement(\"button\");\n option.className = \"sp-export-option\";\n option.setAttribute(\"role\", \"menuitem\");\n\n const iconWrap = el(\"span\", { class: \"sp-export-option-icon\" });\n iconWrap.appendChild(parseSvg(iconSvg));\n\n const labelEl = el(\"span\", { class: \"sp-export-option-label\" });\n setText(labelEl, labelText);\n\n option.appendChild(iconWrap);\n option.appendChild(labelEl);\n\n option.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n onClick();\n this.close();\n });\n\n return option;\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.menu.classList.add(\"sp-export-menu--open\");\n const btn = this.element.querySelector<HTMLButtonElement>(\".sp-export-btn\");\n btn?.setAttribute(\"aria-expanded\", \"true\");\n }\n\n private close(): void {\n this.isOpen = false;\n this.menu.classList.remove(\"sp-export-menu--open\");\n const btn = this.element.querySelector<HTMLButtonElement>(\".sp-export-btn\");\n btn?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n private exportAs(format: \"csv\" | \"json\"): void {\n const feedbacks = this.getFeedbacks();\n if (feedbacks.length === 0) return;\n\n const projectName = feedbacks[0]?.projectName ?? \"feedbacks\";\n const date = new Date().toISOString().slice(0, 10);\n const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\n if (format === \"csv\") {\n const content = feedbacksToCsv(feedbacks);\n downloadFile(content, `feedbacks-${safeName}-${date}.csv`, \"text/csv;charset=utf-8\");\n } else {\n const content = feedbacksToJson(feedbacks);\n downloadFile(content, `feedbacks-${safeName}-${date}.json`, \"application/json;charset=utf-8\");\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick, true);\n this.element.remove();\n }\n}\n","/**\n * Bulk Actions system for the feedback panel.\n *\n * Allows multi-select on feedback cards with a floating action bar\n * for batch resolve/delete operations. Glassmorphism design with\n * spring animations and smooth transitions.\n */\n\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_CHECKBOX = `<svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"4\" stroke=\"currentColor\" stroke-width=\"2\"/></svg>`;\n\nexport const ICON_CHECKBOX_CHECKED = `<svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"4\" fill=\"url(#sp-cb-grad)\" stroke=\"none\"/><polyline points=\"5 9 8 12 13 6\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><defs><linearGradient id=\"sp-cb-grad\" x1=\"0\" y1=\"0\" x2=\"18\" y2=\"18\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0%\" stop-color=\"var(--sp-accent)\"/><stop offset=\"100%\" stop-color=\"var(--sp-accent-dark)\"/></linearGradient></defs></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18N\n// ---------------------------------------------------------------------------\n\nexport const BULK_I18N_EN = {\n \"bulk.selectAll\": \"Select all\",\n \"bulk.selected\": \"{count} selected\",\n \"bulk.resolve\": \"Resolve\",\n \"bulk.delete\": \"Delete\",\n \"bulk.deselect\": \"Deselect\",\n};\n\nexport const BULK_I18N_FR = {\n \"bulk.selectAll\": \"Tout sélectionner\",\n \"bulk.selected\": \"{count} sélectionné(s)\",\n \"bulk.resolve\": \"Résoudre\",\n \"bulk.delete\": \"Supprimer\",\n \"bulk.deselect\": \"Désélectionner\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const BULK_CSS = `\n /* ============================\n Bulk Checkbox\n ============================ */\n\n .sp-bulk-checkbox {\n position: relative;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n cursor: pointer;\n border-radius: 4px;\n color: var(--sp-border);\n opacity: 0;\n transition: opacity 0.15s ease, color 0.15s ease, transform 0.15s ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n .sp-bulk-checkbox svg {\n width: 16px;\n height: 16px;\n display: block;\n }\n\n .sp-bulk-checkbox:hover {\n color: var(--sp-accent);\n transform: scale(1.1);\n }\n\n .sp-bulk-checkbox--checked {\n color: var(--sp-accent);\n opacity: 1 !important;\n filter: drop-shadow(0 0 4px var(--sp-accent-glow));\n }\n\n /* Show checkboxes when hovering a card */\n .sp-card:hover .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* When any card has selection, show ALL checkboxes */\n .sp-list--has-selection .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* ============================\n Card Selected State\n ============================ */\n\n .sp-card--selected {\n border-left: 3px solid var(--sp-accent) !important;\n background: var(--sp-accent-light) !important;\n }\n\n .sp-card--selected:hover {\n background: var(--sp-accent-light) !important;\n }\n\n /* ============================\n Select All Bar\n ============================ */\n\n .sp-bulk-select-all {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n margin-bottom: 4px;\n border-radius: var(--sp-radius);\n background: transparent;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s ease, background 0.2s ease;\n user-select: none;\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n }\n\n .sp-bulk-select-all:hover {\n background: var(--sp-bg-hover);\n }\n\n /* Show select-all on list hover or when selections exist */\n .sp-list:hover .sp-bulk-select-all,\n .sp-list--has-selection .sp-bulk-select-all {\n opacity: 1;\n }\n\n .sp-bulk-select-all .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* ============================\n Floating Action Bar\n ============================ */\n\n @keyframes sp-bulk-bar-in {\n from {\n transform: translateY(100%) scale(0.95);\n opacity: 0;\n }\n to {\n transform: translateY(0) scale(1);\n opacity: 1;\n }\n }\n\n @keyframes sp-bulk-bar-out {\n from {\n transform: translateY(0) scale(1);\n opacity: 1;\n }\n to {\n transform: translateY(100%) scale(0.95);\n opacity: 0;\n }\n }\n\n .sp-bulk-bar {\n position: absolute;\n bottom: 16px;\n left: 16px;\n right: 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n border-radius: 16px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n z-index: 10;\n pointer-events: none;\n opacity: 0;\n transform: translateY(100%) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),\n opacity 0.25s ease;\n font-family: var(--sp-font);\n }\n\n .sp-bulk-bar--visible {\n pointer-events: auto;\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n .sp-bulk-bar-count {\n font-size: 13px;\n font-weight: 600;\n color: var(--sp-text);\n white-space: nowrap;\n letter-spacing: -0.01em;\n }\n\n .sp-bulk-bar-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-bulk-btn-resolve,\n .sp-bulk-btn-delete {\n padding: 7px 14px;\n border-radius: var(--sp-radius-full);\n border: 1.5px solid transparent;\n background: transparent;\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.2s ease;\n white-space: nowrap;\n }\n\n .sp-bulk-btn-resolve {\n color: #22c55e;\n border-color: #22c55e;\n }\n\n .sp-bulk-btn-resolve:hover {\n background: rgba(34, 197, 94, 0.1);\n box-shadow: 0 0 12px rgba(34, 197, 94, 0.15);\n }\n\n .sp-bulk-btn-resolve:active {\n transform: scale(0.96);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-delete {\n color: #ef4444;\n border-color: #ef4444;\n }\n\n .sp-bulk-btn-delete:hover {\n background: rgba(239, 68, 68, 0.1);\n box-shadow: 0 0 12px rgba(239, 68, 68, 0.15);\n }\n\n .sp-bulk-btn-delete:active {\n transform: scale(0.96);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-resolve:disabled,\n .sp-bulk-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-bulk-btn-deselect {\n width: 28px;\n height: 28px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n flex-shrink: 0;\n padding: 0;\n }\n\n .sp-bulk-btn-deselect:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n border-color: var(--sp-text-tertiary);\n }\n\n .sp-bulk-btn-deselect:active {\n transform: scale(0.92);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-deselect svg {\n width: 12px;\n height: 12px;\n }\n\n /* Spinner inside bulk bar buttons */\n .sp-bulk-btn-resolve .sp-spinner,\n .sp-bulk-btn-delete .sp-spinner {\n width: 14px;\n height: 14px;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-bulk-checkbox,\n .sp-bulk-btn-resolve,\n .sp-bulk-btn-delete,\n .sp-bulk-btn-deselect,\n .sp-bulk-bar {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-bulk-checkbox--checked {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-card--selected {\n border-left: 4px solid Highlight !important;\n }\n }\n\n /* ============================\n Reduced Motion\n ============================ */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-bulk-bar {\n transition-duration: 0.01ms !important;\n }\n\n .sp-bulk-checkbox {\n transition-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface BulkActionCallbacks {\n onResolve: (ids: string[]) => Promise<void>;\n onDelete: (ids: string[]) => Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// BulkActions Class\n// ---------------------------------------------------------------------------\n\nexport class BulkActions {\n /** The floating action bar element — append to panel root */\n readonly barElement: HTMLElement;\n\n private selected = new Set<string>();\n private checkboxMap = new Map<string, HTMLElement>();\n private countLabel: HTMLElement;\n private resolveBtn: HTMLButtonElement;\n private deleteBtn: HTMLButtonElement;\n private selectAllCheckbox: HTMLElement | null = null;\n private listContainer: HTMLElement | null = null;\n private isProcessing = false;\n private readonly i18n: typeof BULK_I18N_EN;\n\n constructor(\n _colors: ThemeColors,\n private readonly callbacks: BulkActionCallbacks,\n locale?: string,\n ) {\n this.i18n = locale === \"fr\" ? BULK_I18N_FR : BULK_I18N_EN;\n // ----- Build floating bar -----\n this.barElement = el(\"div\", { class: \"sp-bulk-bar\" });\n this.barElement.setAttribute(\"role\", \"toolbar\");\n this.barElement.setAttribute(\"aria-label\", \"Bulk actions\");\n\n // Left: count label\n this.countLabel = el(\"span\", { class: \"sp-bulk-bar-count\" });\n setText(this.countLabel, this.i18n[\"bulk.selected\"].replace(\"{count}\", \"0\"));\n\n // Right: action buttons\n const actions = el(\"div\", { class: \"sp-bulk-bar-actions\" });\n\n this.resolveBtn = document.createElement(\"button\");\n this.resolveBtn.className = \"sp-bulk-btn-resolve\";\n this.resolveBtn.type = \"button\";\n this.resolveBtn.addEventListener(\"click\", () => this.handleResolve());\n\n this.deleteBtn = document.createElement(\"button\");\n this.deleteBtn.className = \"sp-bulk-btn-delete\";\n this.deleteBtn.type = \"button\";\n this.deleteBtn.addEventListener(\"click\", () => this.handleDelete());\n\n const deselectBtn = document.createElement(\"button\");\n deselectBtn.className = \"sp-bulk-btn-deselect\";\n deselectBtn.type = \"button\";\n deselectBtn.setAttribute(\"aria-label\", this.i18n[\"bulk.deselect\"]);\n deselectBtn.appendChild(\n parseSvg(\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n ),\n );\n deselectBtn.addEventListener(\"click\", () => this.deselectAll());\n\n actions.appendChild(this.resolveBtn);\n actions.appendChild(this.deleteBtn);\n actions.appendChild(deselectBtn);\n\n this.barElement.appendChild(this.countLabel);\n this.barElement.appendChild(actions);\n\n // Initial button text\n this.updateButtonLabels();\n }\n\n /** Create a checkbox element for a card. Returns the checkbox wrapper. */\n createCheckbox(feedbackId: string): HTMLElement {\n const wrapper = el(\"div\", { class: \"sp-bulk-checkbox\" });\n wrapper.setAttribute(\"role\", \"checkbox\");\n wrapper.setAttribute(\"aria-checked\", \"false\");\n wrapper.setAttribute(\"tabindex\", \"0\");\n wrapper.setAttribute(\"aria-label\", `Select feedback ${feedbackId}`);\n\n // Render unchecked icon\n wrapper.appendChild(parseSvg(ICON_CHECKBOX));\n\n // Click handler\n wrapper.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggle(feedbackId);\n });\n\n // Keyboard: space/enter to toggle\n wrapper.addEventListener(\"keydown\", (e) => {\n if ((e as KeyboardEvent).key === \" \" || (e as KeyboardEvent).key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n this.toggle(feedbackId);\n }\n });\n\n this.checkboxMap.set(feedbackId, wrapper);\n return wrapper;\n }\n\n /**\n * Create a \"Select all\" bar element.\n * The caller should insert this at the top of the list container.\n */\n createSelectAllBar(feedbackIds: string[], label: string): HTMLElement {\n const wrapper = el(\"div\", { class: \"sp-bulk-select-all\" });\n\n const checkbox = el(\"div\", { class: \"sp-bulk-checkbox\" });\n checkbox.appendChild(parseSvg(ICON_CHECKBOX));\n this.selectAllCheckbox = checkbox;\n\n const labelEl = el(\"span\");\n setText(labelEl, label);\n\n wrapper.appendChild(checkbox);\n wrapper.appendChild(labelEl);\n\n wrapper.addEventListener(\"click\", () => {\n // If all selected, deselect; otherwise select all\n if (this.selected.size === feedbackIds.length && feedbackIds.length > 0) {\n this.deselectAll();\n } else {\n this.selectAll(feedbackIds);\n }\n });\n\n return wrapper;\n }\n\n /** Set the list container reference (for toggling .sp-list--has-selection) */\n setListContainer(container: HTMLElement): void {\n this.listContainer = container;\n }\n\n /** Toggle selection for a feedback */\n toggle(feedbackId: string): void {\n if (this.isProcessing) return;\n\n if (this.selected.has(feedbackId)) {\n this.selected.delete(feedbackId);\n } else {\n this.selected.add(feedbackId);\n }\n this.updateCheckbox(feedbackId);\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n this.updateCardSelectedState(feedbackId);\n }\n\n /** Select all from the given list */\n selectAll(feedbackIds: string[]): void {\n if (this.isProcessing) return;\n\n for (const id of feedbackIds) {\n this.selected.add(id);\n this.updateCheckbox(id);\n this.updateCardSelectedState(id);\n }\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n }\n\n /** Clear all selections */\n deselectAll(): void {\n const prevSelected = [...this.selected];\n this.selected.clear();\n for (const id of prevSelected) {\n this.updateCheckbox(id);\n this.updateCardSelectedState(id);\n }\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n }\n\n /** Get currently selected IDs */\n get selectedIds(): string[] {\n return [...this.selected];\n }\n\n /** Get selection count */\n get count(): number {\n return this.selected.size;\n }\n\n /** Whether any items are selected */\n get hasSelection(): boolean {\n return this.selected.size > 0;\n }\n\n /** Reset state (e.g., after feedbacks reload) */\n reset(): void {\n this.selected.clear();\n this.checkboxMap.clear();\n this.selectAllCheckbox = null;\n\n this.isProcessing = false;\n this.updateBar();\n this.updateListSelectionClass();\n }\n\n /** Destroy / cleanup */\n destroy(): void {\n this.selected.clear();\n this.checkboxMap.clear();\n this.selectAllCheckbox = null;\n\n this.listContainer = null;\n this.barElement.remove();\n }\n\n // -----------------------------------------------------------------------\n // Private\n // -----------------------------------------------------------------------\n\n /** Update the bar visibility and counts */\n private updateBar(): void {\n const count = this.selected.size;\n const visible = count > 0;\n\n this.barElement.classList.toggle(\"sp-bulk-bar--visible\", visible);\n setText(this.countLabel, this.i18n[\"bulk.selected\"].replace(\"{count}\", String(count)));\n this.updateButtonLabels();\n }\n\n private updateButtonLabels(): void {\n const count = this.selected.size;\n\n // Resolve button\n this.resolveBtn.replaceChildren();\n const resolveLabel = document.createElement(\"span\");\n setText(resolveLabel, count > 0 ? `${this.i18n[\"bulk.resolve\"]} ${count}` : this.i18n[\"bulk.resolve\"]);\n this.resolveBtn.appendChild(resolveLabel);\n\n // Delete button\n this.deleteBtn.replaceChildren();\n const deleteLabel = document.createElement(\"span\");\n setText(deleteLabel, count > 0 ? `${this.i18n[\"bulk.delete\"]} ${count}` : this.i18n[\"bulk.delete\"]);\n this.deleteBtn.appendChild(deleteLabel);\n }\n\n private updateCheckbox(feedbackId: string): void {\n const checkbox = this.checkboxMap.get(feedbackId);\n if (!checkbox) return;\n\n const isChecked = this.selected.has(feedbackId);\n checkbox.classList.toggle(\"sp-bulk-checkbox--checked\", isChecked);\n checkbox.setAttribute(\"aria-checked\", String(isChecked));\n\n // Swap SVG icon\n checkbox.replaceChildren();\n checkbox.appendChild(parseSvg(isChecked ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX));\n }\n\n private updateSelectAllCheckbox(): void {\n if (!this.selectAllCheckbox) return;\n\n const allSelected = this.selected.size > 0 && this.selected.size === this.checkboxMap.size;\n this.selectAllCheckbox.classList.toggle(\"sp-bulk-checkbox--checked\", allSelected);\n this.selectAllCheckbox.setAttribute(\"aria-checked\", String(allSelected));\n\n this.selectAllCheckbox.replaceChildren();\n this.selectAllCheckbox.appendChild(parseSvg(allSelected ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX));\n }\n\n private updateListSelectionClass(): void {\n if (!this.listContainer) return;\n this.listContainer.classList.toggle(\"sp-list--has-selection\", this.selected.size > 0);\n }\n\n private updateCardSelectedState(feedbackId: string): void {\n if (!this.listContainer) return;\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.classList.toggle(\"sp-card--selected\", this.selected.has(feedbackId));\n }\n }\n\n private setButtonLoading(btn: HTMLButtonElement): () => void {\n const snapshot = Array.from(btn.childNodes).map((n) => n.cloneNode(true));\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n return () => {\n btn.replaceChildren(...snapshot);\n btn.disabled = false;\n };\n }\n\n private async handleResolve(): Promise<void> {\n if (this.isProcessing || this.selected.size === 0) return;\n this.isProcessing = true;\n\n const ids = [...this.selected];\n const restoreResolve = this.setButtonLoading(this.resolveBtn);\n this.deleteBtn.disabled = true;\n\n try {\n await this.callbacks.onResolve(ids);\n this.reset();\n } catch {\n restoreResolve();\n this.deleteBtn.disabled = false;\n } finally {\n this.isProcessing = false;\n }\n }\n\n private async handleDelete(): Promise<void> {\n if (this.isProcessing || this.selected.size === 0) return;\n this.isProcessing = true;\n\n const ids = [...this.selected];\n const restoreDelete = this.setButtonLoading(this.deleteBtn);\n this.resolveBtn.disabled = true;\n\n try {\n await this.callbacks.onDelete(ids);\n this.reset();\n } catch {\n restoreDelete();\n this.resolveBtn.disabled = false;\n } finally {\n this.isProcessing = false;\n }\n }\n}\n","/**\n * Detail View for the feedback panel.\n *\n * Slides in from the right (panel-in-panel pattern) when a user clicks\n * a feedback card, showing full details: message, metadata, annotation\n * info, status actions, and a \"Go to annotation\" button.\n *\n * Glassmorphism design — frosted glass surfaces, staggered section\n * animations, accent gradients, premium micro-interactions.\n */\n\nimport type { FeedbackResponse } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_ARROW_LEFT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"19\" y1=\"12\" x2=\"5\" y2=\"12\"/><polyline points=\"12 19 5 12 12 5\"/></svg>`;\n\nexport const ICON_MAP_PIN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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\nexport const ICON_LINK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`;\n\nexport const ICON_USER = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></svg>`;\n\nexport const ICON_CALENDAR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"/><line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\"/><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\"/></svg>`;\n\nexport const ICON_MONITOR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\"/><line x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\"/><line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\"/></svg>`;\n\nconst ICON_CHECK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n\nconst ICON_UNDO = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>`;\n\nconst ICON_TRASH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/></svg>`;\n\nconst ICON_CODE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/></svg>`;\n\nconst ICON_CROSSHAIR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"22\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"6\" y1=\"12\" x2=\"2\" y2=\"12\"/><line x1=\"12\" y1=\"6\" x2=\"12\" y2=\"2\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"18\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18n\n// ---------------------------------------------------------------------------\n\nexport const DETAIL_I18N_EN = {\n \"detail.back\": \"Back\",\n \"detail.title\": \"Feedback #{number}\",\n \"detail.status\": \"Status\",\n \"detail.message\": \"Message\",\n \"detail.metadata\": \"Details\",\n \"detail.annotation\": \"Annotation\",\n \"detail.page\": \"Page\",\n \"detail.author\": \"Author\",\n \"detail.date\": \"Created\",\n \"detail.viewport\": \"Viewport\",\n \"detail.browser\": \"Browser\",\n \"detail.resolvedAt\": \"Resolved at\",\n \"detail.goToAnnotation\": \"Go to annotation\",\n \"detail.element\": \"Element\",\n \"detail.selector\": \"Selector\",\n \"detail.position\": \"Position\",\n \"detail.resolve\": \"Resolve\",\n \"detail.reopen\": \"Reopen\",\n \"detail.delete\": \"Delete\",\n};\n\nexport const DETAIL_I18N_FR = {\n \"detail.back\": \"Retour\",\n \"detail.title\": \"Feedback n\\u00b0{number}\",\n \"detail.status\": \"Statut\",\n \"detail.message\": \"Message\",\n \"detail.metadata\": \"D\\u00e9tails\",\n \"detail.annotation\": \"Annotation\",\n \"detail.page\": \"Page\",\n \"detail.author\": \"Auteur\",\n \"detail.date\": \"Cr\\u00e9\\u00e9 le\",\n \"detail.viewport\": \"Viewport\",\n \"detail.browser\": \"Navigateur\",\n \"detail.resolvedAt\": \"R\\u00e9solu le\",\n \"detail.goToAnnotation\": \"Aller \\u00e0 l'annotation\",\n \"detail.element\": \"\\u00c9l\\u00e9ment\",\n \"detail.selector\": \"S\\u00e9lecteur\",\n \"detail.position\": \"Position\",\n \"detail.resolve\": \"R\\u00e9soudre\",\n \"detail.reopen\": \"Rouvrir\",\n \"detail.delete\": \"Supprimer\",\n};\n\ntype DetailI18nKey = keyof typeof DETAIL_I18N_EN;\ntype DetailI18n = Record<DetailI18nKey, string>;\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const DETAIL_CSS = /* css */ `\n /* ============================\n Detail View — Panel-in-Panel\n ============================ */\n\n .sp-detail {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n z-index: 20;\n transform: translateX(100%);\n transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform;\n overflow: hidden;\n }\n\n .sp-detail--visible {\n transform: translateX(0);\n }\n\n /* ---- Header ---- */\n\n .sp-detail-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n flex-shrink: 0;\n min-height: 64px;\n }\n\n .sp-detail-back {\n width: 40px;\n height: 40px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n flex-shrink: 0;\n padding: 0;\n }\n\n .sp-detail-back:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-detail-back:active {\n transform: scale(0.92);\n transition-duration: 0.1s;\n }\n\n .sp-detail-back svg {\n width: 18px;\n height: 18px;\n }\n\n .sp-detail-title {\n font-size: 16px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-detail-header .sp-badge {\n flex-shrink: 0;\n }\n\n /* ---- Content ---- */\n\n .sp-detail-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0;\n }\n\n .sp-detail-content::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-detail-content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-detail-content::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-detail-content::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n /* ---- Section ---- */\n\n .sp-detail-section {\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n opacity: 0;\n transform: translateY(8px);\n animation: sp-detail-section-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n\n @keyframes sp-detail-section-in {\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .sp-detail-section:last-child {\n border-bottom: none;\n }\n\n .sp-detail-section-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n margin-bottom: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-detail-section-title svg {\n width: 14px;\n height: 14px;\n opacity: 0.6;\n }\n\n /* ---- Status + Actions Section ---- */\n\n .sp-detail-status {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 16px;\n }\n\n .sp-detail-status-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 14px;\n border-radius: var(--sp-radius-full);\n font-size: 12px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-detail-status-pill--open {\n background: rgba(34, 197, 94, 0.1);\n color: #22c55e;\n border: 1px solid rgba(34, 197, 94, 0.2);\n }\n\n .sp-detail-status-pill--resolved {\n background: rgba(156, 163, 175, 0.1);\n color: #9ca3af;\n border: 1px solid rgba(156, 163, 175, 0.2);\n }\n\n .sp-detail-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .sp-detail-actions {\n display: flex;\n gap: 8px;\n }\n\n .sp-detail-actions button {\n flex: 1;\n height: 40px;\n padding: 0 16px;\n border-radius: var(--sp-radius);\n font-family: var(--sp-font);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s ease;\n }\n\n .sp-detail-actions button svg {\n width: 15px;\n height: 15px;\n }\n\n .sp-detail-btn-resolve {\n border: 1.5px solid #22c55e;\n background: rgba(34, 197, 94, 0.06);\n color: #22c55e;\n }\n\n .sp-detail-btn-resolve:hover {\n background: rgba(34, 197, 94, 0.14);\n box-shadow: 0 0 16px rgba(34, 197, 94, 0.12);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-resolve:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-btn-reopen {\n border: 1.5px solid var(--sp-accent);\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n .sp-detail-btn-reopen:hover {\n background: rgba(var(--sp-accent), 0.14);\n box-shadow: 0 0 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-reopen:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-btn-delete {\n border: 1.5px solid #ef4444;\n background: rgba(239, 68, 68, 0.06);\n color: #ef4444;\n }\n\n .sp-detail-btn-delete:hover {\n background: rgba(239, 68, 68, 0.14);\n box-shadow: 0 0 16px rgba(239, 68, 68, 0.12);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-delete:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-actions button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n transform: none;\n box-shadow: none;\n }\n\n /* ---- Message Section ---- */\n\n .sp-detail-message {\n font-size: 14px;\n line-height: 1.65;\n color: var(--sp-text);\n padding: 14px 16px;\n border-left: 3px solid var(--sp-accent);\n border-radius: 0 var(--sp-radius) var(--sp-radius) 0;\n background: var(--sp-glass-bg-heavy);\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n /* ---- Metadata Section ---- */\n\n .sp-detail-meta {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .sp-detail-meta-row {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n }\n\n .sp-detail-meta-row svg {\n width: 14px;\n height: 14px;\n color: var(--sp-text-tertiary);\n flex-shrink: 0;\n margin-top: 1px;\n }\n\n .sp-detail-meta-content {\n flex: 1;\n min-width: 0;\n }\n\n .sp-detail-meta-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .sp-detail-meta-value {\n font-size: 13px;\n line-height: 1.4;\n color: var(--sp-text);\n word-break: break-all;\n }\n\n .sp-detail-meta-value--mono {\n font-family: \"SF Mono\", \"Cascadia Code\", \"Fira Code\", \"Consolas\", monospace;\n font-size: 12px;\n background: var(--sp-glass-bg-heavy);\n padding: 2px 6px;\n border-radius: 4px;\n border: 1px solid var(--sp-glass-border-subtle);\n }\n\n .sp-detail-meta-value--secondary {\n color: var(--sp-text-secondary);\n font-size: 12px;\n }\n\n /* ---- Annotation Section ---- */\n\n .sp-detail-annotation {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .sp-detail-annotation-info {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border-subtle);\n }\n\n .sp-detail-annotation-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n }\n\n .sp-detail-annotation-row svg {\n width: 13px;\n height: 13px;\n color: var(--sp-text-tertiary);\n flex-shrink: 0;\n margin-top: 2px;\n }\n\n .sp-detail-annotation-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n line-height: 1;\n margin-bottom: 3px;\n }\n\n .sp-detail-annotation-value {\n font-size: 12px;\n line-height: 1.4;\n color: var(--sp-text);\n word-break: break-all;\n }\n\n .sp-detail-annotation-value--mono {\n font-family: \"SF Mono\", \"Cascadia Code\", \"Fira Code\", \"Consolas\", monospace;\n font-size: 11px;\n background: var(--sp-bg-hover);\n padding: 2px 6px;\n border-radius: 4px;\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-detail-btn-goto {\n width: 100%;\n height: 44px;\n padding: 0 20px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.25s ease;\n box-shadow: 0 2px 12px var(--sp-accent-glow);\n }\n\n .sp-detail-btn-goto svg {\n width: 16px;\n height: 16px;\n }\n\n .sp-detail-btn-goto:hover {\n box-shadow: 0 4px 20px var(--sp-accent-glow);\n transform: translateY(-2px);\n }\n\n .sp-detail-btn-goto:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n /* ---- Forced Colors / High Contrast ---- */\n\n @media (forced-colors: active) {\n .sp-detail {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-detail-back,\n .sp-detail-btn-goto,\n .sp-detail-btn-resolve,\n .sp-detail-btn-reopen,\n .sp-detail-btn-delete {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-detail-back:focus-visible,\n .sp-detail-btn-goto:focus-visible,\n .sp-detail-btn-resolve:focus-visible,\n .sp-detail-btn-reopen:focus-visible,\n .sp-detail-btn-delete:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-detail-status-pill {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-detail-message {\n border-left: 3px solid ButtonText !important;\n }\n }\n\n /* ---- Reduced Motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-detail {\n transition-duration: 0.01ms !important;\n }\n\n .sp-detail-section {\n animation-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse a userAgent string to extract the browser name and version. */\nfunction parseBrowser(ua: string): string {\n // Order matters: Edge includes \"Edg/\", Chrome includes \"Chrome/\", etc.\n if (/Edg\\//i.test(ua)) {\n const m = ua.match(/Edg\\/([\\d.]+)/);\n return m ? `Edge ${m[1]}` : \"Edge\";\n }\n if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n const m = ua.match(/OPR\\/([\\d.]+)/);\n return m ? `Opera ${m[1]}` : \"Opera\";\n }\n if (/Firefox\\//i.test(ua)) {\n const m = ua.match(/Firefox\\/([\\d.]+)/);\n return m ? `Firefox ${m[1]}` : \"Firefox\";\n }\n if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n const m = ua.match(/Chrome\\/([\\d.]+)/);\n return m ? `Chrome ${m[1]}` : \"Chrome\";\n }\n if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n const m = ua.match(/Version\\/([\\d.]+)/);\n return m ? `Safari ${m[1]}` : \"Safari\";\n }\n return \"Unknown\";\n}\n\n/** Format an ISO date string to a full locale-aware date/time. */\nfunction formatFullDate(isoString: string, locale: string): string {\n try {\n const d = new Date(isoString);\n return d.toLocaleString(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n } catch {\n return isoString;\n }\n}\n\n/** Extract the pathname from a URL string, falling back to the raw string. */\nfunction extractPathname(url: string): string {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n}\n\n/** Truncate a string to a max length with ellipsis. */\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"\\u2026\";\n}\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface DetailCallbacks {\n onBack: () => void;\n onResolve: (feedback: FeedbackResponse) => Promise<void>;\n onDelete: (feedback: FeedbackResponse) => Promise<void>;\n onGoToAnnotation: (feedback: FeedbackResponse) => void;\n}\n\n// ---------------------------------------------------------------------------\n// DetailView Class\n// ---------------------------------------------------------------------------\n\nexport class DetailView {\n readonly element: HTMLElement;\n\n private _isVisible = false;\n private currentFeedback: FeedbackResponse | null = null;\n private readonly content: HTMLElement;\n private readonly i18n: DetailI18n;\n private resolveBtn: HTMLButtonElement | null = null;\n private deleteBtn: HTMLButtonElement | null = null;\n private isProcessing = false;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly callbacks: DetailCallbacks,\n locale: string,\n ) {\n this.i18n = locale.startsWith(\"fr\") ? DETAIL_I18N_FR : DETAIL_I18N_EN;\n\n // Root container\n this.element = el(\"div\", { class: \"sp-detail\" });\n this.element.setAttribute(\"role\", \"dialog\");\n this.element.setAttribute(\"aria-label\", \"Feedback detail\");\n this.element.setAttribute(\"aria-hidden\", \"true\");\n\n // Header (built once, title/badge updated on show())\n const header = el(\"div\", { class: \"sp-detail-header\" });\n\n const backBtn = document.createElement(\"button\");\n backBtn.type = \"button\";\n backBtn.className = \"sp-detail-back\";\n backBtn.setAttribute(\"aria-label\", this.i18n[\"detail.back\"]);\n backBtn.appendChild(parseSvg(ICON_ARROW_LEFT));\n backBtn.addEventListener(\"click\", () => {\n this.hide();\n this.callbacks.onBack();\n });\n\n this.element.appendChild(header);\n header.appendChild(backBtn);\n\n // Title and badge are appended in show()\n\n // Scrollable content area\n this.content = el(\"div\", { class: \"sp-detail-content\" });\n this.element.appendChild(this.content);\n }\n\n /** Show the detail view for a specific feedback. */\n show(feedback: FeedbackResponse, number: number): void {\n this.currentFeedback = feedback;\n this.isProcessing = false;\n\n // ---- Update header ----\n const header = this.element.querySelector<HTMLElement>(\".sp-detail-header\");\n if (!header) return;\n // Remove old title/badge but keep the back button\n const backBtn = header.querySelector<HTMLElement>(\".sp-detail-back\");\n if (!backBtn) return;\n header.replaceChildren(backBtn);\n\n const title = el(\"span\", { class: \"sp-detail-title\" });\n setText(title, this.i18n[\"detail.title\"].replace(\"{number}\", String(number)));\n header.appendChild(title);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n badge.style.background = getTypeBgColor(feedback.type, this.colors);\n badge.style.color = getTypeColor(feedback.type, this.colors);\n setText(badge, feedback.type);\n header.appendChild(badge);\n\n // ---- Build content sections ----\n this.content.replaceChildren();\n\n let sectionIndex = 0;\n\n // Section 1: Status + Actions\n const statusSection = this.buildSection(sectionIndex++);\n this.buildStatusActions(statusSection, feedback);\n this.content.appendChild(statusSection);\n\n // Section 2: Message\n const messageSection = this.buildSection(sectionIndex++);\n const messageSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(messageSectionTitle, this.i18n[\"detail.message\"]);\n messageSection.appendChild(messageSectionTitle);\n\n const messageBlock = el(\"div\", { class: \"sp-detail-message\" });\n messageBlock.style.borderLeftColor = getTypeColor(feedback.type, this.colors);\n setText(messageBlock, feedback.message);\n messageSection.appendChild(messageBlock);\n this.content.appendChild(messageSection);\n\n // Section 3: Metadata\n const metaSection = this.buildSection(sectionIndex++);\n const metaSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(metaSectionTitle, this.i18n[\"detail.metadata\"]);\n metaSection.appendChild(metaSectionTitle);\n this.buildMetadata(metaSection, feedback);\n this.content.appendChild(metaSection);\n\n // Section 4: Annotation (if any)\n if (feedback.annotations.length > 0) {\n const annSection = this.buildSection(sectionIndex++);\n const annSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n annSectionTitle.appendChild(parseSvg(ICON_MAP_PIN));\n const annTitleText = el(\"span\");\n setText(annTitleText, this.i18n[\"detail.annotation\"]);\n annSectionTitle.appendChild(annTitleText);\n annSection.appendChild(annSectionTitle);\n this.buildAnnotation(annSection, feedback);\n this.content.appendChild(annSection);\n }\n\n // ---- Show with animation ----\n this._isVisible = true;\n this.element.setAttribute(\"aria-hidden\", \"false\");\n\n // Force reflow before adding visible class to trigger CSS transition\n void this.element.offsetHeight;\n this.element.classList.add(\"sp-detail--visible\");\n\n // Focus the back button for keyboard users\n requestAnimationFrame(() => {\n backBtn.focus();\n });\n }\n\n /** Hide the detail view with slide-out animation. */\n hide(): void {\n if (!this._isVisible) return;\n this._isVisible = false;\n this.element.classList.remove(\"sp-detail--visible\");\n this.element.setAttribute(\"aria-hidden\", \"true\");\n this.currentFeedback = null;\n this.resolveBtn = null;\n this.deleteBtn = null;\n }\n\n /** Whether the detail view is currently visible. */\n get isVisible(): boolean {\n return this._isVisible;\n }\n\n /** Cleanup all references. */\n destroy(): void {\n this.hide();\n this.element.remove();\n }\n\n // -----------------------------------------------------------------------\n // Private — Section builders\n // -----------------------------------------------------------------------\n\n /** Create a section element with stagger delay. */\n private buildSection(index: number): HTMLElement {\n const section = el(\"div\", { class: \"sp-detail-section\" });\n section.style.animationDelay = `${index * 40}ms`;\n return section;\n }\n\n /** Build Status pill + Resolve/Delete action buttons. */\n private buildStatusActions(container: HTMLElement, feedback: FeedbackResponse): void {\n const isResolved = feedback.status === \"resolved\";\n\n // Section title\n const sectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(sectionTitle, this.i18n[\"detail.status\"]);\n container.appendChild(sectionTitle);\n\n // Status pill\n const statusRow = el(\"div\", { class: \"sp-detail-status\" });\n const pill = el(\"span\", {\n class: `sp-detail-status-pill ${isResolved ? \"sp-detail-status-pill--resolved\" : \"sp-detail-status-pill--open\"}`,\n });\n const dot = el(\"span\", { class: \"sp-detail-status-dot\" });\n dot.style.background = isResolved ? \"#9ca3af\" : \"#22c55e\";\n pill.appendChild(dot);\n const pillLabel = el(\"span\");\n setText(pillLabel, isResolved ? this.i18n[\"detail.reopen\"] : this.i18n[\"detail.resolve\"]);\n // Actually label the pill with Open/Resolved\n setText(pillLabel, isResolved ? \"Resolved\" : \"Open\");\n pill.appendChild(pillLabel);\n statusRow.appendChild(pill);\n container.appendChild(statusRow);\n\n // Action buttons\n const actions = el(\"div\", { class: \"sp-detail-actions\" });\n\n // Resolve / Reopen\n this.resolveBtn = document.createElement(\"button\");\n this.resolveBtn.type = \"button\";\n if (isResolved) {\n this.resolveBtn.className = \"sp-detail-btn-reopen\";\n this.resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.reopen\"]);\n this.resolveBtn.appendChild(span);\n } else {\n this.resolveBtn.className = \"sp-detail-btn-resolve\";\n this.resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.resolve\"]);\n this.resolveBtn.appendChild(span);\n }\n this.resolveBtn.addEventListener(\"click\", () => this.handleResolve());\n\n // Delete\n this.deleteBtn = document.createElement(\"button\");\n this.deleteBtn.type = \"button\";\n this.deleteBtn.className = \"sp-detail-btn-delete\";\n this.deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteSpan = document.createElement(\"span\");\n setText(deleteSpan, this.i18n[\"detail.delete\"]);\n this.deleteBtn.appendChild(deleteSpan);\n this.deleteBtn.addEventListener(\"click\", () => this.handleDelete());\n\n actions.appendChild(this.resolveBtn);\n actions.appendChild(this.deleteBtn);\n container.appendChild(actions);\n }\n\n /** Build the metadata grid. */\n private buildMetadata(container: HTMLElement, feedback: FeedbackResponse): void {\n const meta = el(\"div\", { class: \"sp-detail-meta\" });\n\n // Page\n this.addMetaRow(meta, ICON_LINK, this.i18n[\"detail.page\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n const pathname = extractPathname(feedback.url);\n setText(value, truncate(pathname, 60));\n value.title = feedback.url;\n return value;\n });\n\n // Author\n this.addMetaRow(meta, ICON_USER, this.i18n[\"detail.author\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n const name = feedback.authorName || \"Anonymous\";\n const email = feedback.authorEmail;\n setText(value, email ? `${name} (${email})` : name);\n return value;\n });\n\n // Date\n this.addMetaRow(meta, ICON_CALENDAR, this.i18n[\"detail.date\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n setText(value, formatFullDate(feedback.createdAt, this.i18n === DETAIL_I18N_FR ? \"fr\" : \"en\"));\n return value;\n });\n\n // Viewport\n this.addMetaRow(meta, ICON_MONITOR, this.i18n[\"detail.viewport\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value sp-detail-meta-value--mono\" });\n setText(value, feedback.viewport || \"Unknown\");\n return value;\n });\n\n // Browser\n this.addMetaRow(\n meta,\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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 this.i18n[\"detail.browser\"],\n () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n setText(value, parseBrowser(feedback.userAgent));\n return value;\n },\n );\n\n // Resolved at (only if resolved)\n if (feedback.resolvedAt) {\n const resolvedDate = feedback.resolvedAt;\n this.addMetaRow(meta, ICON_CHECK, this.i18n[\"detail.resolvedAt\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value sp-detail-meta-value--secondary\" });\n setText(value, formatFullDate(resolvedDate, this.i18n === DETAIL_I18N_FR ? \"fr\" : \"en\"));\n return value;\n });\n }\n\n container.appendChild(meta);\n }\n\n /** Add a single metadata row with icon, label, and custom value element. */\n private addMetaRow(container: HTMLElement, iconSvg: string, label: string, buildValue: () => HTMLElement): void {\n const row = el(\"div\", { class: \"sp-detail-meta-row\" });\n row.appendChild(parseSvg(iconSvg));\n\n const content = el(\"div\", { class: \"sp-detail-meta-content\" });\n const labelEl = el(\"div\", { class: \"sp-detail-meta-label\" });\n setText(labelEl, label);\n content.appendChild(labelEl);\n content.appendChild(buildValue());\n\n row.appendChild(content);\n container.appendChild(row);\n }\n\n /** Build the annotation detail section. */\n private buildAnnotation(container: HTMLElement, feedback: FeedbackResponse): void {\n const ann = feedback.annotations[0];\n if (!ann) return;\n\n const wrapper = el(\"div\", { class: \"sp-detail-annotation\" });\n\n // Info card\n const info = el(\"div\", { class: \"sp-detail-annotation-info\" });\n\n // Element tag\n this.addAnnotationRow(info, ICON_CODE, this.i18n[\"detail.element\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value sp-detail-annotation-value--mono\" });\n const tagDisplay = ann.elementId ? `<${ann.elementTag}#${ann.elementId}>` : `<${ann.elementTag}>`;\n setText(value, tagDisplay);\n return value;\n });\n\n // CSS selector\n this.addAnnotationRow(info, ICON_CROSSHAIR, this.i18n[\"detail.selector\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value sp-detail-annotation-value--mono\" });\n setText(value, truncate(ann.cssSelector, 60));\n value.title = ann.cssSelector;\n return value;\n });\n\n // Position\n this.addAnnotationRow(info, ICON_MAP_PIN, this.i18n[\"detail.position\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value\" });\n setText(\n value,\n `${ann.xPct.toFixed(1)}%, ${ann.yPct.toFixed(1)}%` +\n (ann.wPct > 0 || ann.hPct > 0 ? ` (${ann.wPct.toFixed(1)}% \\u00d7 ${ann.hPct.toFixed(1)}%)` : \"\"),\n );\n return value;\n });\n\n wrapper.appendChild(info);\n\n // \"Go to annotation\" button\n const gotoBtn = document.createElement(\"button\");\n gotoBtn.type = \"button\";\n gotoBtn.className = \"sp-detail-btn-goto\";\n gotoBtn.appendChild(parseSvg(ICON_MAP_PIN));\n const gotoLabel = document.createElement(\"span\");\n setText(gotoLabel, this.i18n[\"detail.goToAnnotation\"]);\n gotoBtn.appendChild(gotoLabel);\n gotoBtn.addEventListener(\"click\", () => {\n if (this.currentFeedback) {\n this.callbacks.onGoToAnnotation(this.currentFeedback);\n }\n });\n\n wrapper.appendChild(gotoBtn);\n container.appendChild(wrapper);\n }\n\n /** Add a single annotation info row. */\n private addAnnotationRow(\n container: HTMLElement,\n iconSvg: string,\n label: string,\n buildValue: () => HTMLElement,\n ): void {\n const row = el(\"div\", { class: \"sp-detail-annotation-row\" });\n row.appendChild(parseSvg(iconSvg));\n\n const content = el(\"div\", { class: \"sp-detail-meta-content\" });\n const labelEl = el(\"div\", { class: \"sp-detail-annotation-label\" });\n setText(labelEl, label);\n content.appendChild(labelEl);\n content.appendChild(buildValue());\n\n row.appendChild(content);\n container.appendChild(row);\n }\n\n // -----------------------------------------------------------------------\n // Private — Action handlers\n // -----------------------------------------------------------------------\n\n private async handleResolve(): Promise<void> {\n if (this.isProcessing || !this.currentFeedback) return;\n this.isProcessing = true;\n\n if (this.resolveBtn) this.setButtonLoading(this.resolveBtn);\n if (this.deleteBtn) this.deleteBtn.disabled = true;\n\n try {\n await this.callbacks.onResolve(this.currentFeedback);\n // The parent will call hide() or re-show with updated data\n } catch {\n // Restore buttons on error\n this.isProcessing = false;\n if (this.resolveBtn) this.restoreResolveBtn(this.currentFeedback);\n if (this.deleteBtn) this.deleteBtn.disabled = false;\n }\n }\n\n private async handleDelete(): Promise<void> {\n if (this.isProcessing || !this.currentFeedback) return;\n this.isProcessing = true;\n\n if (this.deleteBtn) this.setButtonLoading(this.deleteBtn);\n if (this.resolveBtn) this.resolveBtn.disabled = true;\n\n try {\n await this.callbacks.onDelete(this.currentFeedback);\n // The parent will call hide() after deletion\n } catch {\n this.isProcessing = false;\n if (this.deleteBtn) this.restoreDeleteBtn();\n if (this.resolveBtn) this.resolveBtn.disabled = false;\n }\n }\n\n private setButtonLoading(btn: HTMLButtonElement): void {\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n }\n\n private restoreResolveBtn(feedback: FeedbackResponse): void {\n if (!this.resolveBtn) return;\n this.resolveBtn.disabled = false;\n this.resolveBtn.replaceChildren();\n\n const isResolved = feedback.status === \"resolved\";\n this.resolveBtn.appendChild(parseSvg(isResolved ? ICON_UNDO : ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, isResolved ? this.i18n[\"detail.reopen\"] : this.i18n[\"detail.resolve\"]);\n this.resolveBtn.appendChild(span);\n }\n\n private restoreDeleteBtn(): void {\n if (!this.deleteBtn) return;\n this.deleteBtn.disabled = false;\n this.deleteBtn.replaceChildren();\n this.deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.delete\"]);\n this.deleteBtn.appendChild(span);\n }\n}\n","/**\n * Sort and group-by-page controls for the feedback panel.\n *\n * Provides:\n * - Sort dropdown (newest, oldest, by-type, open-first)\n * - Group by page toggle (collapsible URL sections)\n * - Pure sort/group utility functions\n *\n * Glassmorphism design — glass surfaces, accent gradients,\n * smooth micro-interactions.\n */\n\nimport type { FeedbackResponse, FeedbackType } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SortMode = \"newest\" | \"oldest\" | \"by-type\" | \"open-first\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_SORT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M11 5h10\"/><path d=\"M11 9h7\"/><path d=\"M11 13h4\"/><path d=\"M3 17l3 3 3-3\"/><path d=\"M6 18V4\"/></svg>`;\n\nexport const ICON_PAGE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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\"/><polyline points=\"10 9 9 9 8 9\"/></svg>`;\n\nexport const ICON_CHEVRON = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18n\n// ---------------------------------------------------------------------------\n\nexport const SORT_I18N_EN = {\n \"sort.newest\": \"Newest first\",\n \"sort.oldest\": \"Oldest first\",\n \"sort.byType\": \"By type\",\n \"sort.openFirst\": \"Open first\",\n \"sort.label\": \"Sort\",\n \"group.byPage\": \"By page\",\n \"group.feedbacks\": \"{count} feedbacks\",\n} as const;\n\nexport const SORT_I18N_FR = {\n \"sort.newest\": \"Plus récents\",\n \"sort.oldest\": \"Plus anciens\",\n \"sort.byType\": \"Par type\",\n \"sort.openFirst\": \"Ouverts d'abord\",\n \"sort.label\": \"Trier\",\n \"group.byPage\": \"Par page\",\n \"group.feedbacks\": \"{count} feedbacks\",\n} as const;\n\nexport type SortI18nKey = keyof typeof SORT_I18N_EN;\nexport type SortI18n = Record<SortI18nKey, string>;\n\n// ---------------------------------------------------------------------------\n// Sort utilities\n// ---------------------------------------------------------------------------\n\n/** Type priority for \"by-type\" sort: question, change, bug, other */\nconst TYPE_ORDER: Record<FeedbackType, number> = {\n question: 0,\n change: 1,\n bug: 2,\n other: 3,\n};\n\n/** Sort feedbacks according to the given mode. Returns a new array. */\nexport function sortFeedbacks(feedbacks: FeedbackResponse[], mode: SortMode): FeedbackResponse[] {\n const sorted = [...feedbacks];\n\n switch (mode) {\n case \"newest\":\n sorted.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n\n case \"oldest\":\n sorted.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());\n break;\n\n case \"by-type\":\n sorted.sort((a, b) => {\n const typeA = TYPE_ORDER[a.type] ?? 99;\n const typeB = TYPE_ORDER[b.type] ?? 99;\n if (typeA !== typeB) return typeA - typeB;\n // Within same type: newest first\n return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n });\n break;\n\n case \"open-first\":\n sorted.sort((a, b) => {\n // Open (0) before resolved (1)\n const statusA = a.status === \"open\" ? 0 : 1;\n const statusB = b.status === \"open\" ? 0 : 1;\n if (statusA !== statusB) return statusA - statusB;\n // Within same status: newest first\n return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n });\n break;\n }\n\n return sorted;\n}\n\n// ---------------------------------------------------------------------------\n// Group by page\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the pathname from a full URL string.\n * Falls back to the raw string if URL parsing fails.\n */\nfunction extractPathname(url: string): string {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n}\n\n/** Truncate a path string, keeping the beginning and end visible. */\nfunction truncatePath(path: string, maxLength: number): string {\n if (path.length <= maxLength) return path;\n const ellipsis = \"\\u2026\";\n const keep = Math.floor((maxLength - 1) / 2);\n return path.slice(0, keep) + ellipsis + path.slice(-keep);\n}\n\n/**\n * Group feedbacks by URL pathname.\n * Returns a Map sorted by feedback count descending (most feedbacks first).\n * Each group's feedbacks maintain their original order.\n */\nexport function groupFeedbacksByPage(feedbacks: FeedbackResponse[]): Map<string, FeedbackResponse[]> {\n const groups = new Map<string, FeedbackResponse[]>();\n\n for (const fb of feedbacks) {\n const path = extractPathname(fb.url);\n const existing = groups.get(path);\n if (existing) {\n existing.push(fb);\n } else {\n groups.set(path, [fb]);\n }\n }\n\n // Sort by count descending\n const sorted = new Map([...groups.entries()].sort((a, b) => b[1].length - a[1].length));\n\n return sorted;\n}\n\n// ---------------------------------------------------------------------------\n// Page group header\n// ---------------------------------------------------------------------------\n\n/**\n * Create a collapsible page group header element.\n * Click toggles the associated `.sp-group-content` sibling.\n */\nexport function createPageGroupHeader(pagePath: string, count: number, colors: ThemeColors): HTMLElement {\n const header = el(\"div\", { class: \"sp-group-header\" });\n header.setAttribute(\"role\", \"button\");\n header.setAttribute(\"tabindex\", \"0\");\n header.setAttribute(\"aria-expanded\", \"true\");\n header.style.borderBottomColor = colors.border;\n\n // Chevron\n const chevronWrap = el(\"span\", { class: \"sp-group-header-chevron\" });\n chevronWrap.appendChild(parseSvg(ICON_CHEVRON));\n header.appendChild(chevronWrap);\n\n // Page icon\n const pageIcon = el(\"span\", { class: \"sp-group-header-icon\" });\n pageIcon.appendChild(parseSvg(ICON_PAGE));\n header.appendChild(pageIcon);\n\n // Path\n const pathEl = el(\"span\", { class: \"sp-group-header-path\" });\n const displayPath = truncatePath(pagePath, 40);\n setText(pathEl, displayPath);\n if (pagePath.length > 40) {\n pathEl.title = pagePath;\n }\n header.appendChild(pathEl);\n\n // Count badge\n const countEl = el(\"span\", { class: \"sp-group-header-count\" });\n countEl.style.background = colors.accentLight;\n countEl.style.color = colors.accent;\n setText(countEl, String(count));\n header.appendChild(countEl);\n\n // Toggle behavior\n const toggle = () => {\n const isExpanded = header.getAttribute(\"aria-expanded\") === \"true\";\n header.setAttribute(\"aria-expanded\", String(!isExpanded));\n header.classList.toggle(\"sp-group-header--collapsed\", isExpanded);\n\n const content = header.nextElementSibling;\n if (content?.classList.contains(\"sp-group-content\")) {\n content.classList.toggle(\"sp-group-content--collapsed\", isExpanded);\n }\n };\n\n header.addEventListener(\"click\", toggle);\n header.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n\n return header;\n}\n\n// ---------------------------------------------------------------------------\n// PanelSortControls\n// ---------------------------------------------------------------------------\n\nexport class PanelSortControls {\n readonly element: HTMLElement;\n\n private _sortMode: SortMode = \"newest\";\n private _groupByPage = false;\n private menuEl: HTMLElement | null = null;\n private sortBtn: HTMLButtonElement;\n private groupToggle: HTMLButtonElement;\n private readonly i18n: SortI18n;\n private readonly colors: ThemeColors;\n private readonly onChange: () => void;\n private outsideClickHandler: ((e: MouseEvent) => void) | null = null;\n\n constructor(colors: ThemeColors, onChange: () => void, locale?: string) {\n this.colors = colors;\n this.onChange = onChange;\n this.i18n = locale === \"fr\" ? SORT_I18N_FR : SORT_I18N_EN;\n\n this.element = el(\"div\", { class: \"sp-sort-controls\" });\n\n // Sort button\n this.sortBtn = document.createElement(\"button\");\n this.sortBtn.className = \"sp-sort-btn\";\n this.sortBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.sortBtn.setAttribute(\"aria-expanded\", \"false\");\n this.sortBtn.setAttribute(\"aria-label\", this.i18n[\"sort.label\"]);\n\n const sortIcon = parseSvg(ICON_SORT);\n this.sortBtn.appendChild(sortIcon);\n\n const sortLabel = el(\"span\", { class: \"sp-sort-btn-label\" });\n setText(sortLabel, this.i18n[\"sort.newest\"]);\n this.sortBtn.appendChild(sortLabel);\n\n this.sortBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggleMenu();\n });\n\n // Group by page toggle\n this.groupToggle = document.createElement(\"button\");\n this.groupToggle.className = \"sp-group-toggle\";\n this.groupToggle.setAttribute(\"aria-pressed\", \"false\");\n\n const groupIcon = parseSvg(ICON_PAGE);\n this.groupToggle.appendChild(groupIcon);\n\n const groupLabel = el(\"span\", { class: \"sp-group-toggle-label\" });\n setText(groupLabel, this.i18n[\"group.byPage\"]);\n this.groupToggle.appendChild(groupLabel);\n\n this.groupToggle.addEventListener(\"click\", () => {\n this._groupByPage = !this._groupByPage;\n this.groupToggle.classList.toggle(\"sp-group-toggle--active\", this._groupByPage);\n this.groupToggle.setAttribute(\"aria-pressed\", String(this._groupByPage));\n this.onChange();\n });\n\n this.element.appendChild(this.sortBtn);\n this.element.appendChild(this.groupToggle);\n }\n\n get sortMode(): SortMode {\n return this._sortMode;\n }\n\n get groupByPage(): boolean {\n return this._groupByPage;\n }\n\n private toggleMenu(): void {\n if (this.menuEl) {\n this.closeMenu();\n return;\n }\n this.openMenu();\n }\n\n private openMenu(): void {\n this.menuEl = el(\"div\", { class: \"sp-sort-menu\" });\n this.menuEl.setAttribute(\"role\", \"listbox\");\n this.menuEl.setAttribute(\"aria-label\", this.i18n[\"sort.label\"]);\n this.sortBtn.setAttribute(\"aria-expanded\", \"true\");\n\n const options: { mode: SortMode; label: string }[] = [\n { mode: \"newest\", label: this.i18n[\"sort.newest\"] },\n { mode: \"oldest\", label: this.i18n[\"sort.oldest\"] },\n { mode: \"by-type\", label: this.i18n[\"sort.byType\"] },\n { mode: \"open-first\", label: this.i18n[\"sort.openFirst\"] },\n ];\n\n for (const opt of options) {\n const item = document.createElement(\"button\");\n item.className = `sp-sort-option${opt.mode === this._sortMode ? \" sp-sort-option--active\" : \"\"}`;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(opt.mode === this._sortMode));\n\n if (opt.mode === this._sortMode) {\n item.style.background = this.colors.accentLight;\n item.style.color = this.colors.accent;\n }\n\n setText(item, opt.label);\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this._sortMode = opt.mode;\n this.updateSortLabel();\n this.closeMenu();\n this.onChange();\n });\n\n this.menuEl.appendChild(item);\n }\n\n // Position relative to button\n this.element.appendChild(this.menuEl);\n\n // Close on outside click (next tick to avoid the current click)\n requestAnimationFrame(() => {\n this.outsideClickHandler = (e: MouseEvent) => {\n if (this.menuEl && !this.element.contains(e.target as Node)) {\n this.closeMenu();\n }\n };\n document.addEventListener(\"click\", this.outsideClickHandler, true);\n });\n\n // Close on Escape\n this.menuEl.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeMenu();\n this.sortBtn.focus();\n }\n });\n }\n\n private closeMenu(): void {\n if (this.menuEl) {\n this.menuEl.remove();\n this.menuEl = null;\n }\n this.sortBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.outsideClickHandler) {\n document.removeEventListener(\"click\", this.outsideClickHandler, true);\n this.outsideClickHandler = null;\n }\n }\n\n private updateSortLabel(): void {\n const labelMap: Record<SortMode, string> = {\n newest: this.i18n[\"sort.newest\"],\n oldest: this.i18n[\"sort.oldest\"],\n \"by-type\": this.i18n[\"sort.byType\"],\n \"open-first\": this.i18n[\"sort.openFirst\"],\n };\n const label = this.sortBtn.querySelector(\".sp-sort-btn-label\");\n if (label) setText(label as HTMLElement, labelMap[this._sortMode]);\n }\n\n destroy(): void {\n this.closeMenu();\n }\n}\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const SORT_CSS = `\n /* ============================\n Sort Controls Container\n ============================ */\n\n .sp-sort-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n padding-top: 8px;\n border-top: 1px solid var(--sp-border);\n }\n\n /* ============================\n Sort Dropdown Button\n ============================ */\n\n .sp-sort-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .sp-sort-btn svg {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n }\n\n .sp-sort-btn:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-sort-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Sort Floating Menu\n ============================ */\n\n .sp-sort-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n min-width: 170px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-sort-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-sort-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n /* ============================\n Sort Menu Option\n ============================ */\n\n .sp-sort-option {\n display: block;\n width: 100%;\n padding: 8px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: all 0.15s ease;\n }\n\n .sp-sort-option:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-sort-option--active {\n font-weight: 600;\n }\n\n .sp-sort-option--active:hover {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n /* ============================\n Group by Page Toggle\n ============================ */\n\n .sp-group-toggle {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: all 0.2s ease;\n }\n\n .sp-group-toggle svg {\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n }\n\n .sp-group-toggle:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-group-toggle--active {\n background: var(--sp-accent-gradient);\n border-color: transparent;\n color: #fff;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-group-toggle--active:hover {\n background: var(--sp-accent-gradient);\n border-color: transparent;\n color: #fff;\n }\n\n /* ============================\n Page Group Header\n ============================ */\n\n .sp-group-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--sp-accent-light);\n border-bottom: 1px solid var(--sp-border);\n cursor: pointer;\n user-select: none;\n position: sticky;\n top: 0;\n z-index: 2;\n transition: background 0.2s ease;\n }\n\n .sp-group-header:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-group-header:focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: -2px;\n }\n\n .sp-group-header-chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n transition: transform 0.2s ease;\n transform: rotate(90deg);\n }\n\n .sp-group-header-chevron svg {\n width: 12px;\n height: 12px;\n color: var(--sp-text-tertiary);\n }\n\n .sp-group-header--collapsed .sp-group-header-chevron {\n transform: rotate(0deg);\n }\n\n .sp-group-header-icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .sp-group-header-icon svg {\n width: 14px;\n height: 14px;\n color: var(--sp-text-tertiary);\n }\n\n .sp-group-header-path {\n font-size: 12px;\n font-weight: 600;\n color: var(--sp-text-secondary);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-group-header-count {\n font-size: 11px;\n font-weight: 700;\n padding: 1px 8px;\n border-radius: var(--sp-radius-full);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n }\n\n /* ============================\n Page Group Content\n ============================ */\n\n .sp-group-content {\n overflow: hidden;\n transition: max-height 0.25s ease, opacity 0.2s ease;\n max-height: 5000px;\n opacity: 1;\n }\n\n .sp-group-content--collapsed {\n max-height: 0;\n opacity: 0;\n pointer-events: none;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-sort-btn,\n .sp-group-toggle,\n .sp-sort-option,\n .sp-group-header {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-sort-btn:focus-visible,\n .sp-group-toggle:focus-visible,\n .sp-sort-option:focus-visible,\n .sp-group-header:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-sort-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n }\n\n /* ============================\n Reduced Motion\n ============================ */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-sort-menu {\n animation: none;\n }\n .sp-group-header-chevron {\n transition: none;\n }\n .sp-group-content {\n transition: none;\n }\n }\n`;\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// i18n — standalone constants, wired into the locale files at integration time\n// ---------------------------------------------------------------------------\n\nexport const STATS_I18N_EN = {\n \"stats.open\": \"Open\",\n \"stats.resolved\": \"Resolved\",\n \"stats.bugs\": \"Bugs\",\n \"stats.progress\": \"{percent}% resolved\",\n};\n\nexport const STATS_I18N_FR = {\n \"stats.open\": \"Ouverts\",\n \"stats.resolved\": \"Résolus\",\n \"stats.bugs\": \"Bugs\",\n \"stats.progress\": \"{percent}% résolus\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const STATS_CSS = /* css */ `\n .sp-stats-bar {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 24px;\n border-bottom: 1px solid var(--sp-border);\n user-select: none;\n }\n\n .sp-stats-bar[hidden] {\n display: none;\n }\n\n .sp-stats-row {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .sp-stats-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-stats-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .sp-stats-value {\n font-size: 16px;\n font-weight: 600;\n line-height: 1;\n color: var(--sp-text);\n font-variant-numeric: tabular-nums;\n font-feature-settings: \"tnum\";\n transition: opacity 0.3s ease;\n }\n\n .sp-stats-label {\n font-size: 11px;\n line-height: 1;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n\n .sp-stats-progress {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-stats-progress-track {\n flex: 1;\n height: 4px;\n border-radius: 2px;\n background: var(--sp-border);\n overflow: hidden;\n }\n\n .sp-stats-progress-fill {\n height: 100%;\n border-radius: 2px;\n background: linear-gradient(90deg, var(--sp-accent), #22c55e);\n width: 0%;\n transition: width 0.5s ease;\n }\n\n .sp-stats-progress-label {\n font-size: 10px;\n line-height: 1;\n color: var(--sp-text-tertiary);\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n font-feature-settings: \"tnum\";\n min-width: 64px;\n text-align: right;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Compact statistics bar displayed between filters and the feedback list.\n * Shows open/resolved/bug counts and a resolved-percentage progress bar.\n */\ntype StatsI18n = typeof STATS_I18N_EN;\n\nexport class PanelStats {\n readonly element: HTMLElement;\n\n private readonly valueOpen: HTMLElement;\n private readonly valueResolved: HTMLElement;\n private readonly valueBugs: HTMLElement;\n private readonly progressFill: HTMLElement;\n private readonly progressLabel: HTMLElement;\n private readonly i18n: StatsI18n;\n\n constructor(\n private readonly colors: ThemeColors,\n locale?: string,\n ) {\n this.i18n = locale === \"fr\" ? STATS_I18N_FR : STATS_I18N_EN;\n // Container\n this.element = el(\"div\", { class: \"sp-stats-bar\" });\n this.element.setAttribute(\"aria-label\", \"Feedback statistics\");\n this.element.hidden = true;\n\n // --- Stats row ---\n const row = el(\"div\", { class: \"sp-stats-row\" });\n\n // Open\n const itemOpen = el(\"div\", { class: \"sp-stats-item\" });\n const dotOpen = el(\"span\", { class: \"sp-stats-dot\" });\n dotOpen.style.background = \"#22c55e\";\n this.valueOpen = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueOpen, \"0\");\n const labelOpen = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelOpen, this.i18n[\"stats.open\"]);\n itemOpen.appendChild(dotOpen);\n itemOpen.appendChild(this.valueOpen);\n itemOpen.appendChild(labelOpen);\n\n // Resolved\n const itemResolved = el(\"div\", { class: \"sp-stats-item\" });\n const dotResolved = el(\"span\", { class: \"sp-stats-dot\" });\n dotResolved.style.background = \"#9ca3af\";\n this.valueResolved = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueResolved, \"0\");\n const labelResolved = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelResolved, this.i18n[\"stats.resolved\"]);\n itemResolved.appendChild(dotResolved);\n itemResolved.appendChild(this.valueResolved);\n itemResolved.appendChild(labelResolved);\n\n // Bugs\n const itemBugs = el(\"div\", { class: \"sp-stats-item\" });\n const dotBugs = el(\"span\", { class: \"sp-stats-dot\" });\n dotBugs.style.background = this.colors.typeBug;\n this.valueBugs = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueBugs, \"0\");\n const labelBugs = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelBugs, this.i18n[\"stats.bugs\"]);\n itemBugs.appendChild(dotBugs);\n itemBugs.appendChild(this.valueBugs);\n itemBugs.appendChild(labelBugs);\n\n row.appendChild(itemOpen);\n row.appendChild(itemResolved);\n row.appendChild(itemBugs);\n\n // --- Progress bar ---\n const progress = el(\"div\", { class: \"sp-stats-progress\" });\n const track = el(\"div\", { class: \"sp-stats-progress-track\" });\n this.progressFill = el(\"div\", { class: \"sp-stats-progress-fill\" });\n track.appendChild(this.progressFill);\n this.progressLabel = el(\"span\", { class: \"sp-stats-progress-label\" });\n setText(this.progressLabel, \"\");\n progress.appendChild(track);\n progress.appendChild(this.progressLabel);\n\n this.element.appendChild(row);\n this.element.appendChild(progress);\n }\n\n /** Update stats from current feedbacks array + total count. */\n update(feedbacks: FeedbackResponse[], total: number): void {\n // Hide when there are no feedbacks at all\n if (total === 0) {\n this.element.hidden = true;\n return;\n }\n this.element.hidden = false;\n\n let openCount = 0;\n let resolvedCount = 0;\n let bugCount = 0;\n\n for (const fb of feedbacks) {\n if (fb.status === \"open\") openCount++;\n if (fb.status === \"resolved\") resolvedCount++;\n if (fb.type === \"bug\") bugCount++;\n }\n\n setText(this.valueOpen, String(openCount));\n setText(this.valueResolved, String(resolvedCount));\n setText(this.valueBugs, String(bugCount));\n\n // Percentage resolved (relative to visible feedbacks, not total)\n const visible = feedbacks.length;\n const pct = visible > 0 ? Math.round((resolvedCount / visible) * 100) : 0;\n\n // Animate fill width via rAF so the transition kicks in after the DOM update\n requestAnimationFrame(() => {\n this.progressFill.style.width = `${pct}%`;\n });\n\n const progressText = this.i18n[\"stats.progress\"].replace(\"{percent}\", String(pct));\n setText(this.progressLabel, progressText);\n }\n}\n","/**\n * Keyboard shortcuts system for the feedback panel.\n *\n * Gmail/GitHub-style single-key shortcuts:\n * J/K — navigate cards, R — resolve, D — delete,\n * F or / — focus search, X — toggle select, ? — help overlay.\n *\n * Active only when the panel is open. Ignores keypresses inside\n * input/textarea elements. Uses a Map<string, handler> for O(1) lookup.\n */\n\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Icon\n// ---------------------------------------------------------------------------\n\nexport const ICON_KEYBOARD = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/><path d=\"M6 8h.01\"/><path d=\"M10 8h.01\"/><path d=\"M14 8h.01\"/><path d=\"M18 8h.01\"/><path d=\"M6 12h.01\"/><path d=\"M18 12h.01\"/><path d=\"M8 16h8\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// i18n\n// ---------------------------------------------------------------------------\n\nexport const SHORTCUTS_I18N_EN = {\n \"shortcuts.title\": \"Keyboard shortcuts\",\n \"shortcuts.navigate\": \"Navigate feedbacks\",\n \"shortcuts.resolve\": \"Resolve / Reopen\",\n \"shortcuts.delete\": \"Delete\",\n \"shortcuts.search\": \"Focus search\",\n \"shortcuts.select\": \"Toggle selection\",\n \"shortcuts.help\": \"Show shortcuts\",\n \"shortcuts.close\": \"Close\",\n \"shortcuts.hint\": \"Keyboard shortcuts\",\n} as const;\n\nexport const SHORTCUTS_I18N_FR = {\n \"shortcuts.title\": \"Raccourcis clavier\",\n \"shortcuts.navigate\": \"Naviguer les feedbacks\",\n \"shortcuts.resolve\": \"Résoudre / Rouvrir\",\n \"shortcuts.delete\": \"Supprimer\",\n \"shortcuts.search\": \"Rechercher\",\n \"shortcuts.select\": \"Sélectionner\",\n \"shortcuts.help\": \"Raccourcis\",\n \"shortcuts.close\": \"Fermer\",\n \"shortcuts.hint\": \"Raccourcis clavier\",\n} as const;\n\nexport type ShortcutsI18n = typeof SHORTCUTS_I18N_EN;\ntype I18nKey = keyof ShortcutsI18n;\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface ShortcutCallbacks {\n onNavigate: (direction: \"up\" | \"down\") => void;\n onResolve: () => void;\n onDelete: () => void;\n onFocusSearch: () => void;\n onToggleSelect: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Card focus helpers\n// ---------------------------------------------------------------------------\n\n/** Get the currently focused card index from the list container (-1 if none). */\nexport function getFocusedCardIndex(listContainer: HTMLElement): number {\n const cards = listContainer.querySelectorAll<HTMLElement>(\".sp-card\");\n for (let i = 0; i < cards.length; i++) {\n if (cards[i]?.classList.contains(\"sp-card--focused\")) return i;\n }\n return -1;\n}\n\n/** Focus a card by index in the list container. Clamps to valid range. */\nexport function focusCardByIndex(listContainer: HTMLElement, index: number): void {\n const cards = listContainer.querySelectorAll<HTMLElement>(\".sp-card\");\n if (cards.length === 0) return;\n\n // Remove previous focus\n for (const card of cards) {\n card.classList.remove(\"sp-card--focused\");\n }\n\n const clamped = Math.max(0, Math.min(index, cards.length - 1));\n const target = cards[clamped];\n if (!target) return;\n target.classList.add(\"sp-card--focused\");\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n target.focus({ preventScroll: true });\n}\n\n// ---------------------------------------------------------------------------\n// Shortcut definitions (used to build help grid)\n// ---------------------------------------------------------------------------\n\ninterface ShortcutDef {\n keys: string[];\n label: I18nKey;\n}\n\nconst SHORTCUT_DEFS: ShortcutDef[] = [\n { keys: [\"J\", \"K\"], label: \"shortcuts.navigate\" },\n { keys: [\"R\"], label: \"shortcuts.resolve\" },\n { keys: [\"D\"], label: \"shortcuts.delete\" },\n { keys: [\"F\", \"/\"], label: \"shortcuts.search\" },\n { keys: [\"X\"], label: \"shortcuts.select\" },\n { keys: [\"?\"], label: \"shortcuts.help\" },\n { keys: [\"Esc\"], label: \"shortcuts.close\" },\n];\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const SHORTCUTS_CSS = /* css */ `\n /* ---- Help overlay backdrop ---- */\n\n .sp-shortcuts-overlay {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s ease;\n }\n\n .sp-shortcuts-overlay--visible {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* ---- Glassmorphism card ---- */\n\n .sp-shortcuts-card {\n width: 380px;\n max-width: calc(100vw - 32px);\n padding: 24px 28px 20px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n position: relative;\n transform: scale(0.92) translateY(8px);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-shortcuts-overlay--visible .sp-shortcuts-card {\n transform: scale(1) translateY(0);\n }\n\n /* ---- Title row ---- */\n\n .sp-shortcuts-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 700;\n color: var(--sp-text);\n margin-bottom: 18px;\n }\n\n .sp-shortcuts-title svg {\n width: 18px;\n height: 18px;\n color: var(--sp-text-secondary);\n flex-shrink: 0;\n }\n\n /* ---- Close button ---- */\n\n .sp-shortcuts-close {\n position: absolute;\n top: 16px;\n right: 16px;\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--sp-text-tertiary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .sp-shortcuts-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-shortcuts-close svg {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Two-column grid ---- */\n\n .sp-shortcuts-grid {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .sp-shortcuts-row {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .sp-shortcuts-keys {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 80px;\n justify-content: flex-end;\n }\n\n .sp-shortcuts-separator {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n user-select: none;\n }\n\n /* ---- Key badge (<kbd> styling) ---- */\n\n .sp-kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 26px;\n padding: 0 7px;\n border-radius: 6px;\n background: var(--sp-bg-hover);\n border: 1px solid var(--sp-border);\n box-shadow:\n inset 0 -1px 0 rgba(0, 0, 0, 0.08),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n font-family: ui-monospace, \"SF Mono\", \"Cascadia Code\", \"Segoe UI Mono\", Menlo, monospace;\n font-size: 12px;\n font-weight: 600;\n color: var(--sp-text);\n text-align: center;\n line-height: 1;\n user-select: none;\n }\n\n /* ---- Description text ---- */\n\n .sp-shortcuts-desc {\n font-size: 13px;\n color: var(--sp-text-secondary);\n line-height: 1.3;\n }\n\n /* ---- Hint button (bottom-right of panel) ---- */\n\n .sp-shortcuts-hint {\n width: 24px;\n height: 24px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-bg-hover);\n color: var(--sp-text-tertiary);\n font-family: ui-monospace, \"SF Mono\", \"Cascadia Code\", \"Segoe UI Mono\", Menlo, monospace;\n font-size: 12px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n position: absolute;\n bottom: 12px;\n right: 12px;\n }\n\n .sp-shortcuts-hint:hover {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n border-color: var(--sp-accent);\n }\n\n .sp-shortcuts-hint::after {\n content: attr(aria-label);\n position: absolute;\n bottom: calc(100% + 6px);\n right: 0;\n padding: 4px 8px;\n border-radius: 6px;\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transform: translateY(4px);\n transition: opacity 0.15s ease, transform 0.15s ease;\n }\n\n .sp-shortcuts-hint:hover::after {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ---- Card focus highlight (navigation) ---- */\n\n .sp-card--focused {\n outline: 2px solid var(--sp-accent);\n outline-offset: -2px;\n border-radius: inherit;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-shortcuts-overlay,\n .sp-shortcuts-card,\n .sp-shortcuts-close,\n .sp-shortcuts-hint,\n .sp-shortcuts-hint::after {\n transition-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Close icon (small X) — reused from icons.ts pattern\n// ---------------------------------------------------------------------------\n\nconst ICON_CLOSE_SM = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// KeyboardShortcuts\n// ---------------------------------------------------------------------------\n\nexport class KeyboardShortcuts {\n /** Help overlay element — append to shadow root. */\n readonly helpOverlay: HTMLElement;\n /** Small \"?\" hint button — append inside the panel. */\n readonly hintButton: HTMLButtonElement;\n\n private readonly keyMap: Map<string, () => void>;\n private readonly boundHandler: (e: KeyboardEvent) => void;\n private shadowRoot: ShadowRoot | HTMLElement | null = null;\n private enabled = false;\n private helpVisible = false;\n private destroyed = false;\n\n constructor(\n _colors: ThemeColors,\n callbacks: ShortcutCallbacks,\n private readonly i18n: ShortcutsI18n = SHORTCUTS_I18N_EN,\n ) {\n // Build key map (O(1) dispatch)\n this.keyMap = new Map<string, () => void>([\n [\"j\", () => callbacks.onNavigate(\"down\")],\n [\"k\", () => callbacks.onNavigate(\"up\")],\n [\"r\", () => callbacks.onResolve()],\n [\"d\", () => callbacks.onDelete()],\n [\"f\", () => callbacks.onFocusSearch()],\n [\"/\", () => callbacks.onFocusSearch()],\n [\"x\", () => callbacks.onToggleSelect()],\n [\"?\", () => this.toggleHelp()],\n ]);\n\n // Build DOM\n this.helpOverlay = this.buildOverlay();\n this.hintButton = this.buildHintButton();\n\n // Bind handler once\n this.boundHandler = (e: KeyboardEvent) => this.handleKeydown(e);\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Enable shortcuts. Provide the shadow root (or document) to attach the listener. */\n enable(root?: ShadowRoot | HTMLElement): void {\n if (this.destroyed || this.enabled) return;\n if (root) this.shadowRoot = root;\n const target = this.shadowRoot ?? document;\n target.addEventListener(\"keydown\", this.boundHandler as EventListener);\n this.enabled = true;\n }\n\n /** Disable shortcuts (call when panel closes). */\n disable(): void {\n if (!this.enabled) return;\n const target = this.shadowRoot ?? document;\n target.removeEventListener(\"keydown\", this.boundHandler as EventListener);\n this.enabled = false;\n // Also hide help if visible\n if (this.helpVisible) this.hideHelp();\n }\n\n /** Show/hide help overlay. */\n toggleHelp(): void {\n if (this.helpVisible) {\n this.hideHelp();\n } else {\n this.showHelp();\n }\n }\n\n /** Destroy and clean up all listeners. */\n destroy(): void {\n if (this.destroyed) return;\n this.disable();\n this.helpOverlay.remove();\n this.hintButton.remove();\n this.destroyed = true;\n }\n\n // -------------------------------------------------------------------------\n // Keyboard handler\n // -------------------------------------------------------------------------\n\n private handleKeydown(e: KeyboardEvent): void {\n // Escape closes help overlay only (panel close handled elsewhere)\n if (e.key === \"Escape\") {\n if (this.helpVisible) {\n e.preventDefault();\n e.stopPropagation();\n this.hideHelp();\n }\n return;\n }\n\n // If help overlay is open, block all other shortcuts\n if (this.helpVisible) return;\n\n // Ignore when focus is in an input, textarea, or contenteditable\n const active = e.composedPath()[0] as HTMLElement | undefined;\n if (active) {\n const tag = active.tagName?.toLowerCase();\n if (tag === \"input\" || tag === \"textarea\" || tag === \"select\") return;\n if (active.isContentEditable) return;\n }\n\n // Ignore modified keys (Ctrl, Alt, Meta) — except Shift for \"?\"\n if (e.ctrlKey || e.altKey || e.metaKey) return;\n\n const handler = this.keyMap.get(e.key);\n if (handler) {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }\n }\n\n // -------------------------------------------------------------------------\n // Help overlay visibility\n // -------------------------------------------------------------------------\n\n private showHelp(): void {\n this.helpVisible = true;\n this.helpOverlay.classList.add(\"sp-shortcuts-overlay--visible\");\n\n // Focus the close button for accessibility\n const closeBtn = this.helpOverlay.querySelector<HTMLButtonElement>(\".sp-shortcuts-close\");\n closeBtn?.focus();\n }\n\n private hideHelp(): void {\n this.helpVisible = false;\n this.helpOverlay.classList.remove(\"sp-shortcuts-overlay--visible\");\n }\n\n // -------------------------------------------------------------------------\n // DOM builders\n // -------------------------------------------------------------------------\n\n private buildOverlay(): HTMLElement {\n const overlay = el(\"div\", { class: \"sp-shortcuts-overlay\" });\n overlay.setAttribute(\"role\", \"dialog\");\n overlay.setAttribute(\"aria-modal\", \"true\");\n overlay.setAttribute(\"aria-label\", this.i18n[\"shortcuts.title\"]);\n\n // Click backdrop to close\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) this.hideHelp();\n });\n\n const card = el(\"div\", { class: \"sp-shortcuts-card\" });\n\n // Title\n const title = el(\"div\", { class: \"sp-shortcuts-title\" });\n title.appendChild(parseSvg(ICON_KEYBOARD));\n const titleText = el(\"span\");\n setText(titleText, this.i18n[\"shortcuts.title\"]);\n title.appendChild(titleText);\n card.appendChild(title);\n\n // Close button\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"sp-shortcuts-close\";\n closeBtn.setAttribute(\"aria-label\", this.i18n[\"shortcuts.close\"]);\n closeBtn.appendChild(parseSvg(ICON_CLOSE_SM));\n closeBtn.addEventListener(\"click\", () => this.hideHelp());\n card.appendChild(closeBtn);\n\n // Grid\n const grid = el(\"div\", { class: \"sp-shortcuts-grid\" });\n\n for (const def of SHORTCUT_DEFS) {\n const row = el(\"div\", { class: \"sp-shortcuts-row\" });\n\n const keysWrap = el(\"div\", { class: \"sp-shortcuts-keys\" });\n def.keys.forEach((key, i) => {\n if (i > 0) {\n const sep = el(\"span\", { class: \"sp-shortcuts-separator\" });\n setText(sep, \"/\");\n keysWrap.appendChild(sep);\n }\n const kbd = el(\"span\", { class: \"sp-kbd\" });\n setText(kbd, key);\n keysWrap.appendChild(kbd);\n });\n\n const desc = el(\"span\", { class: \"sp-shortcuts-desc\" });\n setText(desc, this.i18n[def.label]);\n\n row.appendChild(keysWrap);\n row.appendChild(desc);\n grid.appendChild(row);\n }\n\n card.appendChild(grid);\n overlay.appendChild(card);\n\n return overlay;\n }\n\n private buildHintButton(): HTMLButtonElement {\n const btn = document.createElement(\"button\");\n btn.className = \"sp-shortcuts-hint\";\n btn.setAttribute(\"aria-label\", this.i18n[\"shortcuts.hint\"]);\n setText(btn, \"?\");\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggleHelp();\n });\n return btn;\n }\n}\n","import type { FeedbackResponse, FeedbackStatus, FeedbackType } from \"@siteping/core\";\nimport type { WidgetClient } from \"./api-client.js\";\nimport { PAGE_SIZE } from \"./constants.js\";\nimport { el, formatRelativeDate, parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { EXPORT_I18N_FR, ExportButton } from \"./export-utils.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport {\n ICON_BUG,\n ICON_CHANGE,\n ICON_CHECK,\n ICON_CHEVRON_DOWN,\n ICON_CLOSE,\n ICON_DOT_OPEN,\n ICON_LAYERS,\n ICON_OTHER,\n ICON_QUESTION,\n ICON_SEARCH,\n ICON_TRASH,\n ICON_UNDO,\n} from \"./icons.js\";\nimport type { MarkerManager } from \"./markers.js\";\nimport { BULK_I18N_EN, BULK_I18N_FR, BulkActions } from \"./panel-bulk.js\";\nimport { DetailView } from \"./panel-detail.js\";\nimport { createPageGroupHeader, groupFeedbacksByPage, PanelSortControls, sortFeedbacks } from \"./panel-sort.js\";\nimport { PanelStats } from \"./panel-stats.js\";\nimport {\n focusCardByIndex,\n getFocusedCardIndex,\n KeyboardShortcuts,\n SHORTCUTS_I18N_EN,\n SHORTCUTS_I18N_FR,\n} from \"./shortcuts.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n/**\n * Side panel (400px) with feedback history, filters, search, stats,\n * sort/group, bulk actions, export, detail view, and keyboard shortcuts.\n *\n * Lives inside the Shadow DOM.\n * Glassmorphism: glass background, staggered card animations,\n * loading states, resolve feedback with disabled state.\n */\nexport class Panel {\n private root: HTMLElement;\n private listContainer: HTMLElement;\n private searchInput: HTMLInputElement;\n private closeBtn: HTMLButtonElement;\n private deleteAllBtn: HTMLButtonElement;\n private activeFilters = new Set<string>([\"all\"]);\n private activeStatusFilter: \"all\" | FeedbackStatus = \"all\";\n private typeDropdownBtn!: HTMLButtonElement;\n private typeDropdownContainer!: HTMLElement;\n private typeDropdownMenu: HTMLElement | null = null;\n private typeDropdownOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private statusSegmented!: HTMLElement;\n private typeOptions!: ReadonlyArray<{ value: string; label: string; icon: string; color: string; bg: string }>;\n private statusOptions!: ReadonlyArray<{\n value: \"all\" | FeedbackStatus;\n label: string;\n icon: string;\n color: string;\n bg: string;\n }>;\n private feedbacks: FeedbackResponse[] = [];\n private currentPage = 1;\n private totalFeedbacks = 0;\n private isLoadingMore = false;\n private isOpen = false;\n private searchTimeout: ReturnType<typeof setTimeout> | null = null;\n private loadController: AbortController | null = null;\n /** Tracks feedback IDs with in-flight mutations to prevent spam-click race conditions */\n private pendingMutations = new Set<string>();\n\n // New feature modules\n private readonly stats: PanelStats;\n private readonly sortControls: PanelSortControls;\n private readonly bulk: BulkActions;\n private readonly exportBtn: ExportButton;\n private readonly shortcuts: KeyboardShortcuts;\n private readonly detail: DetailView;\n private readonly shadowRoot: ShadowRoot;\n\n // i18n helpers\n private readonly bulkI18n: typeof BULK_I18N_EN;\n\n constructor(\n shadowRoot: ShadowRoot,\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly client: WidgetClient,\n private readonly projectName: string,\n private readonly markers: MarkerManager,\n private readonly t: TFunction,\n private readonly locale: string,\n ) {\n this.shadowRoot = shadowRoot;\n this.bulkI18n = locale === \"fr\" ? BULK_I18N_FR : BULK_I18N_EN;\n\n this.root = el(\"div\", { class: \"sp-panel\" });\n this.root.setAttribute(\"role\", \"complementary\");\n this.root.setAttribute(\"aria-label\", this.t(\"panel.ariaLabel\"));\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n // --- Header ---\n const header = el(\"div\", { class: \"sp-panel-header\" });\n const title = el(\"span\", { class: \"sp-panel-title\" });\n setText(title, this.t(\"panel.title\"));\n\n this.closeBtn = document.createElement(\"button\");\n this.closeBtn.className = \"sp-panel-close\";\n this.closeBtn.setAttribute(\"aria-label\", this.t(\"panel.close\"));\n this.closeBtn.appendChild(parseSvg(ICON_CLOSE));\n this.closeBtn.addEventListener(\"click\", () => this.close());\n\n this.deleteAllBtn = document.createElement(\"button\");\n this.deleteAllBtn.className = \"sp-btn-delete-all\";\n this.deleteAllBtn.setAttribute(\"aria-label\", this.t(\"panel.deleteAll\"));\n this.deleteAllBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteAllLabel = document.createElement(\"span\");\n setText(deleteAllLabel, ` ${this.t(\"panel.deleteAll\")}`);\n this.deleteAllBtn.appendChild(deleteAllLabel);\n this.deleteAllBtn.addEventListener(\"click\", () => this.confirmDeleteAll());\n\n // Export button\n this.exportBtn = new ExportButton(colors, () => this.feedbacks);\n if (locale === \"fr\") this.exportBtn.setLabels(EXPORT_I18N_FR);\n\n const headerRight = el(\"div\", { class: \"sp-panel-header-right\" });\n headerRight.appendChild(this.exportBtn.element);\n headerRight.appendChild(this.deleteAllBtn);\n headerRight.appendChild(this.closeBtn);\n\n header.appendChild(title);\n header.appendChild(headerRight);\n\n // --- Stats ---\n this.stats = new PanelStats(colors, locale);\n\n // --- Filters ---\n const filters = el(\"div\", { class: \"sp-filters\" });\n\n // Search\n const searchWrap = el(\"div\", { class: \"sp-search-wrap\" });\n const searchIcon = parseSvg(ICON_SEARCH);\n searchIcon.setAttribute(\"class\", \"sp-search-icon\");\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"text\";\n this.searchInput.className = \"sp-search\";\n this.searchInput.placeholder = this.t(\"panel.search\");\n this.searchInput.setAttribute(\"aria-label\", this.t(\"panel.searchAria\"));\n this.searchInput.addEventListener(\"input\", () => {\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.searchTimeout = setTimeout(() => this.loadFeedbacks().catch(() => {}), 200);\n });\n searchWrap.appendChild(searchIcon);\n searchWrap.appendChild(this.searchInput);\n\n // Filter bar (type dropdown + status segmented control)\n const filterBar = el(\"div\", { class: \"sp-filter-bar\" });\n filterBar.appendChild(this.buildTypeDropdown());\n filterBar.appendChild(this.buildStatusSegmented());\n\n // Sort controls\n this.sortControls = new PanelSortControls(colors, () => this.renderList(), locale);\n\n filters.appendChild(searchWrap);\n filters.appendChild(filterBar);\n filters.appendChild(this.sortControls.element);\n\n // --- List ---\n this.listContainer = el(\"div\", { class: \"sp-list\" });\n this.listContainer.setAttribute(\"role\", \"list\");\n this.listContainer.setAttribute(\"aria-label\", this.t(\"panel.feedbackList\"));\n\n // --- Bulk Actions ---\n this.bulk = new BulkActions(\n colors,\n {\n onResolve: (ids) => this.bulkResolve(ids),\n onDelete: (ids) => this.bulkDelete(ids),\n },\n locale,\n );\n this.bulk.setListContainer(this.listContainer);\n\n // --- Detail View ---\n this.detail = new DetailView(\n colors,\n {\n onBack: () => this.detail.hide(),\n onResolve: async (fb) => {\n const newResolved = fb.status !== \"resolved\";\n await this.client.resolveFeedback(fb.id, newResolved);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onDelete: async (fb) => {\n await this.client.deleteFeedback(fb.id);\n this.bus.emit(\"feedback:deleted\", fb.id);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onGoToAnnotation: (fb) => {\n if (fb.annotations.length > 0) {\n const ann = fb.annotations[0];\n if (!ann) return;\n window.scrollTo({ left: ann.scrollX, top: ann.scrollY, behavior: \"smooth\" });\n this.markers.pinHighlight(fb);\n }\n },\n },\n locale,\n );\n\n // --- Keyboard Shortcuts ---\n const shortcutsI18n = (locale === \"fr\" ? SHORTCUTS_I18N_FR : SHORTCUTS_I18N_EN) as typeof SHORTCUTS_I18N_EN;\n this.shortcuts = new KeyboardShortcuts(\n colors,\n {\n onNavigate: (dir) => {\n const idx = getFocusedCardIndex(this.listContainer);\n focusCardByIndex(this.listContainer, dir === \"down\" ? idx + 1 : idx - 1);\n },\n onResolve: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"resolve\"]');\n if (btn) this.toggleResolve(fb, btn).catch(() => {});\n }\n },\n onDelete: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"delete\"]');\n if (btn) this.deleteFeedback(fb, btn).catch(() => {});\n }\n },\n onFocusSearch: () => this.searchInput.focus(),\n onToggleSelect: () => {\n const fb = this.getFocusedFeedback();\n if (fb) this.bulk.toggle(fb.id);\n },\n },\n shortcutsI18n,\n );\n\n // --- Assemble DOM ---\n this.root.appendChild(header);\n this.root.appendChild(this.stats.element);\n this.root.appendChild(filters);\n this.root.appendChild(this.listContainer);\n this.root.appendChild(this.bulk.barElement);\n this.root.appendChild(this.detail.element);\n this.root.appendChild(this.shortcuts.helpOverlay);\n this.root.appendChild(this.shortcuts.hintButton);\n shadowRoot.appendChild(this.root);\n\n // --- Event delegation on listContainer ---\n\n this.onListClick = (e: Event) => {\n const target = e.target as Element;\n\n // Bulk checkbox clicks are handled by BulkActions, skip\n if (target.closest(\".sp-bulk-checkbox\")) return;\n\n // Action buttons (expand, resolve, delete)\n const actionEl = target.closest<HTMLElement>(\"[data-action]\");\n if (actionEl) {\n e.stopPropagation();\n const card = actionEl.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (!feedback) return;\n\n const action = actionEl.dataset.action;\n if (action === \"expand\") {\n const message = card.querySelector<HTMLElement>(\".sp-card-message\");\n if (!message) return;\n const isExpanded = message.classList.toggle(\"sp-card-message--expanded\");\n setText(actionEl, isExpanded ? this.t(\"panel.showLess\") : this.t(\"panel.showMore\"));\n actionEl.setAttribute(\"aria-expanded\", String(isExpanded));\n } else if (action === \"resolve\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.toggleResolve(feedback, btn).catch(() => {});\n } else if (action === \"delete\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.deleteFeedback(feedback, btn).catch(() => {});\n }\n return;\n }\n\n // Card click → open detail view\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (card) {\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n }\n };\n this.listContainer.addEventListener(\"click\", this.onListClick);\n\n this.onListKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key !== \"Enter\" && ke.key !== \" \") return;\n const target = ke.target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n // Only activate if the card itself is focused, not a button inside it\n if (!card || target !== card) return;\n ke.preventDefault();\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n };\n this.listContainer.addEventListener(\"keydown\", this.onListKeydown);\n\n // mouseover/mouseout bubble (unlike mouseenter/mouseleave), enabling delegation\n this.onListMouseover = (e: Event) => {\n const target = (e as MouseEvent).target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n if (feedbackId) this.markers.highlight(feedbackId);\n };\n this.listContainer.addEventListener(\"mouseover\", this.onListMouseover);\n\n this.onListMouseout = (e: Event) => {\n const target = (e as MouseEvent).relatedTarget as Element | null;\n // Only clear highlight when leaving all cards (relatedTarget is outside listContainer)\n if (target && this.listContainer.contains(target)) return;\n this.markers.highlight(\"\");\n };\n this.listContainer.addEventListener(\"mouseout\", this.onListMouseout);\n\n // Events\n this.bus.on(\"panel:toggle\", (open) => {\n open ? this.open() : this.close();\n });\n\n // Keyboard handling: Escape to close + focus trap\n shadowRoot.addEventListener(\"keydown\", (e) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\" && this.isOpen) {\n // If detail view is open, close it instead\n if (this.detail.isVisible) {\n this.detail.hide();\n return;\n }\n this.close();\n return;\n }\n if (ke.key === \"Tab\" && this.isOpen) {\n const focusable = this.root.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first || !last) return;\n const active = (shadowRoot as ShadowRoot).activeElement;\n if (ke.shiftKey && active === first) {\n ke.preventDefault();\n last.focus();\n } else if (!ke.shiftKey && active === last) {\n ke.preventDefault();\n first.focus();\n }\n }\n });\n\n // Listen for marker clicks\n this.onMarkerClick = ((e: CustomEvent) => {\n this.scrollToFeedback(e.detail.feedbackId);\n }) as EventListener;\n document.addEventListener(\"sp-marker-click\", this.onMarkerClick);\n }\n\n private onMarkerClick: EventListener;\n private onListClick: (e: Event) => void;\n private onListKeydown: (e: Event) => void;\n private onListMouseover: (e: Event) => void;\n private onListMouseout: (e: Event) => void;\n\n async open(): Promise<void> {\n if (this.isOpen) return;\n this.isOpen = true;\n this.root.classList.add(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"false\");\n this.bus.emit(\"open\");\n this.shortcuts.enable(this.shadowRoot);\n await this.loadFeedbacks();\n // Move focus into the panel (search input or close button)\n requestAnimationFrame(() => {\n if (this.searchInput) {\n this.searchInput.focus();\n } else {\n this.closeBtn.focus();\n }\n });\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.root.classList.remove(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"true\");\n this.bus.emit(\"close\");\n this.shortcuts.disable();\n this.detail.hide();\n // Restore focus to the FAB\n const fab = (this.root.getRootNode() as ShadowRoot).querySelector<HTMLButtonElement>(\".sp-fab\");\n fab?.focus();\n }\n\n private showLoading(): void {\n this.listContainer.replaceChildren();\n const loading = el(\"div\", { class: \"sp-loading\" });\n loading.setAttribute(\"role\", \"status\");\n loading.setAttribute(\"aria-live\", \"polite\");\n loading.setAttribute(\"aria-label\", this.t(\"panel.loading\"));\n const spinner = el(\"div\", { class: \"sp-spinner\" });\n loading.appendChild(spinner);\n this.listContainer.appendChild(loading);\n }\n\n private showError(): void {\n this.listContainer.replaceChildren();\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const text = el(\"div\", { class: \"sp-empty-text\" });\n setText(text, this.t(\"panel.loadError\"));\n const retryBtn = document.createElement(\"button\");\n retryBtn.className = \"sp-btn-ghost\";\n retryBtn.style.marginTop = \"8px\";\n setText(retryBtn, this.t(\"panel.retry\"));\n retryBtn.addEventListener(\"click\", () => this.loadFeedbacks().catch(() => {}));\n empty.appendChild(text);\n empty.appendChild(retryBtn);\n this.listContainer.appendChild(empty);\n }\n\n private async loadFeedbacks(): Promise<void> {\n // Cancel any in-flight request to prevent stale responses from overwriting newer results\n this.loadController?.abort();\n this.loadController = new AbortController();\n const { signal } = this.loadController;\n\n // Reset to page 1 on fresh load (filter/search change)\n this.currentPage = 1;\n\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const statusFilter = this.activeStatusFilter === \"all\" ? undefined : this.activeStatusFilter;\n\n const options: { page: number; limit: number; type?: FeedbackType; status?: FeedbackStatus; search?: string } = {\n page: 1,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n\n // Only show spinner on first load (empty list) — otherwise keep current content visible\n const hasContent = this.feedbacks.length > 0;\n if (!hasContent) this.showLoading();\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (signal.aborted) return; // Stale response — a newer request superseded this one\n this.feedbacks = feedbacks;\n this.totalFeedbacks = total;\n this.stats.update(feedbacks, total);\n this.bulk.reset();\n this.renderList();\n this.markers.render(feedbacks);\n } catch (error) {\n if (signal.aborted) return; // Expected abort, not a real error\n if (!hasContent) this.showError();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private async loadMoreFeedbacks(): Promise<void> {\n if (this.isLoadingMore) return;\n this.isLoadingMore = true;\n\n // Capture current controller — if loadFeedbacks() runs while we're in-flight,\n // it replaces the controller, signaling that our results are stale.\n const controller = this.loadController;\n\n const nextPage = this.currentPage + 1;\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const statusFilter = this.activeStatusFilter === \"all\" ? undefined : this.activeStatusFilter;\n\n const options: { page: number; limit: number; type?: FeedbackType; status?: FeedbackStatus; search?: string } = {\n page: nextPage,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n\n // Show spinner on the \"Load more\" button\n const loadMoreBtn = this.listContainer.querySelector<HTMLButtonElement>(\".sp-btn-load-more\");\n let restoreBtn: (() => void) | undefined;\n if (loadMoreBtn) restoreBtn = this.setButtonLoading(loadMoreBtn);\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (controller !== this.loadController) return; // Filter/search changed — discard stale page\n this.currentPage = nextPage;\n this.totalFeedbacks = total;\n this.feedbacks = [...this.feedbacks, ...feedbacks];\n this.stats.update(this.feedbacks, total);\n this.renderList();\n this.markers.render(this.feedbacks);\n } catch (error) {\n if (restoreBtn) restoreBtn();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.isLoadingMore = false;\n }\n }\n\n private renderList(): void {\n this.listContainer.replaceChildren();\n\n if (this.feedbacks.length === 0) {\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const emptyText = el(\"div\", { class: \"sp-empty-text\" });\n setText(emptyText, this.t(\"panel.empty\"));\n empty.appendChild(emptyText);\n this.listContainer.appendChild(empty);\n return;\n }\n\n // Apply sorting\n const sorted = sortFeedbacks(this.feedbacks, this.sortControls.sortMode);\n\n // Select all bar\n const feedbackIds = sorted.map((f) => f.id);\n const selectAllBar = this.bulk.createSelectAllBar(feedbackIds, this.bulkI18n[\"bulk.selectAll\"]);\n this.listContainer.appendChild(selectAllBar);\n\n if (this.sortControls.groupByPage) {\n // Group by page rendering\n const groups = groupFeedbacksByPage(sorted);\n let globalIndex = 0;\n for (const [pagePath, groupFeedbacks] of groups) {\n const groupHeader = createPageGroupHeader(pagePath, groupFeedbacks.length, this.colors);\n this.listContainer.appendChild(groupHeader);\n\n const groupContent = el(\"div\", { class: \"sp-group-content\" });\n for (const feedback of groupFeedbacks) {\n const card = this.createCard(feedback, globalIndex + 1);\n card.style.setProperty(\"--sp-card-i\", String(globalIndex));\n groupContent.appendChild(card);\n globalIndex++;\n }\n this.listContainer.appendChild(groupContent);\n }\n } else {\n // Flat list rendering\n sorted.forEach((feedback, index) => {\n const card = this.createCard(feedback, index + 1);\n card.style.setProperty(\"--sp-card-i\", String(index));\n this.listContainer.appendChild(card);\n });\n }\n\n // \"Load more\" button when there are remaining feedbacks\n const remaining = this.totalFeedbacks - this.feedbacks.length;\n if (remaining > 0) {\n const loadMoreWrap = el(\"div\", { class: \"sp-load-more-wrap\" });\n const loadMoreBtn = document.createElement(\"button\");\n loadMoreBtn.className = \"sp-btn-ghost sp-btn-load-more\";\n setText(loadMoreBtn, this.t(\"panel.loadMore\").replace(\"{remaining}\", String(remaining)));\n loadMoreBtn.addEventListener(\"click\", () => this.loadMoreFeedbacks().catch(() => {}));\n loadMoreWrap.appendChild(loadMoreBtn);\n this.listContainer.appendChild(loadMoreWrap);\n }\n }\n\n private createCard(feedback: FeedbackResponse, number: number): HTMLElement {\n const isResolved = feedback.status === \"resolved\";\n const typeColor = getTypeColor(feedback.type, this.colors);\n\n const card = el(\"div\", {\n class: `sp-card ${isResolved ? \"sp-card--resolved\" : \"\"}`,\n });\n card.setAttribute(\"role\", \"listitem\");\n card.setAttribute(\"tabindex\", \"0\");\n card.setAttribute(\n \"aria-label\",\n `Feedback #${number}: ${getTypeLabel(feedback.type, this.t)} — ${feedback.message.slice(0, 80)}`,\n );\n card.dataset.feedbackId = feedback.id;\n\n // Color bar\n const bar = el(\"div\", { class: \"sp-card-bar\" });\n bar.style.background = isResolved ? \"#9ca3af\" : typeColor;\n\n // Body\n const body = el(\"div\", { class: \"sp-card-body\" });\n\n // Header: checkbox + #number + badge + date\n const header = el(\"div\", { class: \"sp-card-header\" });\n\n // Bulk checkbox — inline in the header row\n const checkbox = this.bulk.createCheckbox(feedback.id);\n header.appendChild(checkbox);\n\n const num = el(\"span\", { class: \"sp-card-number\" });\n setText(num, `#${number}`);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n badge.style.background = typeBg;\n badge.style.color = typeColor;\n setText(badge, getTypeLabel(feedback.type, this.t));\n\n const date = el(\"span\", { class: \"sp-card-date\" });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(num);\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message\n const message = el(\"div\", { class: \"sp-card-message\" });\n setText(message, feedback.message);\n\n // Expand button\n const expandBtn = document.createElement(\"button\");\n expandBtn.className = \"sp-card-expand\";\n expandBtn.dataset.action = \"expand\";\n setText(expandBtn, this.t(\"panel.showMore\"));\n expandBtn.style.display = \"none\";\n expandBtn.setAttribute(\"aria-expanded\", \"false\");\n\n // Check if text is clamped (after render)\n requestAnimationFrame(() => {\n if (message.scrollHeight > message.clientHeight) {\n expandBtn.style.display = \"block\";\n }\n });\n\n // Footer: resolve button\n const footer = el(\"div\", { class: \"sp-card-footer\" });\n\n const resolveBtn = document.createElement(\"button\");\n resolveBtn.className = \"sp-btn-resolve\";\n resolveBtn.dataset.action = \"resolve\";\n if (isResolved) {\n resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.reopen\")}`);\n resolveBtn.appendChild(span);\n } else {\n resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.resolve\")}`);\n resolveBtn.appendChild(span);\n }\n\n const deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"sp-btn-delete\";\n deleteBtn.dataset.action = \"delete\";\n deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteBtnLabel = document.createElement(\"span\");\n setText(deleteBtnLabel, ` ${this.t(\"panel.delete\")}`);\n deleteBtn.appendChild(deleteBtnLabel);\n\n footer.appendChild(resolveBtn);\n footer.appendChild(deleteBtn);\n\n body.appendChild(header);\n body.appendChild(message);\n body.appendChild(expandBtn);\n body.appendChild(footer);\n\n card.appendChild(bar);\n card.appendChild(body);\n\n return card;\n }\n\n // ---------------------------------------------------------------------------\n // Bulk operations\n // ---------------------------------------------------------------------------\n\n private async bulkResolve(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.resolveFeedback(id, true)));\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n private async bulkDelete(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.deleteFeedback(id)));\n for (const id of ids) this.bus.emit(\"feedback:deleted\", id);\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Existing methods (preserved)\n // ---------------------------------------------------------------------------\n\n private async confirmDeleteAll(): Promise<void> {\n const confirmed = await this.showConfirmDialog(\n this.t(\"panel.deleteAllConfirmTitle\"),\n this.t(\"panel.deleteAllConfirmMessage\"),\n );\n if (!confirmed) return;\n\n this.deleteAllBtn.disabled = true;\n try {\n await this.client.deleteAllFeedbacks(this.projectName);\n this.bus.emit(\"feedback:all-deleted\");\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.deleteAllBtn.disabled = false;\n }\n }\n\n private showConfirmDialog(title: string, message: string): Promise<boolean> {\n return new Promise((resolve) => {\n const backdrop = el(\"div\", { class: \"sp-confirm-backdrop\" });\n\n const titleId = `sp-confirm-title-${Date.now()}`;\n const messageId = `sp-confirm-msg-${Date.now()}`;\n\n const dialog = el(\"div\", { class: \"sp-confirm-dialog\" });\n dialog.setAttribute(\"role\", \"alertdialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", titleId);\n dialog.setAttribute(\"aria-describedby\", messageId);\n\n const titleEl = el(\"div\", { class: \"sp-confirm-title\" });\n titleEl.id = titleId;\n setText(titleEl, title);\n\n const messageEl = el(\"div\", { class: \"sp-confirm-message\" });\n messageEl.id = messageId;\n setText(messageEl, message);\n\n const btnRow = el(\"div\", { class: \"sp-confirm-actions\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.type = \"button\";\n cancelBtn.className = \"sp-btn-ghost\";\n setText(cancelBtn, this.t(\"panel.cancel\"));\n\n const confirmBtn = document.createElement(\"button\");\n confirmBtn.type = \"button\";\n confirmBtn.className = \"sp-btn-danger\";\n setText(confirmBtn, this.t(\"panel.confirmDelete\"));\n\n let closed = false;\n const close = (result: boolean) => {\n if (closed) return;\n closed = true;\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n dialog.style.transform = \"translateY(8px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n resolve(result);\n }, 200);\n };\n\n // Focus trap: Tab cycles between cancel and confirm\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n close(false);\n return;\n }\n if (ke.key === \"Tab\") {\n ke.preventDefault();\n const active = (backdrop.getRootNode() as ShadowRoot).activeElement;\n if (active === cancelBtn) {\n confirmBtn.focus();\n } else {\n cancelBtn.focus();\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n cancelBtn.addEventListener(\"click\", () => close(false));\n confirmBtn.addEventListener(\"click\", () => close(true));\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) close(false);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(confirmBtn);\n dialog.appendChild(titleEl);\n dialog.appendChild(messageEl);\n dialog.appendChild(btnRow);\n backdrop.appendChild(dialog);\n\n this.root.getRootNode() instanceof ShadowRoot\n ? (this.root.getRootNode() as ShadowRoot).appendChild(backdrop)\n : this.root.appendChild(backdrop);\n\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n dialog.style.transform = \"translateY(0) scale(1)\";\n cancelBtn.focus();\n });\n });\n }\n\n private setButtonLoading(btn: HTMLButtonElement): () => void {\n const snapshot = Array.from(btn.childNodes).map((n) => n.cloneNode(true));\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n return () => {\n btn.replaceChildren(...snapshot);\n btn.disabled = false;\n };\n }\n\n private async deleteFeedback(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = this.setButtonLoading(btn);\n try {\n await this.client.deleteFeedback(feedback.id);\n this.bus.emit(\"feedback:deleted\", feedback.id);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private async toggleResolve(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = this.setButtonLoading(btn);\n try {\n const newResolved = feedback.status !== \"resolved\";\n await this.client.resolveFeedback(feedback.id, newResolved);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private buildTypeDropdown(): HTMLElement {\n this.typeOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.filterAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"question\",\n label: this.t(\"type.question\"),\n icon: ICON_QUESTION,\n color: this.colors.typeQuestion,\n bg: this.colors.typeQuestionBg,\n },\n {\n value: \"change\",\n label: this.t(\"type.change\"),\n icon: ICON_CHANGE,\n color: this.colors.typeChange,\n bg: this.colors.typeChangeBg,\n },\n {\n value: \"bug\",\n label: this.t(\"type.bug\"),\n icon: ICON_BUG,\n color: this.colors.typeBug,\n bg: this.colors.typeBugBg,\n },\n {\n value: \"other\",\n label: this.t(\"type.other\"),\n icon: ICON_OTHER,\n color: this.colors.typeOther,\n bg: this.colors.typeOtherBg,\n },\n ];\n\n this.typeDropdownContainer = el(\"div\", { class: \"sp-filter-dropdown\" });\n\n this.typeDropdownBtn = document.createElement(\"button\");\n this.typeDropdownBtn.type = \"button\";\n this.typeDropdownBtn.className = \"sp-filter-dropdown-btn\";\n this.typeDropdownBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n this.renderTypeDropdownTrigger();\n\n this.typeDropdownBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n if (this.typeDropdownMenu) this.closeTypeDropdown();\n else this.openTypeDropdown();\n });\n\n this.typeDropdownContainer.appendChild(this.typeDropdownBtn);\n return this.typeDropdownContainer;\n }\n\n private renderTypeDropdownTrigger(): void {\n const active = this.typeOptions.find((o) => this.activeFilters.has(o.value)) ?? this.typeOptions[0];\n if (!active) return;\n\n this.typeDropdownBtn.replaceChildren();\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-color\", active.color);\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-bg\", active.bg);\n this.typeDropdownBtn.dataset.filter = active.value;\n this.typeDropdownBtn.classList.toggle(\"sp-filter-dropdown-btn--filtered\", active.value !== \"all\");\n this.typeDropdownBtn.setAttribute(\"aria-label\", `${this.t(\"type.label\")}: ${active.label}`);\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__icon\" });\n iconWrap.appendChild(parseSvg(active.icon));\n this.typeDropdownBtn.appendChild(iconWrap);\n\n const labelWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__label\" });\n const prefix = el(\"span\", { class: \"sp-filter-dropdown-btn__prefix\" });\n setText(prefix, this.t(\"type.label\"));\n const value = el(\"span\", { class: \"sp-filter-dropdown-btn__value\" });\n setText(value, active.label);\n labelWrap.appendChild(prefix);\n labelWrap.appendChild(value);\n this.typeDropdownBtn.appendChild(labelWrap);\n\n const chevron = el(\"span\", { class: \"sp-filter-dropdown-btn__chevron\" });\n chevron.appendChild(parseSvg(ICON_CHEVRON_DOWN));\n this.typeDropdownBtn.appendChild(chevron);\n }\n\n private openTypeDropdown(): void {\n this.typeDropdownMenu = el(\"div\", { class: \"sp-filter-dropdown-menu\" });\n this.typeDropdownMenu.setAttribute(\"role\", \"listbox\");\n this.typeDropdownMenu.setAttribute(\"aria-label\", this.t(\"type.label\"));\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"true\");\n\n for (const option of this.typeOptions) {\n const item = document.createElement(\"button\");\n item.type = \"button\";\n const isActive = this.activeFilters.has(option.value);\n item.className = `sp-filter-dropdown-option${isActive ? \" sp-filter-dropdown-option--active\" : \"\"}`;\n item.style.setProperty(\"--sp-chip-color\", option.color);\n item.style.setProperty(\"--sp-chip-bg\", option.bg);\n item.dataset.filter = option.value;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(isActive));\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-option__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n item.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-filter-dropdown-option__label\" });\n setText(labelEl, option.label);\n item.appendChild(labelEl);\n\n if (isActive) {\n const checkWrap = el(\"span\", { class: \"sp-filter-dropdown-option__check\" });\n checkWrap.appendChild(parseSvg(ICON_CHECK));\n item.appendChild(checkWrap);\n }\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.selectTypeFilter(option.value);\n });\n\n this.typeDropdownMenu.appendChild(item);\n }\n\n this.typeDropdownContainer.appendChild(this.typeDropdownMenu);\n\n requestAnimationFrame(() => {\n this.typeDropdownOutsideHandler = (e: MouseEvent) => {\n if (this.typeDropdownMenu && !this.typeDropdownContainer.contains(e.target as Node)) {\n this.closeTypeDropdown();\n }\n };\n document.addEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n });\n\n this.typeDropdownMenu.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeTypeDropdown();\n this.typeDropdownBtn.focus();\n }\n });\n }\n\n private closeTypeDropdown(): void {\n if (this.typeDropdownMenu) {\n this.typeDropdownMenu.remove();\n this.typeDropdownMenu = null;\n }\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.typeDropdownOutsideHandler) {\n document.removeEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n this.typeDropdownOutsideHandler = null;\n }\n }\n\n private selectTypeFilter(value: string): void {\n this.activeFilters.clear();\n this.activeFilters.add(value);\n this.renderTypeDropdownTrigger();\n this.closeTypeDropdown();\n this.loadFeedbacks().catch(() => {});\n }\n\n private buildStatusSegmented(): HTMLElement {\n this.statusOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.statusAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"open\",\n label: this.t(\"panel.statusOpen\"),\n icon: ICON_DOT_OPEN,\n color: this.colors.statusOpen,\n bg: this.colors.statusOpenBg,\n },\n {\n value: \"resolved\",\n label: this.t(\"panel.statusResolved\"),\n icon: ICON_CHECK,\n color: this.colors.statusResolved,\n bg: this.colors.statusResolvedBg,\n },\n ];\n\n this.statusSegmented = el(\"div\", { class: \"sp-segmented\", role: \"radiogroup\" });\n this.statusSegmented.setAttribute(\"aria-label\", this.t(\"status.label\"));\n\n for (const option of this.statusOptions) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = `sp-segmented__btn sp-segmented__btn--${option.value}`;\n btn.dataset.statusFilter = option.value;\n btn.setAttribute(\"role\", \"radio\");\n const isActive = this.activeStatusFilter === option.value;\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n if (isActive) btn.classList.add(\"sp-segmented__btn--active\");\n btn.style.setProperty(\"--sp-chip-color\", option.color);\n btn.style.setProperty(\"--sp-chip-bg\", option.bg);\n\n const iconWrap = el(\"span\", { class: \"sp-segmented__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n btn.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-segmented__label\" });\n setText(labelEl, option.label);\n btn.appendChild(labelEl);\n\n btn.addEventListener(\"click\", () => this.selectStatusFilter(option.value));\n btn.addEventListener(\"keydown\", (e) => this.handleSegmentedKey(e, option.value));\n\n this.statusSegmented.appendChild(btn);\n }\n\n return this.statusSegmented;\n }\n\n private handleSegmentedKey(e: KeyboardEvent, current: \"all\" | FeedbackStatus): void {\n const values = this.statusOptions.map((o) => o.value);\n const idx = values.indexOf(current);\n let nextIdx: number;\n switch (e.key) {\n case \"ArrowLeft\":\n nextIdx = (idx - 1 + values.length) % values.length;\n break;\n case \"ArrowRight\":\n nextIdx = (idx + 1) % values.length;\n break;\n case \"Home\":\n nextIdx = 0;\n break;\n case \"End\":\n nextIdx = values.length - 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n const next = values[nextIdx];\n if (!next) return;\n this.selectStatusFilter(next);\n const btn = this.statusSegmented.querySelector<HTMLButtonElement>(`[data-status-filter=\"${next}\"]`);\n btn?.focus();\n }\n\n private selectStatusFilter(value: \"all\" | FeedbackStatus): void {\n this.activeStatusFilter = value;\n const buttons = this.statusSegmented.querySelectorAll<HTMLButtonElement>(\".sp-segmented__btn\");\n for (const btn of buttons) {\n const isActive = btn.dataset.statusFilter === value;\n btn.classList.toggle(\"sp-segmented__btn--active\", isActive);\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n }\n this.loadFeedbacks().catch(() => {});\n }\n\n /** Get the focused feedback (for keyboard shortcuts) */\n private getFocusedFeedback(): FeedbackResponse | undefined {\n const idx = getFocusedCardIndex(this.listContainer);\n if (idx < 0) return undefined;\n const card = this.listContainer.querySelectorAll<HTMLElement>(\".sp-card\")[idx];\n if (!card) return undefined;\n return this.feedbacks.find((f) => f.id === card.dataset.feedbackId);\n }\n\n scrollToFeedback(feedbackId: string): void {\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n card.classList.add(\"sp-anim-flash\");\n card.addEventListener(\n \"animationend\",\n () => {\n card.classList.remove(\"sp-anim-flash\");\n },\n { once: true },\n );\n }\n }\n\n /** Refresh the panel after a new feedback is submitted */\n async refresh(): Promise<void> {\n if (this.isOpen) {\n await this.loadFeedbacks();\n }\n }\n\n destroy(): void {\n this.loadController?.abort();\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.listContainer.removeEventListener(\"click\", this.onListClick);\n this.listContainer.removeEventListener(\"keydown\", this.onListKeydown);\n this.listContainer.removeEventListener(\"mouseover\", this.onListMouseover);\n this.listContainer.removeEventListener(\"mouseout\", this.onListMouseout);\n document.removeEventListener(\"sp-marker-click\", this.onMarkerClick);\n this.closeTypeDropdown();\n this.sortControls.destroy();\n this.bulk.destroy();\n this.exportBtn.destroy();\n this.shortcuts.destroy();\n this.detail.destroy();\n this.root.remove();\n }\n}\n","// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\n/** Configuration options for the Siteping widget. */\nexport interface SitepingConfig {\n /** HTTP endpoint that receives feedbacks (e.g. '/api/siteping'). Required unless `store` is provided. */\n endpoint?: string | undefined;\n /** Required — project identifier used to scope feedbacks */\n projectName: string;\n /** Direct store for client-side mode. When set, bypasses HTTP and uses the store directly in the browser. */\n store?: SitepingStore | undefined;\n /** FAB position — defaults to 'bottom-right' */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Accent color for the widget UI — defaults to '#0066ff' */\n accentColor?: string;\n /** Show the widget even in production — defaults to false */\n forceShow?: boolean;\n /** Enable debug logging of lifecycle events — defaults to false */\n debug?: boolean;\n /** Color theme — defaults to 'light' */\n theme?: \"light\" | \"dark\" | \"auto\";\n /** UI locale — defaults to 'en'. Built-in: en, fr, de, es, it, pt (Brazilian), ru. Any other string falls back to English. */\n locale?: \"en\" | \"fr\" | \"de\" | \"es\" | \"it\" | \"pt\" | \"ru\" | (string & {}) | undefined;\n /** Called when the widget is skipped (production mode, mobile viewport) */\n onSkip?: (reason: \"production\" | \"mobile\") => void;\n\n // Events\n /** Called when the feedback panel is opened. */\n onOpen?: () => void;\n /** Called when the feedback panel is closed. */\n onClose?: () => void;\n onFeedbackSent?: (feedback: FeedbackResponse) => void;\n onError?: (error: Error) => void;\n /** Called when the user starts drawing an annotation. */\n onAnnotationStart?: () => void;\n /** Called when the user finishes drawing an annotation. */\n onAnnotationEnd?: () => void;\n}\n\n/** Instance returned by initSiteping() with lifecycle methods. */\nexport interface SitepingInstance {\n /** Remove the widget from the DOM and clean up all listeners. */\n destroy: () => void;\n /** Open the panel programmatically */\n open: () => void;\n /** Close the panel */\n close: () => void;\n /** Reload feedbacks from server */\n refresh: () => void;\n /** Subscribe to a public widget event */\n on: <K extends keyof SitepingPublicEvents>(\n event: K,\n listener: (...args: SitepingPublicEvents[K]) => void,\n ) => () => void;\n /** Unsubscribe from a public widget event */\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => void;\n}\n\n/** Events exposed to consumers via SitepingInstance.on / .off */\nexport interface SitepingPublicEvents {\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [string];\n \"panel:open\": [];\n \"panel:close\": [];\n}\n\n// ---------------------------------------------------------------------------\n// Feedback\n// ---------------------------------------------------------------------------\n\n/** Single source of truth for feedback types — used by both TS types and Zod schemas. */\nexport const FEEDBACK_TYPES = [\"question\", \"change\", \"bug\", \"other\"] as const;\nexport type FeedbackType = (typeof FEEDBACK_TYPES)[number];\n\n/** Single source of truth for feedback statuses. */\nexport const FEEDBACK_STATUSES = [\"open\", \"resolved\"] as const;\nexport type FeedbackStatus = (typeof FEEDBACK_STATUSES)[number];\n\n// ---------------------------------------------------------------------------\n// Abstract Store — adapter pattern\n// ---------------------------------------------------------------------------\n\n/** Input for creating a feedback record in the store. */\nexport interface FeedbackCreateInput {\n projectName: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n url: string;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n clientId: string;\n annotations: AnnotationCreateInput[];\n}\n\n/** Input for a single annotation when creating a feedback. */\nexport interface AnnotationCreateInput {\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId?: string | undefined;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n}\n\n/** Query parameters for fetching feedbacks. */\nexport interface FeedbackQuery {\n projectName: string;\n type?: FeedbackType | undefined;\n status?: FeedbackStatus | undefined;\n search?: string | undefined;\n page?: number | undefined;\n limit?: number | undefined;\n}\n\n/** Update payload for patching a feedback. */\nexport interface FeedbackUpdateInput {\n status: FeedbackStatus;\n resolvedAt: Date | null;\n}\n\n/** A persisted feedback record returned by the store. */\nexport interface FeedbackRecord {\n id: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n projectName: string;\n url: string;\n authorName: string;\n authorEmail: string;\n viewport: string;\n userAgent: string;\n clientId: string;\n resolvedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n annotations: AnnotationRecord[];\n}\n\n/** A persisted annotation record returned by the store. */\nexport interface AnnotationRecord {\n id: string;\n feedbackId: string;\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId: string | null;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n createdAt: Date;\n}\n\n// ---------------------------------------------------------------------------\n// Store errors — throw these from adapter implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when a record is not found during update or delete.\n *\n * Handlers translate this to HTTP 404. Adapters MUST throw this (not\n * ORM-specific errors) so the handler layer remains ORM-agnostic.\n */\nexport class StoreNotFoundError extends Error {\n readonly code = \"STORE_NOT_FOUND\" as const;\n constructor(message = \"Record not found\") {\n super(message);\n this.name = \"StoreNotFoundError\";\n }\n}\n\n/**\n * Thrown when a unique constraint is violated (e.g. duplicate `clientId`).\n *\n * Handlers use this to return the existing record instead of failing.\n */\nexport class StoreDuplicateError extends Error {\n readonly code = \"STORE_DUPLICATE\" as const;\n constructor(message = \"Duplicate record\") {\n super(message);\n this.name = \"StoreDuplicateError\";\n }\n}\n\n/** Type guard — works for `StoreNotFoundError` and ORM-specific equivalents (e.g. Prisma P2025). */\nexport function isStoreNotFound(error: unknown): boolean {\n if (error instanceof StoreNotFoundError) return true;\n // Backwards compat: Prisma's P2025\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code: string }).code === \"P2025\";\n}\n\n/** Type guard — works for `StoreDuplicateError` and ORM-specific equivalents (e.g. Prisma P2002). */\nexport function isStoreDuplicate(error: unknown): boolean {\n if (error instanceof StoreDuplicateError) return true;\n // Backwards compat: Prisma's P2002\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code: string }).code === \"P2002\";\n}\n\n// ---------------------------------------------------------------------------\n// Store helpers — shared conversion logic for adapters\n// ---------------------------------------------------------------------------\n\n/** Flatten a widget `AnnotationPayload` (nested anchor + rect) into a flat `AnnotationCreateInput`. */\nexport function flattenAnnotation(ann: AnnotationPayload): AnnotationCreateInput {\n return {\n cssSelector: ann.anchor.cssSelector,\n xpath: ann.anchor.xpath,\n textSnippet: ann.anchor.textSnippet,\n elementTag: ann.anchor.elementTag,\n elementId: ann.anchor.elementId,\n textPrefix: ann.anchor.textPrefix,\n textSuffix: ann.anchor.textSuffix,\n fingerprint: ann.anchor.fingerprint,\n neighborText: ann.anchor.neighborText,\n xPct: ann.rect.xPct,\n yPct: ann.rect.yPct,\n wPct: ann.rect.wPct,\n hPct: ann.rect.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Abstract Store — adapter pattern\n// ---------------------------------------------------------------------------\n\n/**\n * Abstract storage interface for Siteping.\n *\n * Any adapter (Prisma, Drizzle, raw SQL, localStorage, etc.) implements this\n * interface. The HTTP handler and widget `StoreClient` operate against\n * `SitepingStore`, decoupled from the storage backend.\n *\n * ## Error contract\n *\n * - **`updateFeedback` / `deleteFeedback`**: throw `StoreNotFoundError` when\n * the record does not exist.\n * - **`createFeedback`**: either return the existing record on duplicate\n * `clientId` (idempotent) or throw `StoreDuplicateError`. The handler\n * handles both patterns.\n * - Other methods should not throw on empty results — return empty arrays or `null`.\n */\nexport interface SitepingStore {\n /** Create a feedback with its annotations. Idempotent on `clientId` — return existing record on duplicate, or throw `StoreDuplicateError`. */\n createFeedback(data: FeedbackCreateInput): Promise<FeedbackRecord>;\n /** Paginated query with optional filters. Returns empty array (not error) when no results. */\n getFeedbacks(query: FeedbackQuery): Promise<{ feedbacks: FeedbackRecord[]; total: number }>;\n /** Lookup by client-generated UUID. Returns `null` (not error) when not found. */\n findByClientId(clientId: string): Promise<FeedbackRecord | null>;\n /** Update status/resolvedAt. Throws `StoreNotFoundError` if `id` does not exist. */\n updateFeedback(id: string, data: FeedbackUpdateInput): Promise<FeedbackRecord>;\n /** Delete a single record. Throws `StoreNotFoundError` if `id` does not exist. */\n deleteFeedback(id: string): Promise<void>;\n /** Bulk delete all feedbacks for a project. No-op (not error) if none exist. */\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/** Payload sent from the widget to the server when submitting feedback. */\nexport interface FeedbackPayload {\n projectName: string;\n type: FeedbackType;\n message: string;\n url: string;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n annotations: AnnotationPayload[];\n /** Client-generated UUID for deduplication */\n clientId: string;\n}\n\n// ---------------------------------------------------------------------------\n// Annotation — multi-selector anchoring (Hypothesis / W3C Web Annotation)\n// ---------------------------------------------------------------------------\n\n/** DOM anchoring data for re-attaching annotations to page elements. */\nexport interface AnchorData {\n /** CSS selector generated by @medv/finder — primary anchor */\n cssSelector: string;\n /** XPath — fallback 1 */\n xpath: string;\n /** First ~120 chars of element innerText — empty string if none */\n textSnippet: string;\n /** Tag name for validation (e.g. \"DIV\", \"SECTION\") */\n elementTag: string;\n /** Element id attribute if available — most stable */\n elementId?: string | undefined;\n /** ~32 chars of text before this element in document flow (disambiguation) */\n textPrefix: string;\n /** ~32 chars of text after this element in document flow (disambiguation) */\n textSuffix: string;\n /** Structural fingerprint: \"childCount:siblingIdx:attrHash\" */\n fingerprint: string;\n /** Text content of adjacent sibling elements (context) */\n neighborText: string;\n}\n\n/** Drawn rectangle coordinates as percentages relative to the anchor element. */\nexport interface RectData {\n /** X offset as fraction of anchor element width — must be in range [0, 1] */\n xPct: number;\n /** Y offset as fraction of anchor element height — must be in range [0, 1] */\n yPct: number;\n /** Width as fraction of anchor element width — must be in range [0, 1] */\n wPct: number;\n /** Height as fraction of anchor element height — must be in range [0, 1] */\n hPct: number;\n}\n\n/** Annotation data sent as part of a feedback submission. */\nexport interface AnnotationPayload {\n anchor: AnchorData;\n rect: RectData;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n}\n\n// ---------------------------------------------------------------------------\n// API responses\n// ---------------------------------------------------------------------------\n\n/** Feedback record as returned by the API (dates serialized as strings). */\nexport interface FeedbackResponse {\n id: string;\n projectName: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n url: string;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n resolvedAt: string | null;\n createdAt: string;\n updatedAt: string;\n annotations: AnnotationResponse[];\n}\n\n/** Annotation record as returned by the API. */\nexport interface AnnotationResponse {\n id: string;\n feedbackId: string;\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId: string | null;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n createdAt: string;\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n type FeedbackStatus,\n type FeedbackType,\n flattenAnnotation,\n type SitepingStore,\n} from \"@siteping/core\";\nimport type { WidgetClient } from \"./api-client.js\";\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const record = await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n });\n\n return toResponse(record);\n }\n\n async getFeedbacks(\n projectName: string,\n options?: { page?: number; limit?: number; type?: FeedbackType; status?: FeedbackStatus; search?: string },\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n search: options?.search,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, {\n status: resolved ? \"resolved\" : \"open\",\n resolvedAt: resolved ? new Date() : null,\n });\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = `\n /* ---- Keyframes ---- */\n\n @keyframes sp-fab-in {\n from {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n to {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes sp-fab-glow {\n 0%, 100% { box-shadow: 0 4px 20px var(--sp-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.08); }\n 50% { box-shadow: 0 4px 28px var(--sp-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.1); }\n }\n\n @keyframes sp-marker-in {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 60% {\n transform: scale(1.2);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n }\n }\n\n @keyframes sp-pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 var(--sp-accent-glow);\n }\n 70% {\n box-shadow: 0 0 0 8px transparent;\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n @keyframes sp-flash-bg {\n 0% { background-color: var(--sp-accent-light); }\n 100% { background-color: transparent; }\n }\n\n @keyframes sp-slide-up {\n from {\n transform: translateY(8px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n @keyframes sp-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes sp-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n /* ---- Animation classes ---- */\n\n .sp-anim-fab-in {\n animation: sp-fab-in 0.5s ${SPRING_LINEAR} both;\n }\n\n .sp-anim-marker-in {\n animation: sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;\n }\n\n .sp-anim-pulse {\n animation: sp-pulse-ring 0.7s ease-out;\n }\n\n .sp-anim-flash {\n animation: sp-flash-bg 0.5s ${EASE_OUT_QUART};\n }\n\n .sp-anim-slide-up {\n animation: sp-slide-up 0.3s ${EASE_OUT_EXPO} both;\n }\n\n .sp-anim-fade-in {\n animation: sp-fade-in 0.2s ease-out both;\n }\n\n /* ---- Transition utilities ---- */\n\n .sp-panel {\n transform: translateX(110%);\n transition: transform 0.4s ${EASE_OUT_EXPO};\n }\n\n .sp-panel.sp-panel--open {\n transform: translateX(0);\n }\n\n .sp-radial-item {\n opacity: 0;\n pointer-events: none;\n transform: translate(0, 0) scale(0.8);\n transition:\n transform 0.35s ${SPRING_OVERSHOOT},\n opacity 0.2s ease,\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n }\n\n .sp-radial-item.sp-radial-item--open {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Stagger delay via CSS custom property --sp-i */\n .sp-radial-item {\n transition-delay: calc(var(--sp-i, 0) * 50ms);\n }\n\n /* ---- Card stagger animation ---- */\n\n @keyframes sp-card-in {\n from {\n transform: translateY(12px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n .sp-card {\n animation: sp-card-in 0.35s ${EASE_OUT_EXPO} both;\n animation-delay: calc(var(--sp-card-i, 0) * 40ms);\n }\n\n /* ---- Loading spinner ---- */\n\n @keyframes sp-spin {\n to { transform: rotate(360deg); }\n }\n\n .sp-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--sp-border);\n border-top-color: var(--sp-accent);\n border-radius: 50%;\n animation: sp-spin 0.6s linear infinite;\n }\n\n /* ---- Badge bounce ---- */\n\n @keyframes sp-badge-in {\n 0% { transform: scale(0); }\n 60% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n }\n\n .sp-fab-badge {\n animation: sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n\n`;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return `\n :host {\n all: initial;\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n font-family: var(--sp-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--sp-text);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n ${cssVariables(colors)}\n\n /* Identity modal — theme-aware backdrop + panel */\n --sp-identity-bg: ${colors.glassBgHeavy};\n --sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ============================\n Focus visible (accessibility)\n ============================ */\n\n :focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: 2px;\n }\n\n /* ============================\n FAB (Floating Action Button)\n ============================ */\n\n .sp-fab {\n position: fixed;\n width: 52px;\n height: 52px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-accent-gradient);\n color: #fff;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow:\n 0 4px 20px var(--sp-accent-glow),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.3s ease;\n outline: none;\n }\n\n .sp-fab:focus-visible {\n outline: 2px solid #fff;\n outline-offset: 3px;\n }\n\n .sp-fab:hover {\n transform: translateY(-2px) scale(1.05);\n box-shadow:\n 0 8px 28px var(--sp-accent-glow),\n 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .sp-fab:active {\n transform: translateY(0) scale(0.95);\n transition-duration: 0.1s;\n }\n\n .sp-fab--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-fab--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-fab svg {\n width: 22px;\n height: 22px;\n fill: currentColor;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n /* ---- FAB Badge ---- */\n\n .sp-fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: var(--sp-radius-full);\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid #fff;\n pointer-events: none;\n font-family: var(--sp-font);\n line-height: 1;\n }\n\n /* ============================\n Radial Menu\n ============================ */\n\n .sp-radial {\n position: fixed;\n pointer-events: none;\n width: 52px;\n height: 52px;\n }\n\n .sp-radial--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-radial--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-radial-item {\n position: absolute;\n left: 4px;\n bottom: 4px;\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n color: var(--sp-text);\n border: 1px solid var(--sp-glass-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--sp-shadow-md);\n font-size: 12px;\n font-weight: 600;\n }\n\n .sp-radial-item:hover,\n .sp-radial-item:focus-visible {\n background: rgba(255, 255, 255, 0.95);\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n box-shadow:\n var(--sp-shadow-md),\n 0 0 0 3px var(--sp-accent-light);\n outline: none;\n }\n\n .sp-radial-item svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n stroke: currentColor;\n fill: none;\n }\n\n .sp-radial-label {\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text);\n pointer-events: none;\n opacity: 0;\n padding: 4px 12px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n transform: translateX(4px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n\n .sp-radial-item:hover .sp-radial-label,\n .sp-radial-item:focus-visible .sp-radial-label {\n opacity: 1;\n transform: translateX(0);\n }\n\n /* ============================\n Panel (Side drawer)\n ============================ */\n\n .sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border-left: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n @media (max-width: 480px) {\n .sp-panel {\n width: 100vw;\n border-left: none;\n }\n }\n\n .sp-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: relative;\n z-index: 2;\n }\n\n .sp-panel-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-panel-close {\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n }\n\n .sp-panel-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-panel-close svg {\n width: 16px;\n height: 16px;\n }\n\n /* ============================\n Filters & Search\n ============================ */\n\n .sp-filters {\n padding: 16px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .sp-search-wrap {\n position: relative;\n margin-bottom: 12px;\n }\n\n .sp-search {\n width: 100%;\n height: 40px;\n padding: 0 12px 0 38px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 13px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-search::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-search:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: #fff;\n }\n\n .sp-search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--sp-text-tertiary);\n width: 16px;\n height: 16px;\n transition: color 0.2s ease;\n }\n\n .sp-search:focus ~ .sp-search-icon,\n .sp-search-wrap:focus-within .sp-search-icon {\n color: var(--sp-accent);\n }\n\n /* ============================\n Filter bar (type dropdown + status segmented)\n ============================ */\n\n .sp-filter-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n }\n\n /* ============================\n Type filter dropdown\n ============================ */\n\n .sp-filter-dropdown {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .sp-filter-dropdown-btn {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: var(--sp-glass-bg-heavy);\n\n display: inline-flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px 0 10px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-filter-dropdown-btn:hover {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--sp-chip-color) 14%, transparent);\n }\n\n .sp-filter-dropdown-btn--filtered {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-btn__icon svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-filter-dropdown-btn__label {\n display: inline-flex;\n align-items: baseline;\n gap: 6px;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sp-filter-dropdown-btn__prefix {\n color: var(--sp-text-tertiary);\n font-weight: 500;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .sp-filter-dropdown-btn__value {\n color: var(--sp-chip-color);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sp-filter-dropdown-btn__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-text-tertiary);\n transition: transform 0.18s ease, color 0.18s ease;\n }\n\n .sp-filter-dropdown-btn__chevron svg {\n width: 12px;\n height: 12px;\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron {\n transform: rotate(180deg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-filter-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-filter-menu-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .sp-filter-dropdown-option {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: transparent;\n\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: background 0.12s ease, color 0.12s ease;\n }\n\n .sp-filter-dropdown-option__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n flex-shrink: 0;\n border-radius: 6px;\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option__label {\n flex: 1;\n min-width: 0;\n }\n\n .sp-filter-dropdown-option__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__check svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-filter-dropdown-option--active {\n color: var(--sp-chip-color);\n font-weight: 600;\n }\n\n .sp-filter-dropdown-option--active:hover {\n background: var(--sp-chip-bg);\n }\n\n /* ============================\n Status segmented control\n ============================ */\n\n .sp-segmented {\n display: inline-flex;\n align-items: stretch;\n padding: 2px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n flex-shrink: 0;\n }\n\n .sp-segmented__btn {\n --sp-chip-color: var(--sp-text-tertiary);\n --sp-chip-bg: transparent;\n\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--sp-radius-full);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-segmented__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n transition: color 0.18s ease, transform 0.18s ease;\n }\n\n .sp-segmented__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-segmented__btn:hover {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn:hover .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--active {\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n font-weight: 600;\n box-shadow:\n inset 0 0 0 1px color-mix(in srgb, var(--sp-chip-color) 35%, transparent),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n\n .sp-segmented__btn--active .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: sp-segmented-pulse 2.4s ease-in-out infinite;\n }\n\n @keyframes sp-segmented-pulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(0.85); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sp-filter-dropdown-btn,\n .sp-filter-dropdown-btn__chevron,\n .sp-filter-dropdown-option,\n .sp-segmented__btn,\n .sp-segmented__icon {\n transition: none;\n }\n .sp-filter-dropdown-menu {\n animation: none;\n }\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: none;\n }\n }\n\n /* ============================\n Feedback Cards\n ============================ */\n\n .sp-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n }\n\n .sp-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-list::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-list::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n .sp-card {\n display: flex;\n padding: 14px 16px;\n margin-bottom: 6px;\n cursor: pointer;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xs);\n transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .sp-card:hover {\n background: #fff;\n border-color: var(--sp-border);\n box-shadow: var(--sp-shadow-md);\n transform: translateY(-2px);\n }\n\n .sp-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 0.1s;\n }\n\n .sp-card-bar {\n width: 3px;\n border-radius: var(--sp-radius-full);\n margin-right: 14px;\n flex-shrink: 0;\n }\n\n .sp-card-body {\n flex: 1;\n min-width: 0;\n }\n\n .sp-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .sp-card-number {\n font-size: 12px;\n font-weight: 700;\n color: var(--sp-text-tertiary);\n font-variant-numeric: tabular-nums;\n }\n\n .sp-badge {\n padding: 2px 10px;\n border-radius: var(--sp-radius-full);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-card-date {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n margin-left: auto;\n }\n\n .sp-card-message {\n font-size: 13px;\n line-height: 1.5;\n color: var(--sp-text);\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .sp-card-message--expanded {\n -webkit-line-clamp: unset;\n }\n\n .sp-card-expand {\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-accent);\n cursor: pointer;\n background: none;\n border: none;\n padding: 4px 0;\n font-family: var(--sp-font);\n transition: opacity 0.15s ease;\n }\n\n .sp-card-expand:hover {\n opacity: 0.8;\n }\n\n .sp-card-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n }\n\n .sp-btn-resolve,\n .sp-btn-delete {\n padding: 8px 14px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-resolve svg,\n .sp-btn-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-btn-resolve:hover {\n border-color: #22c55e;\n color: #22c55e;\n background: rgba(34, 197, 94, 0.06);\n }\n\n .sp-btn-delete:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-resolve:disabled,\n .sp-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-spinner--sm {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Delete All (header) ---- */\n\n .sp-panel-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-btn-delete-all {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-delete-all svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-btn-delete-all:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-delete-all:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ---- Confirm Dialog ---- */\n\n .sp-confirm-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: ${Z_INDEX_MAX};\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n .sp-confirm-dialog {\n width: 340px;\n padding: 28px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n transform: translateY(8px) scale(0.97);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-confirm-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n margin-bottom: 8px;\n }\n\n .sp-confirm-message {\n font-size: 14px;\n color: var(--sp-text-secondary);\n line-height: 1.5;\n margin-bottom: 20px;\n }\n\n .sp-confirm-actions {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n }\n\n .sp-btn-danger {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: #ef4444;\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);\n }\n\n .sp-btn-danger:hover {\n background: #dc2626;\n box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);\n transform: translateY(-1px);\n }\n\n .sp-btn-danger:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-card--resolved {\n opacity: 0.5;\n }\n\n .sp-card--resolved .sp-card-message {\n text-decoration: line-through;\n text-decoration-color: var(--sp-text-tertiary);\n }\n\n /* ============================\n Loading State\n ============================ */\n\n .sp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n }\n\n /* ============================\n Identity Form\n ============================ */\n\n .sp-identity-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-input {\n width: 100%;\n height: 42px;\n padding: 0 14px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 14px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-input::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-input:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: #fff;\n }\n\n .sp-input-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n margin-bottom: 6px;\n display: block;\n }\n\n /* ============================\n Buttons\n ============================ */\n\n .sp-btn-primary {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-btn-primary:hover {\n box-shadow: 0 4px 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-btn-primary:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-btn-primary:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n .sp-btn-ghost {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .sp-btn-ghost:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Empty State\n ============================ */\n\n .sp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 56px 24px;\n color: var(--sp-text-tertiary);\n text-align: center;\n gap: 8px;\n animation: sp-fade-in 0.3s ease-out both;\n }\n\n .sp-empty-text {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* ============================\n Load More\n ============================ */\n\n .sp-load-more-wrap {\n display: flex;\n justify-content: center;\n padding: 12px 0 4px;\n }\n\n .sp-btn-load-more {\n width: 100%;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-fab,\n .sp-radial-item,\n .sp-filter-dropdown-btn,\n .sp-segmented,\n .sp-segmented__btn,\n .sp-card,\n .sp-panel-close,\n .sp-search,\n .sp-btn-resolve,\n .sp-btn-delete,\n .sp-btn-delete-all,\n .sp-btn-primary,\n .sp-btn-ghost,\n .sp-btn-danger,\n .sp-card-expand,\n .sp-input,\n .sp-confirm-dialog {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-segmented__btn--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-filter-dropdown-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-filter-dropdown-option--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-fab:focus-visible,\n .sp-radial-item:focus-visible,\n .sp-filter-dropdown-btn:focus-visible,\n .sp-segmented__btn:focus-visible,\n .sp-filter-dropdown-option:focus-visible,\n .sp-panel-close:focus-visible,\n .sp-btn-resolve:focus-visible,\n .sp-btn-delete:focus-visible,\n .sp-btn-delete-all:focus-visible,\n .sp-btn-primary:focus-visible,\n .sp-btn-ghost:focus-visible,\n .sp-btn-danger:focus-visible,\n .sp-card-expand:focus-visible,\n .sp-input:focus-visible,\n .sp-search:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-panel {\n border: 2px solid ButtonText !important;\n }\n\n .sp-fab-badge {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-card-bar {\n background: ButtonText !important;\n }\n }\n\n ${ANIMATION_CSS}\n ${STATS_CSS}\n ${SORT_CSS}\n ${BULK_CSS}\n ${EXPORT_CSS}\n ${SHORTCUTS_CSS}\n ${DETAIL_CSS}\n `;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: `\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n max-width: 280px;\n padding: 12px 14px;\n border-radius: 14px;\n background: ${this.colors.glassBgHeavy};\n backdrop-filter: blur(24px);\n -webkit-backdrop-filter: blur(24px);\n border: 1px solid ${this.colors.glassBorder};\n box-shadow: 0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family: \"Inter\", system-ui, -apple-system, sans-serif;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(6px) scale(0.97);\n transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n visibility: hidden;\n -webkit-font-smoothing: antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: `\n position: absolute;\n width: 12px;\n height: 12px;\n background: ${this.colors.glassBgHeavy};\n border: 1px solid ${this.colors.glassBorder};\n transform: rotate(45deg);\n pointer-events: none;\n `,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelHide();\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: `\n padding:3px 10px;border-radius:9999px;\n font-size:11px;font-weight:600;\n color:${typeColor};background:${typeBg};\n letter-spacing:0.02em;\n `,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-right:1px solid ${this.colors.glassBorder};\n border-bottom:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n bottom:-6px;\n left:${arrowLeft}px;\n `;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-left:1px solid ${this.colors.glassBorder};\n border-top:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n top:-6px;\n left:${arrowLeft}px;\n `;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import type { FeedbackPayload, SitepingConfig, SitepingInstance, SitepingPublicEvents } from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { MOBILE_BREAKPOINT, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { EventBus, type PublicWidgetEvents, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createT, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport { Panel } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n on: () => noop,\n off: noop,\n };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses)\n if (!config.forceShow) {\n try {\n // Check for Node/bundler production environment — avoid import.meta\n // which causes \"Critical dependency\" warnings in Next.js webpack builds\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n }\n\n // Guard: desktop only (< MOBILE_BREAKPOINT = hidden)\n if (window.innerWidth < MOBILE_BREAKPOINT) {\n const reason = \"mobile\";\n console.info(`[siteping] Widget not loaded: viewport width < ${MOBILE_BREAKPOINT}px (mobile not supported).`);\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n const locale = config.locale ?? \"en\";\n const t = createT(locale);\n\n log(\"Initializing widget\", { projectName: config.projectName, theme: config.theme ?? \"light\", locale });\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<PublicWidgetEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint)\n const client: WidgetClient = config.store\n ? new StoreClient(config.store, config.projectName)\n : new ApiClient(config.endpoint as string, config.projectName);\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Bridge internal events to public bus\n bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb));\n bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id));\n bus.on(\"open\", () => publicBus.emit(\"panel:open\"));\n bus.on(\"close\", () => publicBus.emit(\"panel:close\"));\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n let isTestEnv = false;\n try {\n // Dynamic key prevents bundlers (tsup/esbuild) from statically replacing\n // process.env.NODE_ENV at build time — the widget needs runtime detection\n // so E2E tests can set globalThis.process = { env: { NODE_ENV: 'test' } }\n const envKey = \"NODE_\" + \"ENV\";\n if (typeof process !== \"undefined\" && process.env?.[envKey] === \"test\") {\n isTestEnv = true;\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n const shadowMode = isTestEnv ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n (shadow as unknown as DocumentFragment).appendChild(style);\n }\n\n document.body.appendChild(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n const panel = new Panel(shadow, colors, bus, client, config.projectName, markers, t, locale);\n const annotator = new Annotator(colors, bus, t);\n\n // Handle annotation completion via event bus (not DOM events)\n // Concurrency guard: prevent duplicate submissions if user draws two annotations quickly\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) return;\n submitting = true;\n try {\n const { annotation, type, message } = data;\n\n // Ensure identity\n let identity = getIdentity();\n if (!identity) {\n identity = await promptIdentity(shadow, t);\n if (!identity) return; // User cancelled\n saveIdentity(identity);\n }\n\n // Sanitize URL — strip sensitive query params before sending\n const rawUrl = new URL(window.location.href);\n for (const key of [...rawUrl.searchParams.keys()]) {\n if (/token|key|secret|auth|session|password|code/i.test(key)) {\n rawUrl.searchParams.delete(key);\n }\n }\n const sanitizedUrl = rawUrl.toString();\n\n // crypto.randomUUID() throws in non-secure contexts (plain HTTP)\n const clientId = (() => {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n })();\n\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: sanitizedUrl,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n markers.addFeedback(response, markers.count + 1);\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n await panel.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load\n client\n .getFeedbacks(config.projectName, { limit: PAGE_SIZE })\n .then(({ feedbacks }) => {\n markers.render(feedbacks);\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint)\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n instance = {\n destroy: () => {\n log(\"Destroying widget\");\n unsubAnnotation();\n fab.destroy();\n panel.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n instance = null;\n },\n open: () => {\n panel.open();\n },\n close: () => {\n panel.close();\n },\n refresh: () => {\n panel.refresh();\n },\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => {\n // Safe cast: SitepingPublicEvents and PublicWidgetEvents have identical keys and value types\n type TargetKey = K & keyof PublicWidgetEvents;\n return publicBus.on(event as TargetKey, listener as unknown as (...args: PublicWidgetEvents[TargetKey]) => void);\n },\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => {\n // Safe cast: SitepingPublicEvents and PublicWidgetEvents have identical keys and value types\n type TargetKey = K & keyof PublicWidgetEvents;\n publicBus.off(event as TargetKey, listener as unknown as (...args: PublicWidgetEvents[TargetKey]) => void);\n },\n };\n\n return instance;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n const backdrop = document.createElement(\"div\");\n backdrop.style.cssText = `\n position:fixed;inset:0;\n background:var(--sp-identity-overlay);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n display:flex;align-items:center;justify-content:center;\n z-index:${Z_INDEX_MAX};\n opacity:0;transition:opacity 0.25s ease;\n `;\n\n const modal = document.createElement(\"div\");\n modal.style.cssText = `\n width:340px;padding:28px;border-radius:var(--sp-radius-xl);\n background:var(--sp-identity-bg);\n backdrop-filter:blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter:blur(var(--sp-blur-heavy));\n border:1px solid var(--sp-glass-border);\n box-shadow:0 16px 48px var(--sp-shadow), 0 8px 16px var(--sp-shadow);\n font-family:var(--sp-font, \"Inter\",system-ui,-apple-system,sans-serif);\n color:var(--sp-text);\n transform:translateY(12px) scale(0.97);\n transition:transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n -webkit-font-smoothing:antialiased;\n `;\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;justify-content:flex-end;margin-top:20px;\";\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n modal.style.transform = \"translateY(12px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n emailInput.style.borderColor = \"var(--sp-type-bug, #ef4444)\";\n return;\n }\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n modal.style.transform = \"translateY(0) scale(1)\";\n nameInput.focus();\n });\n });\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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AA;AAAA,0BAGFA,EAAO,YAAY;AAAA,+BACdA,EAAO,KAAO,UAAY,wBAA0B,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAw1BtF,UAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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":["index_exports","__export","initSiteping","config","rootDocument","start","finder","input","options","defaults","name","value","findRootDocument","path","bottomUpSearch","optimized","sort","optimize","selector","rootNode","limit","fallback","stack","current","i","elapsedTime","level","maybe","id","attr","classNames","tagName","any","nth","index","dispensableNth","node","nthChild","findUniquePath","paths","combinations","candidate","unique","query","penalty","acc","css","elementId","parent","child","list","notEmpty","a","b","scope","newPath","newPathKey","same","STABLE_ATTRS","djb2","str","hash","i","generateFingerprint","element","childCount","siblingIdx","parent","child","attrs","attr","val","attrHash","scoreFingerprint","candidate","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","adjacentText","element","direction","prop","sibling","attempts","text","neighborText","prev","next","generateXPath","element","safeId","segments","current","tag","parent","position","sibling","generateAnchor","element","cssSelector","finder","name","xpath","generateXPath","textSnippet","textPrefix","adjacentText","textSuffix","fingerprint","generateFingerprint","neighbor","neighborText","findAnchorElement","rect","root","centerX","centerY","elementAtCenter","current","bounds","rectToPercentages","anchorBounds","parseSvg","svgString","svg","attr","el","tag","attrs","element","key","value","setText","text","formatRelativeDate","isoString","locale","diff","seconds","rtf","minutes","hours","days","ICON_SITEPING","ICON_CHAT","ICON_ANNOTATE","ICON_EYE","ICON_EYE_OFF","ICON_CLOSE","ICON_SEARCH","ICON_CHECK","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","ICON_LAYERS","ICON_DOT_OPEN","ICON_CHEVRON_DOWN","ICON_UNDO","ICON_TRASH","DEFAULT_ACCENT","HEX6_RE","HEX3_RE","HEX8_RE","normalizeHex","raw","short","darkenHex","hex","amount","r","g","b","prefersDark","resolveTheme","theme","buildThemeColors","accent","dark","getTypeColor","type","colors","getTypeBgColor","cssVariables","Popup","colors","el","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","typeRow","option","btn","icon","parseSvg","labelSpan","setText","bgColor","getTypeBgColor","getTypeColor","hint","uaData","isMac","e","btnRow","cancelBtn","rectBounds","resolve","top","left","focusableEls","first","last","reduceMotion","type","container","buttons","isActive","color","enabled","Annotator","colors","bus","t","Popup","el","dot","style","instruction","setText","cancelBtn","target","bounds","rectBounds","result","annotation","generateAnchor","touch","clientX","clientY","source","evt","x","y","w","h","anchorElement","findAnchorElement","anchor","anchorBounds","rect","rectToPercentages","RETRY_QUEUE_KEY","resilientFetch","url","init","retries","attempt","controller","timeout","response","error","baseDelay","jitter","r","LOCK_NAME","withRetryLock","callback","queueForRetry","endpoint","payload","raw","RETRY_QUEUE_KEY","parsed","queue","flushRetryQueue","toRetry","e","failed","entry","remaining","ApiClient","projectName","text","options","params","id","resolved","EventBus","event","listener","set","args","fn","err","ITEM_GAP","Fab","shadowRoot","config","bus","t","position","isRight","ICON_CHAT","ICON_ANNOTATE","ICON_EYE","ICON_EYE_OFF","parseSvg","ICON_SITEPING","i","item","btn","e","label","host","handleEscape","items","activeEl","currentIndex","nextIndex","count","displayText","setText","ICON_CLOSE","y","svgStr","badge","id","de","en","es","fr","it","pt","ru","LOCALES","de","en","es","fr","it","pt","ru","createT","locale","lang","LOCALES","dict","key","getTypeLabel","type","t","STORAGE_KEY","getIdentity","raw","parsed","identity","saveIdentity","editDistance","a","b","t","aLen","bLen","prev","k","curr","j","i","prevDiag","tmp","similarity","maxLen","fuzzyIncludes","haystack","needle","minScore","nLen","score","best","capped","limit","window","MAX_SCAN_CANDIDATES","TEXT_MATCH_THRESHOLD","textMatches","el","anchor","text","fuzzyIncludes","resolveAnchor","smartScan","tag","candidates","bestElement","bestScore","limit","i","score","scoreCandidate","candidate","totalWeight","candidateText","scoreFingerprint","contextScore","contextParts","prevText","adjacentText","similarity","nextText","candidateNeighbor","neighborText","resolveAnnotation","rect","resolution","bounds","absoluteRect","toAnchorData","a","toRectData","MARKER_OFFSET","markerPosition","rect","clusterMarker","cluster","i","entry","elIdx","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","colors","tooltip","bus","t","el","visible","mutations","hasRelevantMutation","m","e","validKeys","markerEl","annotation","cacheKey","cachedEl","resolved","anchorRect","r","resolveAnnotation","pos","key","feedbacks","feedback","index","marker","badge","allItems","used","itemI","j","itemJ","b","first","baseTop","baseLeft","isSolo","count","totalWidth","startLeft","topMarker","setText","confidence","isResolved","number","typeColor","getTypeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","feedbackId","highlight","h","ICON_EXPORT","ICON_CSV","ICON_JSON","EXPORT_I18N_EN","EXPORT_I18N_FR","EXPORT_CSS","CSV_COLUMNS","escapeCsvField","value","feedbacksToCsv","feedbacks","header","rows","fb","col","raw","feedbacksToJson","downloadFile","content","filename","mimeType","blob","url","anchor","ExportButton","_colors","getFeedbacks","el","btn","parseSvg","label","setText","e","csvOption","jsonOption","labels","span","options","iconSvg","labelText","onClick","option","iconWrap","labelEl","format","projectName","date","safeName","ICON_CHECKBOX","ICON_CHECKBOX_CHECKED","BULK_I18N_EN","BULK_I18N_FR","BULK_CSS","BulkActions","_colors","callbacks","locale","el","setText","actions","deselectBtn","parseSvg","feedbackId","wrapper","e","feedbackIds","label","checkbox","labelEl","container","id","prevSelected","count","visible","resolveLabel","deleteLabel","isChecked","allSelected","escapedId","card","btn","snapshot","n","ids","restoreResolve","restoreDelete","ICON_ARROW_LEFT","ICON_MAP_PIN","ICON_LINK","ICON_USER","ICON_CALENDAR","ICON_MONITOR","ICON_CHECK","ICON_UNDO","ICON_TRASH","ICON_CODE","ICON_CROSSHAIR","DETAIL_I18N_EN","DETAIL_I18N_FR","DETAIL_CSS","parseBrowser","ua","m","formatFullDate","isoString","locale","extractPathname","url","truncate","str","max","DetailView","colors","callbacks","el","header","backBtn","parseSvg","feedback","number","title","setText","badge","getTypeBgColor","getTypeColor","sectionIndex","statusSection","messageSection","messageSectionTitle","messageBlock","metaSection","metaSectionTitle","annSection","annSectionTitle","annTitleText","index","section","container","isResolved","sectionTitle","statusRow","pill","dot","pillLabel","actions","span","deleteSpan","meta","value","pathname","name","email","resolvedDate","iconSvg","label","buildValue","row","content","labelEl","ann","wrapper","info","tagDisplay","gotoBtn","gotoLabel","btn","ICON_SORT","ICON_PAGE","ICON_CHEVRON","SORT_I18N_EN","SORT_I18N_FR","TYPE_ORDER","sortFeedbacks","feedbacks","mode","sorted","a","b","typeA","typeB","statusA","statusB","extractPathname","url","truncatePath","path","maxLength","ellipsis","keep","groupFeedbacksByPage","groups","fb","existing","createPageGroupHeader","pagePath","count","colors","header","el","chevronWrap","parseSvg","pageIcon","pathEl","displayPath","setText","countEl","toggle","isExpanded","content","e","PanelSortControls","onChange","locale","sortIcon","sortLabel","groupIcon","groupLabel","options","opt","item","labelMap","label","SORT_CSS","STATS_I18N_EN","STATS_I18N_FR","STATS_CSS","PanelStats","colors","locale","el","row","itemOpen","dotOpen","setText","labelOpen","itemResolved","dotResolved","labelResolved","itemBugs","dotBugs","labelBugs","progress","track","feedbacks","total","openCount","resolvedCount","bugCount","fb","visible","pct","progressText","ICON_KEYBOARD","SHORTCUTS_I18N_EN","SHORTCUTS_I18N_FR","getFocusedCardIndex","listContainer","cards","i","focusCardByIndex","index","card","clamped","target","SHORTCUT_DEFS","SHORTCUTS_CSS","ICON_CLOSE_SM","KeyboardShortcuts","_colors","callbacks","i18n","e","root","active","tag","handler","overlay","el","title","parseSvg","titleText","setText","closeBtn","grid","def","row","keysWrap","key","sep","kbd","desc","btn","Panel","shadowRoot","colors","bus","client","projectName","markers","t","locale","BULK_I18N_FR","BULK_I18N_EN","el","header","title","setText","parseSvg","ICON_CLOSE","ICON_TRASH","deleteAllLabel","ExportButton","EXPORT_I18N_FR","headerRight","PanelStats","filters","searchWrap","searchIcon","ICON_SEARCH","filterBar","PanelSortControls","BulkActions","ids","DetailView","fb","newResolved","ann","shortcutsI18n","SHORTCUTS_I18N_FR","SHORTCUTS_I18N_EN","KeyboardShortcuts","dir","idx","getFocusedCardIndex","focusCardByIndex","btn","e","target","actionEl","card","feedbackId","feedback","f","action","message","isExpanded","number","ke","open","focusable","first","last","active","loading","spinner","empty","text","retryBtn","signal","search","typeFilter","statusFilter","options","hasContent","feedbacks","total","error","controller","nextPage","loadMoreBtn","restoreBtn","emptyText","sorted","sortFeedbacks","feedbackIds","selectAllBar","groups","groupFeedbacksByPage","globalIndex","pagePath","groupFeedbacks","groupHeader","createPageGroupHeader","groupContent","index","remaining","loadMoreWrap","isResolved","typeColor","getTypeColor","getTypeLabel","bar","body","checkbox","num","badge","typeBg","getTypeBgColor","date","formatRelativeDate","expandBtn","footer","resolveBtn","ICON_UNDO","span","ICON_CHECK","deleteBtn","deleteBtnLabel","id","resolve","backdrop","titleId","messageId","dialog","titleEl","messageEl","btnRow","cancelBtn","confirmBtn","closed","close","result","onKeydown","snapshot","n","restore","ICON_LAYERS","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","o","iconWrap","labelWrap","prefix","value","chevron","ICON_CHEVRON_DOWN","option","item","isActive","labelEl","checkWrap","ICON_DOT_OPEN","current","values","nextIdx","next","buttons","escapedId","flattenAnnotation","ann","StoreClient","store","projectName","payload","record","flattenAnnotation","toResponse","options","feedbacks","total","id","resolved","toAnnotationResponse","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","buildStyles","colors","cssVariables","ANIMATION_CSS","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","Tooltip","colors","locale","el","feedback","anchorRect","reduceMotion","children","child","typeColor","getTypeColor","typeBg","getTypeBgColor","t","createT","typeLabel","getTypeLabel","header","badge","setText","date","formatRelativeDate","body","tooltipRect","gap","top","left","isAbove","arrowLeft","node","instance","skippedInstance","noop","launch","config","log","args","reason","locale","t","createT","colors","buildThemeColors","bus","EventBus","publicBus","client","StoreClient","ApiClient","fb","id","err","host","isTestEnv","shadowMode","shadow","sheet","buildStyles","style","liveRegion","tooltip","Tooltip","markers","MarkerManager","fab","Fab","panel","Panel","annotator","Annotator","submitting","unsubAnnotation","data","annotation","type","message","identity","getIdentity","promptIdentity","saveIdentity","rawUrl","key","sanitizedUrl","clientId","payload","response","error","feedbacks","flushRetryQueue","event","listener","shadowRoot","resolve","previouslyFocused","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","btnRow","closeModal","result","onKeydown","cancelBtn","submitBtn","name","email","focusableSelectors","e","ke","focusableEls","first","last","active","initSiteping","config","launch"]}
1
+ {"version":3,"sources":["../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/tslib/tslib.es6.js","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/layout/bounds.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/src/Util.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/css-line-break/node_modules/src/Util.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/css-line-break/node_modules/src/Trie.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/css-line-break/node_modules/utrie/node_modules/src/index.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/src/linebreak-trie.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/src/LineBreak.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/syntax/tokenizer.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/syntax/parser.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/length.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/length-percentage.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/angle.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-clip.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/linear-gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/-prefix-linear-gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/-webkit-gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/radial-gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/-prefix-radial-gradient.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/image.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-image.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-origin.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-position.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-repeat.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/background-size.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/border-color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/border-radius.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/border-style.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/border-width.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/direction.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/display.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/float.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/letter-spacing.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/line-break.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/line-height.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/list-style-image.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/list-style-position.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/list-style-type.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/margin.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/overflow.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/overflow-wrap.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/padding.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/text-align.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/position.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/text-shadow.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/text-transform.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/transform.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/transform-origin.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/visibility.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/word-break.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/z-index.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/time.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/opacity.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/text-decoration-color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/text-decoration-line.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/font-family.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/font-size.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/font-weight.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/font-variant.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/font-style.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/bitwise.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/content.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/counter-increment.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/counter-reset.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/duration.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/quotes.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/box-shadow.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/paint-order.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/webkit-text-stroke-color.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/property-descriptors/webkit-text-stroke-width.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/index.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/debugger.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/src/grapheme-break-trie.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/text-segmentation/node_modules/src/Util.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/text-segmentation/node_modules/src/Trie.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/text-segmentation/node_modules/utrie/node_modules/src/index.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/html2canvas/node_modules/src/GraphemeBreak.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/features.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/layout/text.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/text-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/replaced-elements/image-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/replaced-elements/canvas-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/replaced-elements/svg-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/elements/li-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/elements/ol-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/replaced-elements/input-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/elements/select-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/elements/textarea-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/replaced-elements/iframe-element-container.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/node-parser.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/css/types/functions/counter.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/dom/document-cloner.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/cache-storage.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/vector.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/bezier-curve.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/bound-curves.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/effects.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/path.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/stacking-context.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/border.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/box-sizing.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/background.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/util.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/font-metrics.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/renderer.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/canvas/canvas-renderer.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/render/canvas/foreignobject-renderer.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/logger.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/core/context.ts","../../../node_modules/.bun/html2canvas@1.4.1/node_modules/src/index.ts","../src/index.ts","../../../node_modules/.bun/@medv+finder@3.2.0/node_modules/@medv/finder/finder.js","../src/dom/fingerprint.ts","../src/dom/text-context.ts","../src/dom/xpath.ts","../src/dom/anchor.ts","../src/dom-utils.ts","../src/icons.ts","../src/styles/theme.ts","../src/popup.ts","../src/screenshot.ts","../src/annotator.ts","../src/api-client.ts","../src/events.ts","../src/fab.ts","../src/i18n/de.ts","../src/i18n/en.ts","../src/i18n/es.ts","../src/i18n/fr.ts","../src/i18n/it.ts","../src/i18n/pt.ts","../src/i18n/ru.ts","../src/i18n/index.ts","../src/identity.ts","../src/dom/fuzzy.ts","../src/dom/resolver.ts","../src/markers.ts","../src/export-utils.ts","../src/panel-bulk.ts","../src/panel-detail.ts","../src/panel-sort.ts","../src/panel-stats.ts","../src/shortcuts.ts","../src/panel.ts","../../core/src/types.ts","../src/store-client.ts","../src/styles/animations.ts","../src/styles/base.ts","../src/tooltip.ts","../src/launcher.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || from);\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n","import {Context} from '../../core/context';\n\nexport class Bounds {\n constructor(readonly left: number, readonly top: number, readonly width: number, readonly height: number) {}\n\n add(x: number, y: number, w: number, h: number): Bounds {\n return new Bounds(this.left + x, this.top + y, this.width + w, this.height + h);\n }\n\n static fromClientRect(context: Context, clientRect: ClientRect): Bounds {\n return new Bounds(\n clientRect.left + context.windowBounds.left,\n clientRect.top + context.windowBounds.top,\n clientRect.width,\n clientRect.height\n );\n }\n\n static fromDOMRectList(context: Context, domRectList: DOMRectList): Bounds {\n const domRect = Array.from(domRectList).find((rect) => rect.width !== 0);\n return domRect\n ? new Bounds(\n domRect.left + context.windowBounds.left,\n domRect.top + context.windowBounds.top,\n domRect.width,\n domRect.height\n )\n : Bounds.EMPTY;\n }\n\n static EMPTY = new Bounds(0, 0, 0, 0);\n}\n\nexport const parseBounds = (context: Context, node: Element): Bounds => {\n return Bounds.fromClientRect(context, node.getBoundingClientRect());\n};\n\nexport const parseDocumentSize = (document: Document): Bounds => {\n const body = document.body;\n const documentElement = document.documentElement;\n\n if (!body || !documentElement) {\n throw new Error(`Unable to get document size`);\n }\n const width = Math.max(\n Math.max(body.scrollWidth, documentElement.scrollWidth),\n Math.max(body.offsetWidth, documentElement.offsetWidth),\n Math.max(body.clientWidth, documentElement.clientWidth)\n );\n\n const height = Math.max(\n Math.max(body.scrollHeight, documentElement.scrollHeight),\n Math.max(body.offsetHeight, documentElement.offsetHeight),\n Math.max(body.clientHeight, documentElement.clientHeight)\n );\n\n return new Bounds(0, 0, width, height);\n};\n","export const toCodePoints = (str: string): number[] => {\n const codePoints = [];\n let i = 0;\n const length = str.length;\n while (i < length) {\n const value = str.charCodeAt(i++);\n if (value >= 0xd800 && value <= 0xdbff && i < length) {\n const extra = str.charCodeAt(i++);\n if ((extra & 0xfc00) === 0xdc00) {\n codePoints.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);\n } else {\n codePoints.push(value);\n i--;\n }\n } else {\n codePoints.push(value);\n }\n }\n return codePoints;\n};\n\nexport const fromCodePoint = (...codePoints: number[]): string => {\n if (String.fromCodePoint) {\n return String.fromCodePoint(...codePoints);\n }\n\n const length = codePoints.length;\n if (!length) {\n return '';\n }\n\n const codeUnits = [];\n\n let index = -1;\n let result = '';\n while (++index < length) {\n let codePoint = codePoints[index];\n if (codePoint <= 0xffff) {\n codeUnits.push(codePoint);\n } else {\n codePoint -= 0x10000;\n codeUnits.push((codePoint >> 10) + 0xd800, (codePoint % 0x400) + 0xdc00);\n }\n if (index + 1 === length || codeUnits.length > 0x4000) {\n result += String.fromCharCode(...codeUnits);\n codeUnits.length = 0;\n }\n }\n return result;\n};\n\nconst chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\n\nexport const decode = (base64: string): ArrayBuffer | number[] => {\n let bufferLength = base64.length * 0.75,\n len = base64.length,\n i,\n p = 0,\n encoded1,\n encoded2,\n encoded3,\n encoded4;\n\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n const buffer =\n typeof ArrayBuffer !== 'undefined' &&\n typeof Uint8Array !== 'undefined' &&\n typeof Uint8Array.prototype.slice !== 'undefined'\n ? new ArrayBuffer(bufferLength)\n : new Array(bufferLength);\n const bytes = Array.isArray(buffer) ? buffer : new Uint8Array(buffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n\n return buffer;\n};\n\nexport const polyUint16Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 2) {\n bytes.push((buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n\nexport const polyUint32Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 4) {\n bytes.push((buffer[i + 3] << 24) | (buffer[i + 2] << 16) | (buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\n\nexport const decode = (base64: string): ArrayBuffer | number[] => {\n let bufferLength = base64.length * 0.75,\n len = base64.length,\n i,\n p = 0,\n encoded1,\n encoded2,\n encoded3,\n encoded4;\n\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n const buffer =\n typeof ArrayBuffer !== 'undefined' &&\n typeof Uint8Array !== 'undefined' &&\n typeof Uint8Array.prototype.slice !== 'undefined'\n ? new ArrayBuffer(bufferLength)\n : new Array(bufferLength);\n const bytes = Array.isArray(buffer) ? buffer : new Uint8Array(buffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n\n return buffer;\n};\n\nexport const polyUint16Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 2) {\n bytes.push((buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n\nexport const polyUint32Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 4) {\n bytes.push((buffer[i + 3] << 24) | (buffer[i + 2] << 16) | (buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n","import {decode, polyUint16Array, polyUint32Array} from './Util';\n\nexport type int = number;\n\n/** Shift size for getting the index-2 table offset. */\nexport const UTRIE2_SHIFT_2 = 5;\n\n/** Shift size for getting the index-1 table offset. */\nexport const UTRIE2_SHIFT_1 = 6 + 5;\n\n/**\n * Shift size for shifting left the index array values.\n * Increases possible data size with 16-bit index values at the cost\n * of compactability.\n * This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY.\n */\nexport const UTRIE2_INDEX_SHIFT = 2;\n\n/**\n * Difference between the two shift sizes,\n * for getting an index-1 offset from an index-2 offset. 6=11-5\n */\nexport const UTRIE2_SHIFT_1_2 = UTRIE2_SHIFT_1 - UTRIE2_SHIFT_2;\n\n/**\n * The part of the index-2 table for U+D800..U+DBFF stores values for\n * lead surrogate code _units_ not code _points_.\n * Values for lead surrogate code _points_ are indexed with this portion of the table.\n * Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.)\n */\nexport const UTRIE2_LSCP_INDEX_2_OFFSET = 0x10000 >> UTRIE2_SHIFT_2;\n\n/** Number of entries in a data block. 32=0x20 */\nexport const UTRIE2_DATA_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_2;\n/** Mask for getting the lower bits for the in-data-block offset. */\nexport const UTRIE2_DATA_MASK = UTRIE2_DATA_BLOCK_LENGTH - 1;\n\nexport const UTRIE2_LSCP_INDEX_2_LENGTH = 0x400 >> UTRIE2_SHIFT_2;\n/** Count the lengths of both BMP pieces. 2080=0x820 */\nexport const UTRIE2_INDEX_2_BMP_LENGTH = UTRIE2_LSCP_INDEX_2_OFFSET + UTRIE2_LSCP_INDEX_2_LENGTH;\n/**\n * The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n * Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2.\n */\nexport const UTRIE2_UTF8_2B_INDEX_2_OFFSET = UTRIE2_INDEX_2_BMP_LENGTH;\nexport const UTRIE2_UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; /* U+0800 is the first code point after 2-byte UTF-8 */\n/**\n * The index-1 table, only used for supplementary code points, at offset 2112=0x840.\n * Variable length, for code points up to highStart, where the last single-value range starts.\n * Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1.\n * (For 0x100000 supplementary code points U+10000..U+10ffff.)\n *\n * The part of the index-2 table for supplementary code points starts\n * after this index-1 table.\n *\n * Both the index-1 table and the following part of the index-2 table\n * are omitted completely if there is only BMP data.\n */\nexport const UTRIE2_INDEX_1_OFFSET = UTRIE2_UTF8_2B_INDEX_2_OFFSET + UTRIE2_UTF8_2B_INDEX_2_LENGTH;\n\n/**\n * Number of index-1 entries for the BMP. 32=0x20\n * This part of the index-1 table is omitted from the serialized form.\n */\nexport const UTRIE2_OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> UTRIE2_SHIFT_1;\n\n/** Number of entries in an index-2 block. 64=0x40 */\nexport const UTRIE2_INDEX_2_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_1_2;\n/** Mask for getting the lower bits for the in-index-2-block offset. */\nexport const UTRIE2_INDEX_2_MASK = UTRIE2_INDEX_2_BLOCK_LENGTH - 1;\n\nconst slice16 = (view: number[] | Uint16Array, start: number, end?: number) => {\n if (view.slice) {\n return view.slice(start, end);\n }\n\n return new Uint16Array(Array.prototype.slice.call(view, start, end));\n};\n\nconst slice32 = (view: number[] | Uint32Array, start: number, end?: number) => {\n if (view.slice) {\n return view.slice(start, end);\n }\n\n return new Uint32Array(Array.prototype.slice.call(view, start, end));\n};\n\nexport const createTrieFromBase64 = (base64: string, _byteLength: number): Trie => {\n const buffer = decode(base64);\n const view32 = Array.isArray(buffer) ? polyUint32Array(buffer) : new Uint32Array(buffer);\n const view16 = Array.isArray(buffer) ? polyUint16Array(buffer) : new Uint16Array(buffer);\n const headerLength = 24;\n\n const index = slice16(view16, headerLength / 2, view32[4] / 2);\n const data =\n view32[5] === 2\n ? slice16(view16, (headerLength + view32[4]) / 2)\n : slice32(view32, Math.ceil((headerLength + view32[4]) / 4));\n\n return new Trie(view32[0], view32[1], view32[2], view32[3], index, data);\n};\n\nexport class Trie {\n initialValue: int;\n errorValue: int;\n highStart: int;\n highValueIndex: int;\n index: Uint16Array | number[];\n data: Uint32Array | Uint16Array | number[];\n\n constructor(\n initialValue: int,\n errorValue: int,\n highStart: int,\n highValueIndex: int,\n index: Uint16Array | number[],\n data: Uint32Array | Uint16Array | number[]\n ) {\n this.initialValue = initialValue;\n this.errorValue = errorValue;\n this.highStart = highStart;\n this.highValueIndex = highValueIndex;\n this.index = index;\n this.data = data;\n }\n\n /**\n * Get the value for a code point as stored in the Trie.\n *\n * @param codePoint the code point\n * @return the value\n */\n get(codePoint: number): number {\n let ix;\n if (codePoint >= 0) {\n if (codePoint < 0x0d800 || (codePoint > 0x0dbff && codePoint <= 0x0ffff)) {\n // Ordinary BMP code point, excluding leading surrogates.\n // BMP uses a single level lookup. BMP index starts at offset 0 in the Trie2 index.\n // 16 bit data is stored in the index array itself.\n ix = this.index[codePoint >> UTRIE2_SHIFT_2];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n\n if (codePoint <= 0xffff) {\n // Lead Surrogate Code Point. A Separate index section is stored for\n // lead surrogate code units and code points.\n // The main index has the code unit data.\n // For this function, we need the code point data.\n // Note: this expression could be refactored for slightly improved efficiency, but\n // surrogate code points will be so rare in practice that it's not worth it.\n ix = this.index[UTRIE2_LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> UTRIE2_SHIFT_2)];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n\n if (codePoint < this.highStart) {\n // Supplemental code point, use two-level lookup.\n ix = UTRIE2_INDEX_1_OFFSET - UTRIE2_OMITTED_BMP_INDEX_1_LENGTH + (codePoint >> UTRIE2_SHIFT_1);\n ix = this.index[ix];\n ix += (codePoint >> UTRIE2_SHIFT_2) & UTRIE2_INDEX_2_MASK;\n ix = this.index[ix];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n if (codePoint <= 0x10ffff) {\n return this.data[this.highValueIndex];\n }\n }\n\n // Fall through. The code point is outside of the legal range of 0..0x10ffff.\n return this.errorValue;\n }\n}\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\n\nexport const encode = (arraybuffer: ArrayBuffer): string => {\n let bytes = new Uint8Array(arraybuffer),\n i,\n len = bytes.length,\n base64 = '';\n\n for (i = 0; i < len; i += 3) {\n base64 += chars[bytes[i] >> 2];\n base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n base64 += chars[bytes[i + 2] & 63];\n }\n\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + '=';\n } else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + '==';\n }\n\n return base64;\n};\n\nexport const decode = (base64: string): ArrayBuffer => {\n let bufferLength = base64.length * 0.75,\n len = base64.length,\n i,\n p = 0,\n encoded1,\n encoded2,\n encoded3,\n encoded4;\n\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n const arraybuffer = new ArrayBuffer(bufferLength),\n bytes = new Uint8Array(arraybuffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n\n return arraybuffer;\n};\n","export const base64 =\n 'KwAAAAAAAAAACA4AUD0AADAgAAACAAAAAAAIABAAGABAAEgAUABYAGAAaABgAGgAYgBqAF8AZwBgAGgAcQB5AHUAfQCFAI0AlQCdAKIAqgCyALoAYABoAGAAaABgAGgAwgDKAGAAaADGAM4A0wDbAOEA6QDxAPkAAQEJAQ8BFwF1AH0AHAEkASwBNAE6AUIBQQFJAVEBWQFhAWgBcAF4ATAAgAGGAY4BlQGXAZ8BpwGvAbUBvQHFAc0B0wHbAeMB6wHxAfkBAQIJAvEBEQIZAiECKQIxAjgCQAJGAk4CVgJeAmQCbAJ0AnwCgQKJApECmQKgAqgCsAK4ArwCxAIwAMwC0wLbAjAA4wLrAvMC+AIAAwcDDwMwABcDHQMlAy0DNQN1AD0DQQNJA0kDSQNRA1EDVwNZA1kDdQB1AGEDdQBpA20DdQN1AHsDdQCBA4kDkQN1AHUAmQOhA3UAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AKYDrgN1AHUAtgO+A8YDzgPWAxcD3gPjA+sD8wN1AHUA+wMDBAkEdQANBBUEHQQlBCoEFwMyBDgEYABABBcDSARQBFgEYARoBDAAcAQzAXgEgASIBJAEdQCXBHUAnwSnBK4EtgS6BMIEyAR1AHUAdQB1AHUAdQCVANAEYABgAGAAYABgAGAAYABgANgEYADcBOQEYADsBPQE/AQEBQwFFAUcBSQFLAU0BWQEPAVEBUsFUwVbBWAAYgVgAGoFcgV6BYIFigWRBWAAmQWfBaYFYABgAGAAYABgAKoFYACxBbAFuQW6BcEFwQXHBcEFwQXPBdMF2wXjBeoF8gX6BQIGCgYSBhoGIgYqBjIGOgZgAD4GRgZMBmAAUwZaBmAAYABgAGAAYABgAGAAYABgAGAAYABgAGIGYABpBnAGYABgAGAAYABgAGAAYABgAGAAYAB4Bn8GhQZgAGAAYAB1AHcDFQSLBmAAYABgAJMGdQA9A3UAmwajBqsGqwaVALMGuwbDBjAAywbSBtIG1QbSBtIG0gbSBtIG0gbdBuMG6wbzBvsGAwcLBxMHAwcbByMHJwcsBywHMQcsB9IGOAdAB0gHTgfSBkgHVgfSBtIG0gbSBtIG0gbSBtIG0gbSBiwHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAdgAGAALAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAdbB2MHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsB2kH0gZwB64EdQB1AHUAdQB1AHUAdQB1AHUHfQdgAIUHjQd1AHUAlQedB2AAYAClB6sHYACzB7YHvgfGB3UAzgfWBzMB3gfmB1EB7gf1B/0HlQENAQUIDQh1ABUIHQglCBcDLQg1CD0IRQhNCEEDUwh1AHUAdQBbCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIaQhjCGQIZQhmCGcIaAhpCGMIZAhlCGYIZwhoCGkIYwhkCGUIZghnCGgIcAh3CHoIMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwAIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIgggwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAALAcsBywHLAcsBywHLAcsBywHLAcsB4oILAcsB44I0gaWCJ4Ipgh1AHUAqgiyCHUAdQB1AHUAdQB1AHUAdQB1AHUAtwh8AXUAvwh1AMUIyQjRCNkI4AjoCHUAdQB1AO4I9gj+CAYJDgkTCS0HGwkjCYIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiCCIIIggiAAIAAAAFAAYABgAGIAXwBgAHEAdQBFAJUAogCyAKAAYABgAEIA4ABGANMA4QDxAMEBDwE1AFwBLAE6AQEBUQF4QkhCmEKoQrhCgAHIQsAB0MLAAcABwAHAAeDC6ABoAHDCwMMAAcABwAHAAdDDGMMAAcAB6MM4wwjDWMNow3jDaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAGgAaABoAEjDqABWw6bDqABpg6gAaABoAHcDvwOPA+gAaABfA/8DvwO/A78DvwO/A78DvwO/A78DvwO/A78DvwO/A78DvwO/A78DvwO/A78DvwO/A78DvwO/A78DpcPAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcAB9cPKwkyCToJMAB1AHUAdQBCCUoJTQl1AFUJXAljCWcJawkwADAAMAAwAHMJdQB2CX4JdQCECYoJjgmWCXUAngkwAGAAYABxAHUApgn3A64JtAl1ALkJdQDACTAAMAAwADAAdQB1AHUAdQB1AHUAdQB1AHUAowYNBMUIMAAwADAAMADICcsJ0wnZCRUE4QkwAOkJ8An4CTAAMAB1AAAKvwh1AAgKDwoXCh8KdQAwACcKLgp1ADYKqAmICT4KRgowADAAdQB1AE4KMAB1AFYKdQBeCnUAZQowADAAMAAwADAAMAAwADAAMAAVBHUAbQowADAAdQC5CXUKMAAwAHwBxAijBogEMgF9CoQKiASMCpQKmgqIBKIKqgquCogEDQG2Cr4KxgrLCjAAMADTCtsKCgHjCusK8Qr5CgELMAAwADAAMAB1AIsECQsRC3UANAEZCzAAMAAwADAAMAB1ACELKQswAHUANAExCzkLdQBBC0kLMABRC1kLMAAwADAAMAAwADAAdQBhCzAAMAAwAGAAYABpC3ELdwt/CzAAMACHC4sLkwubC58Lpwt1AK4Ltgt1APsDMAAwADAAMAAwADAAMAAwAL4LwwvLC9IL1wvdCzAAMADlC+kL8Qv5C/8LSQswADAAMAAwADAAMAAwADAAMAAHDDAAMAAwADAAMAAODBYMHgx1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1ACYMMAAwADAAdQB1AHUALgx1AHUAdQB1AHUAdQA2DDAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwAHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AD4MdQBGDHUAdQB1AHUAdQB1AEkMdQB1AHUAdQB1AFAMMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwAHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQBYDHUAdQB1AF8MMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUA+wMVBGcMMAAwAHwBbwx1AHcMfwyHDI8MMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAYABgAJcMMAAwADAAdQB1AJ8MlQClDDAAMACtDCwHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsB7UMLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHdQB1AHUAdQB1AHUAdQB1AHUAdQB1AHUAdQB1AA0EMAC9DDAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAsBywHLAcsBywHLAcsBywHLQcwAMEMyAwsBywHLAcsBywHLAcsBywHLAcsBywHzAwwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwAHUAdQB1ANQM2QzhDDAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMABgAGAAYABgAGAAYABgAOkMYADxDGAA+AwADQYNYABhCWAAYAAODTAAMAAwADAAFg1gAGAAHg37AzAAMAAwADAAYABgACYNYAAsDTQNPA1gAEMNPg1LDWAAYABgAGAAYABgAGAAYABgAGAAUg1aDYsGVglhDV0NcQBnDW0NdQ15DWAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAlQCBDZUAiA2PDZcNMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAnw2nDTAAMAAwADAAMAAwAHUArw23DTAAMAAwADAAMAAwADAAMAAwADAAMAB1AL8NMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAB1AHUAdQB1AHUAdQDHDTAAYABgAM8NMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAA1w11ANwNMAAwAD0B5A0wADAAMAAwADAAMADsDfQN/A0EDgwOFA4wABsOMAAwADAAMAAwADAAMAAwANIG0gbSBtIG0gbSBtIG0gYjDigOwQUuDsEFMw7SBjoO0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIGQg5KDlIOVg7SBtIGXg5lDm0OdQ7SBtIGfQ6EDooOjQ6UDtIGmg6hDtIG0gaoDqwO0ga0DrwO0gZgAGAAYADEDmAAYAAkBtIGzA5gANIOYADaDokO0gbSBt8O5w7SBu8O0gb1DvwO0gZgAGAAxA7SBtIG0gbSBtIGYABgAGAAYAAED2AAsAUMD9IG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIGFA8sBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAccD9IGLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHJA8sBywHLAcsBywHLAccDywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywPLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAc0D9IG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIGLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAccD9IG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIGFA8sBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHLAcsBywHPA/SBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gbSBtIG0gYUD0QPlQCVAJUAMAAwADAAMACVAJUAlQCVAJUAlQCVAEwPMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAA//8EAAQABAAEAAQABAAEAAQABAANAAMAAQABAAIABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQACgATABcAHgAbABoAHgAXABYAEgAeABsAGAAPABgAHABLAEsASwBLAEsASwBLAEsASwBLABgAGAAeAB4AHgATAB4AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQABYAGwASAB4AHgAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAWAA0AEQAeAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAAQABAAEAAQABAAFAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAJABYAGgAbABsAGwAeAB0AHQAeAE8AFwAeAA0AHgAeABoAGwBPAE8ADgBQAB0AHQAdAE8ATwAXAE8ATwBPABYAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAFAAUABQAFAAUABQAFAAUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAFAAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAeAB4AHgAeAFAATwBAAE8ATwBPAEAATwBQAFAATwBQAB4AHgAeAB4AHgAeAB0AHQAdAB0AHgAdAB4ADgBQAFAAUABQAFAAHgAeAB4AHgAeAB4AHgBQAB4AUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4ABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAJAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAkACQAJAAkACQAJAAkABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAeAB4AHgAeAFAAHgAeAB4AKwArAFAAUABQAFAAGABQACsAKwArACsAHgAeAFAAHgBQAFAAUAArAFAAKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4ABAAEAAQABAAEAAQABAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAUAAeAB4AHgAeAB4AHgBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAYAA0AKwArAB4AHgAbACsABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQADQAEAB4ABAAEAB4ABAAEABMABAArACsAKwArACsAKwArACsAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAKwArACsAKwBWAFYAVgBWAB4AHgArACsAKwArACsAKwArACsAKwArACsAHgAeAB4AHgAeAB4AHgAeAB4AGgAaABoAGAAYAB4AHgAEAAQABAAEAAQABAAEAAQABAAEAAQAEwAEACsAEwATAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABABLAEsASwBLAEsASwBLAEsASwBLABoAGQAZAB4AUABQAAQAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQABMAUAAEAAQABAAEAAQABAAEAB4AHgAEAAQABAAEAAQABABQAFAABAAEAB4ABAAEAAQABABQAFAASwBLAEsASwBLAEsASwBLAEsASwBQAFAAUAAeAB4AUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwAeAFAABABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAFAAKwArACsAKwArACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQAUABQAB4AHgAYABMAUAArACsABAAbABsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAFAABAAEAAQABAAEAFAABAAEAAQAUAAEAAQABAAEAAQAKwArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAArACsAHgArAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwArACsAKwArACsAKwArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAB4ABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAUAAEAAQABAAEAAQABAAEAFAAUABQAFAAUABQAFAAUABQAFAABAAEAA0ADQBLAEsASwBLAEsASwBLAEsASwBLAB4AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAArAFAAUABQAFAAUABQAFAAUAArACsAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUAArACsAKwBQAFAAUABQACsAKwAEAFAABAAEAAQABAAEAAQABAArACsABAAEACsAKwAEAAQABABQACsAKwArACsAKwArACsAKwAEACsAKwArACsAUABQACsAUABQAFAABAAEACsAKwBLAEsASwBLAEsASwBLAEsASwBLAFAAUAAaABoAUABQAFAAUABQAEwAHgAbAFAAHgAEACsAKwAEAAQABAArAFAAUABQAFAAUABQACsAKwArACsAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUABQACsAUABQACsAUABQACsAKwAEACsABAAEAAQABAAEACsAKwArACsABAAEACsAKwAEAAQABAArACsAKwAEACsAKwArACsAKwArACsAUABQAFAAUAArAFAAKwArACsAKwArACsAKwBLAEsASwBLAEsASwBLAEsASwBLAAQABABQAFAAUAAEAB4AKwArACsAKwArACsAKwArACsAKwAEAAQABAArAFAAUABQAFAAUABQAFAAUABQACsAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUABQACsAUABQAFAAUABQACsAKwAEAFAABAAEAAQABAAEAAQABAAEACsABAAEAAQAKwAEAAQABAArACsAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAABAAEACsAKwBLAEsASwBLAEsASwBLAEsASwBLAB4AGwArACsAKwArACsAKwArAFAABAAEAAQABAAEAAQAKwAEAAQABAArAFAAUABQAFAAUABQAFAAUAArACsAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAArACsABAAEACsAKwAEAAQABAArACsAKwArACsAKwArAAQABAAEACsAKwArACsAUABQACsAUABQAFAABAAEACsAKwBLAEsASwBLAEsASwBLAEsASwBLAB4AUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArAAQAUAArAFAAUABQAFAAUABQACsAKwArAFAAUABQACsAUABQAFAAUAArACsAKwBQAFAAKwBQACsAUABQACsAKwArAFAAUAArACsAKwBQAFAAUAArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArAAQABAAEAAQABAArACsAKwAEAAQABAArAAQABAAEAAQAKwArAFAAKwArACsAKwArACsABAArACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAUABQAFAAHgAeAB4AHgAeAB4AGwAeACsAKwArACsAKwAEAAQABAAEAAQAUABQAFAAUABQAFAAUABQACsAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAUAAEAAQABAAEAAQABAAEACsABAAEAAQAKwAEAAQABAAEACsAKwArACsAKwArACsABAAEACsAUABQAFAAKwArACsAKwArAFAAUAAEAAQAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAKwAOAFAAUABQAFAAUABQAFAAHgBQAAQABAAEAA4AUABQAFAAUABQAFAAUABQACsAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAKwArAAQAUAAEAAQABAAEAAQABAAEACsABAAEAAQAKwAEAAQABAAEACsAKwArACsAKwArACsABAAEACsAKwArACsAKwArACsAUAArAFAAUAAEAAQAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwBQAFAAKwArACsAKwArACsAKwArACsAKwArACsAKwAEAAQABAAEAFAAUABQAFAAUABQAFAAUABQACsAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAFAABAAEAAQABAAEAAQABAArAAQABAAEACsABAAEAAQABABQAB4AKwArACsAKwBQAFAAUAAEAFAAUABQAFAAUABQAFAAUABQAFAABAAEACsAKwBLAEsASwBLAEsASwBLAEsASwBLAFAAUABQAFAAUABQAFAAUABQABoAUABQAFAAUABQAFAAKwAEAAQABAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQACsAUAArACsAUABQAFAAUABQAFAAUAArACsAKwAEACsAKwArACsABAAEAAQABAAEAAQAKwAEACsABAAEAAQABAAEAAQABAAEACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArAAQABAAeACsAKwArACsAKwArACsAKwArACsAKwArAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXAAqAFwAXAAqACoAKgAqACoAKgAqACsAKwArACsAGwBcAFwAXABcAFwAXABcACoAKgAqACoAKgAqACoAKgAeAEsASwBLAEsASwBLAEsASwBLAEsADQANACsAKwArACsAKwBcAFwAKwBcACsAXABcAFwAXABcACsAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcACsAXAArAFwAXABcAFwAXABcAFwAXABcAFwAKgBcAFwAKgAqACoAKgAqACoAKgAqACoAXAArACsAXABcAFwAXABcACsAXAArACoAKgAqACoAKgAqACsAKwBLAEsASwBLAEsASwBLAEsASwBLACsAKwBcAFwAXABcAFAADgAOAA4ADgAeAA4ADgAJAA4ADgANAAkAEwATABMAEwATAAkAHgATAB4AHgAeAAQABAAeAB4AHgAeAB4AHgBLAEsASwBLAEsASwBLAEsASwBLAFAAUABQAFAAUABQAFAAUABQAFAADQAEAB4ABAAeAAQAFgARABYAEQAEAAQAUABQAFAAUABQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQADQAEAAQABAAEAAQADQAEAAQAUABQAFAAUABQAAQABAAEAAQABAAEAAQABAAEAAQABAArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAArAA0ADQAeAB4AHgAeAB4AHgAEAB4AHgAeAB4AHgAeACsAHgAeAA4ADgANAA4AHgAeAB4AHgAeAAkACQArACsAKwArACsAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgBcAEsASwBLAEsASwBLAEsASwBLAEsADQANAB4AHgAeAB4AXABcAFwAXABcAFwAKgAqACoAKgBcAFwAXABcACoAKgAqAFwAKgAqACoAXABcACoAKgAqACoAKgAqACoAXABcAFwAKgAqACoAKgBcAFwAXABcAFwAXABcAFwAXABcAFwAXABcACoAKgAqACoAKgAqACoAKgAqACoAKgAqAFwAKgBLAEsASwBLAEsASwBLAEsASwBLACoAKgAqACoAKgAqAFAAUABQAFAAUABQACsAUAArACsAKwArACsAUAArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgBQAFAAUABQAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFAAUABQAFAAUABQAFAAUABQACsAUABQAFAAUAArACsAUABQAFAAUABQAFAAUAArAFAAKwBQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAKwArAFAAUABQAFAAUABQAFAAKwBQACsAUABQAFAAUAArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsABAAEAAQAHgANAB4AHgAeAB4AHgAeAB4AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUAArACsADQBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAANAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAWABEAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAA0ADQANAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAAQABAAEACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAANAA0AKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUAArAAQABAArACsAKwArACsAKwArACsAKwArACsAKwBcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqAA0ADQAVAFwADQAeAA0AGwBcACoAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwAeAB4AEwATAA0ADQAOAB4AEwATAB4ABAAEAAQACQArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAFAAUABQAFAAUAAEAAQAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQAUAArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAArACsAKwArAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwArACsAHgArACsAKwATABMASwBLAEsASwBLAEsASwBLAEsASwBcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXAArACsAXABcAFwAXABcACsAKwArACsAKwArACsAKwArACsAKwBcAFwAXABcAFwAXABcAFwAXABcAFwAXAArACsAKwArAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAXAArACsAKwAqACoAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAArACsAHgAeAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcACoAKgAqACoAKgAqACoAKgAqACoAKwAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKwArAAQASwBLAEsASwBLAEsASwBLAEsASwArACsAKwArACsAKwBLAEsASwBLAEsASwBLAEsASwBLACsAKwArACsAKwArACoAKgAqACoAKgAqACoAXAAqACoAKgAqACoAKgArACsABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsABAAEAAQABAAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABABQAFAAUABQAFAAUABQACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwANAA0AHgANAA0ADQANAB4AHgAeAB4AHgAeAB4AHgAeAB4ABAAEAAQABAAEAAQABAAEAAQAHgAeAB4AHgAeAB4AHgAeAB4AKwArACsABAAEAAQAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABABQAFAASwBLAEsASwBLAEsASwBLAEsASwBQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwArACsAKwArACsAKwAeAB4AHgAeAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwArAA0ADQANAA0ADQBLAEsASwBLAEsASwBLAEsASwBLACsAKwArAFAAUABQAEsASwBLAEsASwBLAEsASwBLAEsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAA0ADQBQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUAAeAB4AHgAeAB4AHgAeAB4AKwArACsAKwArACsAKwArAAQABAAEAB4ABAAEAAQABAAEAAQABAAEAAQABAAEAAQABABQAFAAUABQAAQAUABQAFAAUABQAFAABABQAFAABAAEAAQAUAArACsAKwArACsABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsABAAEAAQABAAEAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwArAFAAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAKwBQACsAUAArAFAAKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACsAKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArAB4AHgAeAB4AHgAeAB4AHgBQAB4AHgAeAFAAUABQACsAHgAeAB4AHgAeAB4AHgAeAB4AHgBQAFAAUABQACsAKwAeAB4AHgAeAB4AHgArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwArAFAAUABQACsAHgAeAB4AHgAeAB4AHgAOAB4AKwANAA0ADQANAA0ADQANAAkADQANAA0ACAAEAAsABAAEAA0ACQANAA0ADAAdAB0AHgAXABcAFgAXABcAFwAWABcAHQAdAB4AHgAUABQAFAANAAEAAQAEAAQABAAEAAQACQAaABoAGgAaABoAGgAaABoAHgAXABcAHQAVABUAHgAeAB4AHgAeAB4AGAAWABEAFQAVABUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4ADQAeAA0ADQANAA0AHgANAA0ADQAHAB4AHgAeAB4AKwAEAAQABAAEAAQABAAEAAQABAAEAFAAUAArACsATwBQAFAAUABQAFAAHgAeAB4AFgARAE8AUABPAE8ATwBPAFAAUABQAFAAUAAeAB4AHgAWABEAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArABsAGwAbABsAGwAbABsAGgAbABsAGwAbABsAGwAbABsAGwAbABsAGwAbABsAGgAbABsAGwAbABoAGwAbABoAGwAbABsAGwAbABsAGwAbABsAGwAbABsAGwAbABsAGwAbAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAHgAeAFAAGgAeAB0AHgBQAB4AGgAeAB4AHgAeAB4AHgAeAB4AHgBPAB4AUAAbAB4AHgBQAFAAUABQAFAAHgAeAB4AHQAdAB4AUAAeAFAAHgBQAB4AUABPAFAAUAAeAB4AHgAeAB4AHgAeAFAAUABQAFAAUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAFAAHgBQAFAAUABQAE8ATwBQAFAAUABQAFAATwBQAFAATwBQAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAFAAUABQAFAATwBPAE8ATwBPAE8ATwBPAE8ATwBQAFAAUABQAFAAUABQAFAAUAAeAB4AUABQAFAAUABPAB4AHgArACsAKwArAB0AHQAdAB0AHQAdAB0AHQAdAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB0AHgAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB4AHQAdAB4AHgAeAB0AHQAeAB4AHQAeAB4AHgAdAB4AHQAbABsAHgAdAB4AHgAeAB4AHQAeAB4AHQAdAB0AHQAeAB4AHQAeAB0AHgAdAB0AHQAdAB0AHQAeAB0AHgAeAB4AHgAeAB0AHQAdAB0AHgAeAB4AHgAdAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB4AHgAeAB0AHgAeAB4AHgAeAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB0AHgAeAB0AHQAdAB0AHgAeAB0AHQAeAB4AHQAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB0AHQAeAB4AHQAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHQAeAB4AHgAdAB4AHgAeAB4AHgAeAB4AHQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AFAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeABYAEQAWABEAHgAeAB4AHgAeAB4AHQAeAB4AHgAeAB4AHgAeACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAWABEAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AJQAlACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAFAAHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHgAeAB4AHgAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAeAB4AHQAdAB0AHQAeAB4AHgAeAB4AHgAeAB4AHgAeAB0AHQAeAB0AHQAdAB0AHQAdAB0AHgAeAB4AHgAeAB4AHgAeAB0AHQAeAB4AHQAdAB4AHgAeAB4AHQAdAB4AHgAeAB4AHQAdAB0AHgAeAB0AHgAeAB0AHQAdAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB0AHQAdAB4AHgAeAB4AHgAeAB4AHgAeAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAlACUAJQAlAB4AHQAdAB4AHgAdAB4AHgAeAB4AHQAdAB4AHgAeAB4AJQAlAB0AHQAlAB4AJQAlACUAIAAlACUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAlACUAJQAeAB4AHgAeAB0AHgAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB0AHgAdAB0AHQAeAB0AJQAdAB0AHgAdAB0AHgAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHQAdAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAlACUAJQAlACUAJQAlACUAJQAlACUAJQAdAB0AHQAdACUAHgAlACUAJQAdACUAJQAdAB0AHQAlACUAHQAdACUAHQAdACUAJQAlAB4AHQAeAB4AHgAeAB0AHQAlAB0AHQAdAB0AHQAdACUAJQAlACUAJQAdACUAJQAgACUAHQAdACUAJQAlACUAJQAlACUAJQAeAB4AHgAlACUAIAAgACAAIAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB0AHgAeAB4AFwAXABcAFwAXABcAHgATABMAJQAeAB4AHgAWABEAFgARABYAEQAWABEAFgARABYAEQAWABEATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeABYAEQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAWABEAFgARABYAEQAWABEAFgARAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AFgARABYAEQAWABEAFgARABYAEQAWABEAFgARABYAEQAWABEAFgARABYAEQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAWABEAFgARAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AFgARAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAdAB0AHQAdAB0AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AUABQAFAAUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAEAAQABAAeAB4AKwArACsAKwArABMADQANAA0AUAATAA0AUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAUAANACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQACsAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXAA0ADQANAA0ADQANAA0ADQAeAA0AFgANAB4AHgAXABcAHgAeABcAFwAWABEAFgARABYAEQAWABEADQANAA0ADQATAFAADQANAB4ADQANAB4AHgAeAB4AHgAMAAwADQANAA0AHgANAA0AFgANAA0ADQANAA0ADQANAA0AHgANAB4ADQANAB4AHgAeACsAKwArACsAKwArACsAKwArACsAKwArACsAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACsAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAKwArACsAKwArACsAKwArACsAKwArACsAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAlACUAJQAlACUAJQAlACUAJQAlACUAJQArACsAKwArAA0AEQARACUAJQBHAFcAVwAWABEAFgARABYAEQAWABEAFgARACUAJQAWABEAFgARABYAEQAWABEAFQAWABEAEQAlAFcAVwBXAFcAVwBXAFcAVwBXAAQABAAEAAQABAAEACUAVwBXAFcAVwA2ACUAJQBXAFcAVwBHAEcAJQAlACUAKwBRAFcAUQBXAFEAVwBRAFcAUQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFEAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBRAFcAUQBXAFEAVwBXAFcAVwBXAFcAUQBXAFcAVwBXAFcAVwBRAFEAKwArAAQABAAVABUARwBHAFcAFQBRAFcAUQBXAFEAVwBRAFcAUQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFEAVwBRAFcAUQBXAFcAVwBXAFcAVwBRAFcAVwBXAFcAVwBXAFEAUQBXAFcAVwBXABUAUQBHAEcAVwArACsAKwArACsAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAKwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAKwAlACUAVwBXAFcAVwAlACUAJQAlACUAJQAlACUAJQAlACsAKwArACsAKwArACsAKwArACsAKwArAFEAUQBRAFEAUQBRAFEAUQBRAFEAUQBRAFEAUQBRAFEAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQArAFcAVwBXAFcAVwBXAFcAVwBXAFcAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQBPAE8ATwBPAE8ATwBPAE8AJQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXACUAJQAlAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAEcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAKwArACsAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAADQATAA0AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABLAEsASwBLAEsASwBLAEsASwBLAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAFAABAAEAAQABAAeAAQABAAEAAQABAAEAAQABAAEAAQAHgBQAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AUABQAAQABABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAeAA0ADQANAA0ADQArACsAKwArACsAKwArACsAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAFAAUABQAFAAUABQAFAAUABQAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AUAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgBQAB4AHgAeAB4AHgAeAFAAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAHgAeAB4AHgAeAB4AHgAeAB4AKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAeAB4AUABQAFAAUABQAFAAUABQAFAAUABQAAQAUABQAFAABABQAFAAUABQAAQAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAAeAB4AHgAeAAQAKwArACsAUABQAFAAUABQAFAAHgAeABoAHgArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAADgAOABMAEwArACsAKwArACsAKwArACsABAAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAAEACsAKwArACsAKwArACsAKwANAA0ASwBLAEsASwBLAEsASwBLAEsASwArACsAKwArACsAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABABQAFAAUABQAFAAUAAeAB4AHgBQAA4AUABQAAQAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAA0ADQBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAKwArACsAKwArACsAKwArACsAKwArAB4AWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYAFgAWABYACsAKwArAAQAHgAeAB4AHgAeAB4ADQANAA0AHgAeAB4AHgArAFAASwBLAEsASwBLAEsASwBLAEsASwArACsAKwArAB4AHgBcAFwAXABcAFwAKgBcAFwAXABcAFwAXABcAFwAXABcAEsASwBLAEsASwBLAEsASwBLAEsAXABcAFwAXABcACsAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsAKwArACsAKwArACsAKwArAFAAUABQAAQAUABQAFAAUABQAFAAUABQAAQABAArACsASwBLAEsASwBLAEsASwBLAEsASwArACsAHgANAA0ADQBcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAKgAqACoAXAAqACoAKgBcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXAAqAFwAKgAqACoAXABcACoAKgBcAFwAXABcAFwAKgAqAFwAKgBcACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFwAXABcACoAKgBQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAA0ADQBQAFAAUAAEAAQAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUAArACsAUABQAFAAUABQAFAAKwArAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgAeACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQADQAEAAQAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAVABVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBUAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVAFUAVQBVACsAKwArACsAKwArACsAKwArACsAKwArAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAWQBZAFkAKwArACsAKwBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAWgBaAFoAKwArACsAKwAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYABgAGAAYAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXACUAJQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAJQAlACUAJQAlACUAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAKwArACsAKwArAFYABABWAFYAVgBWAFYAVgBWAFYAVgBWAB4AVgBWAFYAVgBWAFYAVgBWAFYAVgBWAFYAVgArAFYAVgBWAFYAVgArAFYAKwBWAFYAKwBWAFYAKwBWAFYAVgBWAFYAVgBWAFYAVgBWAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAEQAWAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUAAaAB4AKwArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAGAARABEAGAAYABMAEwAWABEAFAArACsAKwArACsAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACUAJQAlACUAJQAWABEAFgARABYAEQAWABEAFgARABYAEQAlACUAFgARACUAJQAlACUAJQAlACUAEQAlABEAKwAVABUAEwATACUAFgARABYAEQAWABEAJQAlACUAJQAlACUAJQAlACsAJQAbABoAJQArACsAKwArAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArAAcAKwATACUAJQAbABoAJQAlABYAEQAlACUAEQAlABEAJQBXAFcAVwBXAFcAVwBXAFcAVwBXABUAFQAlACUAJQATACUAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXABYAJQARACUAJQAlAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwAWACUAEQAlABYAEQARABYAEQARABUAVwBRAFEAUQBRAFEAUQBRAFEAUQBRAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAEcARwArACsAVwBXAFcAVwBXAFcAKwArAFcAVwBXAFcAVwBXACsAKwBXAFcAVwBXAFcAVwArACsAVwBXAFcAKwArACsAGgAbACUAJQAlABsAGwArAB4AHgAeAB4AHgAeAB4AKwArACsAKwArACsAKwArACsAKwAEAAQABAAQAB0AKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsADQANAA0AKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArAB4AHgAeAB4AHgAeAB4AHgAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgBQAFAAHgAeAB4AKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAAQAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAA0AUABQAFAAUAArACsAKwArAFAAUABQAFAAUABQAFAAUAANAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwAeACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAKwArAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUAArACsAKwBQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwANAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAeAB4AUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUAArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArAA0AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAUABQAFAAUABQAAQABAAEACsABAAEACsAKwArACsAKwAEAAQABAAEAFAAUABQAFAAKwBQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArAAQABAAEACsAKwArACsABABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAA0ADQANAA0ADQANAA0ADQAeACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAeAFAAUABQAFAAUABQAFAAUAAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAArACsAKwArAFAAUABQAFAAUAANAA0ADQANAA0ADQAUACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsADQANAA0ADQANAA0ADQBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAB4AHgAeAB4AKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArAFAAUABQAFAAUABQAAQABAAEAAQAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUAArAAQABAANACsAKwBQAFAAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAAQABAAEAAQABAAEAAQABAAEAAQABABQAFAAUABQAB4AHgAeAB4AHgArACsAKwArACsAKwAEAAQABAAEAAQABAAEAA0ADQAeAB4AHgAeAB4AKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsABABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAQABAAEAAQABAAEAAQABAAEAAQABAAeAB4AHgANAA0ADQANACsAKwArACsAKwArACsAKwArACsAKwAeACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwArACsAKwBLAEsASwBLAEsASwBLAEsASwBLACsAKwArACsAKwArAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEACsASwBLAEsASwBLAEsASwBLAEsASwANAA0ADQANAFAABAAEAFAAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAeAA4AUAArACsAKwArACsAKwArACsAKwAEAFAAUABQAFAADQANAB4ADQAEAAQABAAEAB4ABAAEAEsASwBLAEsASwBLAEsASwBLAEsAUAAOAFAADQANAA0AKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAANAA0AHgANAA0AHgAEACsAUABQAFAAUABQAFAAUAArAFAAKwBQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAA0AKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsABAAEAAQABAArAFAAUABQAFAAUABQAFAAUAArACsAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUABQACsAUABQAFAAUABQACsABAAEAFAABAAEAAQABAAEAAQABAArACsABAAEACsAKwAEAAQABAArACsAUAArACsAKwArACsAKwAEACsAKwArACsAKwBQAFAAUABQAFAABAAEACsAKwAEAAQABAAEAAQABAAEACsAKwArAAQABAAEAAQABAArACsAKwArACsAKwArACsAKwArACsABAAEAAQABAAEAAQABABQAFAAUABQAA0ADQANAA0AHgBLAEsASwBLAEsASwBLAEsASwBLAA0ADQArAB4ABABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAEAAQABAAEAFAAUAAeAFAAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAArACsABAAEAAQABAAEAAQABAAEAAQADgANAA0AEwATAB4AHgAeAA0ADQANAA0ADQANAA0ADQANAA0ADQANAA0ADQANAFAAUABQAFAABAAEACsAKwAEAA0ADQAeAFAAKwArACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAFAAKwArACsAKwArACsAKwBLAEsASwBLAEsASwBLAEsASwBLACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAXABcAFwAKwArACoAKgAqACoAKgAqACoAKgAqACoAKgAqACoAKgAqACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwBcAFwADQANAA0AKgBQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAeACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwBQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAKwArAFAAKwArAFAAUABQAFAAUABQAFAAUAArAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQAKwAEAAQAKwArAAQABAAEAAQAUAAEAFAABAAEAA0ADQANACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAArACsABAAEAAQABAAEAAQABABQAA4AUAAEACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAABAAEAAQABAAEAAQABAAEAAQABABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAFAABAAEAAQABAAOAB4ADQANAA0ADQAOAB4ABAArACsAKwArACsAKwArACsAUAAEAAQABAAEAAQABAAEAAQABAAEAAQAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAA0ADQANAFAADgAOAA4ADQANACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAEAAQABAAEACsABAAEAAQABAAEAAQABAAEAFAADQANAA0ADQANACsAKwArACsAKwArACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwAOABMAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQACsAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAArACsAKwAEACsABAAEACsABAAEAAQABAAEAAQABABQAAQAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAUABQAFAAUABQAFAAKwBQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQAKwAEAAQAKwAEAAQABAAEAAQAUAArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAABAAEAAQABAAeAB4AKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAB4AHgAeAB4AHgAeAB4AHgAaABoAGgAaAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwArACsAKwArACsAKwArAA0AUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsADQANAA0ADQANACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAASABIAEgAQwBDAEMAUABQAFAAUABDAFAAUABQAEgAQwBIAEMAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAASABDAEMAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwAJAAkACQAJAAkACQAJABYAEQArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABIAEMAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwANAA0AKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArAAQABAAEAAQABAANACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEAA0ADQANAB4AHgAeAB4AHgAeAFAAUABQAFAADQAeACsAKwArACsAKwArACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwArAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAANAA0AHgAeACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwAEAFAABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAKwArACsAKwArACsAKwAEAAQABAAEAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAARwBHABUARwAJACsAKwArACsAKwArACsAKwArACsAKwAEAAQAKwArACsAKwArACsAKwArACsAKwArACsAKwArAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXACsAKwArACsAKwArACsAKwBXAFcAVwBXAFcAVwBXAFcAVwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUQBRAFEAKwArACsAKwArACsAKwArACsAKwArACsAKwBRAFEAUQBRACsAKwArACsAKwArACsAKwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUAArACsAHgAEAAQADQAEAAQABAAEACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwArACsAKwArAB4AHgAeAB4AHgAeAB4AKwArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAAQABAAEAAQABAAeAB4AHgAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAB4AHgAEAAQABAAEAAQABAAEAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4ABAAEAAQABAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4ABAAEAAQAHgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwArACsAKwArACsAKwArACsAKwArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwArACsAKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwBQAFAAKwArAFAAKwArAFAAUAArACsAUABQAFAAUAArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACsAUAArAFAAUABQAFAAUABQAFAAKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwBQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAHgAeAFAAUABQAFAAUAArAFAAKwArACsAUABQAFAAUABQAFAAUAArAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAHgBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgBQAFAAUABQAFAAUABQAFAAUABQAFAAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAB4AHgAeAB4AHgAeAB4AHgAeACsAKwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAEsASwBLAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAeAB4AHgAeAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAeAB4AHgAeAB4AHgAeAB4ABAAeAB4AHgAeAB4AHgAeAB4AHgAeAAQAHgAeAA0ADQANAA0AHgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAEAAQABAAEAAQAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAAQABAAEAAQABAAEAAQAKwAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAKwArAAQABAAEAAQABAAEAAQAKwAEAAQAKwAEAAQABAAEAAQAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwAEAAQABAAEAAQABAAEAFAAUABQAFAAUABQAFAAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwBQAB4AKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArABsAUABQAFAAUABQACsAKwBQAFAAUABQAFAAUABQAFAAUAAEAAQABAAEAAQABAAEACsAKwArACsAKwArACsAKwArAB4AHgAeAB4ABAAEAAQABAAEAAQABABQACsAKwArACsASwBLAEsASwBLAEsASwBLAEsASwArACsAKwArABYAFgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAGgBQAFAAUAAaAFAAUABQAFAAKwArACsAKwArACsAKwArACsAKwArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAeAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQACsAKwBQAFAAUABQACsAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwBQAFAAKwBQACsAKwBQACsAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAKwBQACsAUAArACsAKwArACsAKwBQACsAKwArACsAUAArAFAAKwBQACsAUABQAFAAKwBQAFAAKwBQACsAKwBQACsAUAArAFAAKwBQACsAUAArAFAAUAArAFAAKwArAFAAUABQAFAAKwBQAFAAUABQAFAAUABQACsAUABQAFAAUAArAFAAUABQAFAAKwBQACsAUABQAFAAUABQAFAAUABQAFAAUAArAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAArACsAKwArACsAUABQAFAAKwBQAFAAUABQAFAAKwBQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwAeAB4AKwArACsAKwArACsAKwArACsAKwArACsAKwArAE8ATwBPAE8ATwBPAE8ATwBPAE8ATwBPAE8AJQAlACUAHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHgAeAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB4AHgAeACUAJQAlAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAdAB0AHQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQApACkAKQApACkAKQApACkAKQApACkAKQApACkAKQApACkAKQApACkAKQApACkAKQApACkAJQAlACUAJQAlACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAeAB4AJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlAB4AHgAlACUAJQAlACUAHgAlACUAJQAlACUAIAAgACAAJQAlACAAJQAlACAAIAAgACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACEAIQAhACEAIQAlACUAIAAgACUAJQAgACAAIAAgACAAIAAgACAAIAAgACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJQAlACUAIAAlACUAJQAlACAAIAAgACUAIAAgACAAJQAlACUAJQAlACUAJQAgACUAIAAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAHgAlAB4AJQAeACUAJQAlACUAJQAgACUAJQAlACUAHgAlAB4AHgAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlAB4AHgAeAB4AHgAeAB4AJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAeACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACAAIAAlACUAJQAlACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACAAJQAlACUAJQAgACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAHgAeAB4AHgAeAB4AHgAeACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAeAB4AHgAeAB4AHgAlACUAJQAlACUAJQAlACAAIAAgACUAJQAlACAAIAAgACAAIAAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeABcAFwAXABUAFQAVAB4AHgAeAB4AJQAlACUAIAAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACAAIAAgACUAJQAlACUAJQAlACUAJQAlACAAJQAlACUAJQAlACUAJQAlACUAJQAlACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AJQAlACUAJQAlACUAJQAlACUAJQAlACUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AJQAlACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeACUAJQAlACUAJQAlACUAJQAeAB4AHgAeAB4AHgAeAB4AHgAeACUAJQAlACUAJQAlAB4AHgAeAB4AHgAeAB4AHgAlACUAJQAlACUAJQAlACUAHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAgACUAJQAgACUAJQAlACUAJQAlACUAJQAgACAAIAAgACAAIAAgACAAJQAlACUAJQAlACUAIAAlACUAJQAlACUAJQAlACUAJQAgACAAIAAgACAAIAAgACAAIAAgACUAJQAgACAAIAAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAgACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACAAIAAlACAAIAAlACAAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAgACAAIAAlACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAJQAlAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AKwAeAB4AHgAeAB4AHgAeAB4AHgAeAB4AHgArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAEsASwBLAEsASwBLAEsASwBLAEsAKwArACsAKwArACsAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAKwArAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXACUAJQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwAlACUAJQAlACUAJQAlACUAJQAlACUAVwBXACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQBXAFcAVwBXAFcAVwBXAFcAVwBXAFcAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAJQAlACUAKwAEACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArACsAKwArAA==';\nexport const byteLength = 39664;\n","'use strict';\n\nimport {createTrieFromBase64} from 'utrie';\nimport {base64, byteLength} from './linebreak-trie';\nimport {fromCodePoint, toCodePoints} from './Util';\n\nexport const LETTER_NUMBER_MODIFIER = 50;\n\n// Non-tailorable Line Breaking Classes\nconst BK = 1; // Cause a line break (after)\nconst CR = 2; // Cause a line break (after), except between CR and LF\nconst LF = 3; // Cause a line break (after)\nconst CM = 4; // Prohibit a line break between the character and the preceding character\nconst NL = 5; // Cause a line break (after)\nconst SG = 6; // Do not occur in well-formed text\nconst WJ = 7; // Prohibit line breaks before and after\nconst ZW = 8; // Provide a break opportunity\nconst GL = 9; // Prohibit line breaks before and after\nconst SP = 10; // Enable indirect line breaks\nconst ZWJ = 11; // Prohibit line breaks within joiner sequences\n// Break Opportunities\nconst B2 = 12; // Provide a line break opportunity before and after the character\nconst BA = 13; // Generally provide a line break opportunity after the character\nconst BB = 14; // Generally provide a line break opportunity before the character\nconst HY = 15; // Provide a line break opportunity after the character, except in numeric context\nconst CB = 16; // Provide a line break opportunity contingent on additional information\n// Characters Prohibiting Certain Breaks\nconst CL = 17; // Prohibit line breaks before\nconst CP = 18; // Prohibit line breaks before\nconst EX = 19; // Prohibit line breaks before\nconst IN = 20; // Allow only indirect line breaks between pairs\nconst NS = 21; // Allow only indirect line breaks before\nconst OP = 22; // Prohibit line breaks after\nconst QU = 23; // Act like they are both opening and closing\n// Numeric Context\nconst IS = 24; // Prevent breaks after any and before numeric\nconst NU = 25; // Form numeric expressions for line breaking purposes\nconst PO = 26; // Do not break following a numeric expression\nconst PR = 27; // Do not break in front of a numeric expression\nconst SY = 28; // Prevent a break before; and allow a break after\n// Other Characters\nconst AI = 29; // Act like AL when the resolvedEAW is N; otherwise; act as ID\nconst AL = 30; // Are alphabetic characters or symbols that are used with alphabetic characters\nconst CJ = 31; // Treat as NS or ID for strict or normal breaking.\nconst EB = 32; // Do not break from following Emoji Modifier\nconst EM = 33; // Do not break from preceding Emoji Base\nconst H2 = 34; // Form Korean syllable blocks\nconst H3 = 35; // Form Korean syllable blocks\nconst HL = 36; // Do not break around a following hyphen; otherwise act as Alphabetic\nconst ID = 37; // Break before or after; except in some numeric context\nconst JL = 38; // Form Korean syllable blocks\nconst JV = 39; // Form Korean syllable blocks\nconst JT = 40; // Form Korean syllable blocks\nconst RI = 41; // Keep pairs together. For pairs; break before and after other classes\nconst SA = 42; // Provide a line break opportunity contingent on additional, language-specific context analysis\nconst XX = 43; // Have as yet unknown line breaking behavior or unassigned code positions\n\nconst ea_OP = [0x2329, 0xff08];\n\nexport const classes: {[key: string]: number} = {\n BK,\n CR,\n LF,\n CM,\n NL,\n SG,\n WJ,\n ZW,\n GL,\n SP,\n ZWJ,\n B2,\n BA,\n BB,\n HY,\n CB,\n CL,\n CP,\n EX,\n IN,\n NS,\n OP,\n QU,\n IS,\n NU,\n PO,\n PR,\n SY,\n AI,\n AL,\n CJ,\n EB,\n EM,\n H2,\n H3,\n HL,\n ID,\n JL,\n JV,\n JT,\n RI,\n SA,\n XX,\n};\n\nexport const BREAK_MANDATORY = '!';\nexport const BREAK_NOT_ALLOWED = '×';\nexport const BREAK_ALLOWED = '÷';\nexport const UnicodeTrie = createTrieFromBase64(base64, byteLength);\n\nconst ALPHABETICS = [AL, HL];\nconst HARD_LINE_BREAKS = [BK, CR, LF, NL];\nconst SPACE = [SP, ZW];\nconst PREFIX_POSTFIX = [PR, PO];\nconst LINE_BREAKS = HARD_LINE_BREAKS.concat(SPACE);\nconst KOREAN_SYLLABLE_BLOCK = [JL, JV, JT, H2, H3];\nconst HYPHEN = [HY, BA];\n\nexport const codePointsToCharacterClasses = (\n codePoints: number[],\n lineBreak: string = 'strict'\n): [number[], number[], boolean[]] => {\n const types: number[] = [];\n const indices: number[] = [];\n const categories: boolean[] = [];\n codePoints.forEach((codePoint, index) => {\n let classType = UnicodeTrie.get(codePoint);\n if (classType > LETTER_NUMBER_MODIFIER) {\n categories.push(true);\n classType -= LETTER_NUMBER_MODIFIER;\n } else {\n categories.push(false);\n }\n\n if (['normal', 'auto', 'loose'].indexOf(lineBreak) !== -1) {\n // U+2010, – U+2013, 〜 U+301C, ゠ U+30A0\n if ([0x2010, 0x2013, 0x301c, 0x30a0].indexOf(codePoint) !== -1) {\n indices.push(index);\n return types.push(CB);\n }\n }\n\n if (classType === CM || classType === ZWJ) {\n // LB10 Treat any remaining combining mark or ZWJ as AL.\n if (index === 0) {\n indices.push(index);\n return types.push(AL);\n }\n\n // LB9 Do not break a combining character sequence; treat it as if it has the line breaking class of\n // the base character in all of the following rules. Treat ZWJ as if it were CM.\n const prev = types[index - 1];\n if (LINE_BREAKS.indexOf(prev) === -1) {\n indices.push(indices[index - 1]);\n return types.push(prev);\n }\n indices.push(index);\n return types.push(AL);\n }\n\n indices.push(index);\n\n if (classType === CJ) {\n return types.push(lineBreak === 'strict' ? NS : ID);\n }\n\n if (classType === SA) {\n return types.push(AL);\n }\n\n if (classType === AI) {\n return types.push(AL);\n }\n\n // For supplementary characters, a useful default is to treat characters in the range 10000..1FFFD as AL\n // and characters in the ranges 20000..2FFFD and 30000..3FFFD as ID, until the implementation can be revised\n // to take into account the actual line breaking properties for these characters.\n if (classType === XX) {\n if ((codePoint >= 0x20000 && codePoint <= 0x2fffd) || (codePoint >= 0x30000 && codePoint <= 0x3fffd)) {\n return types.push(ID);\n } else {\n return types.push(AL);\n }\n }\n\n types.push(classType);\n });\n\n return [indices, types, categories];\n};\n\nconst isAdjacentWithSpaceIgnored = (\n a: number[] | number,\n b: number,\n currentIndex: number,\n classTypes: number[]\n): boolean => {\n const current = classTypes[currentIndex];\n if (Array.isArray(a) ? a.indexOf(current) !== -1 : a === current) {\n let i = currentIndex;\n while (i <= classTypes.length) {\n i++;\n let next = classTypes[i];\n\n if (next === b) {\n return true;\n }\n\n if (next !== SP) {\n break;\n }\n }\n }\n\n if (current === SP) {\n let i = currentIndex;\n\n while (i > 0) {\n i--;\n const prev = classTypes[i];\n\n if (Array.isArray(a) ? a.indexOf(prev) !== -1 : a === prev) {\n let n = currentIndex;\n while (n <= classTypes.length) {\n n++;\n let next = classTypes[n];\n\n if (next === b) {\n return true;\n }\n\n if (next !== SP) {\n break;\n }\n }\n }\n\n if (prev !== SP) {\n break;\n }\n }\n }\n return false;\n};\n\nconst previousNonSpaceClassType = (currentIndex: number, classTypes: number[]): number => {\n let i = currentIndex;\n while (i >= 0) {\n let type = classTypes[i];\n if (type === SP) {\n i--;\n } else {\n return type;\n }\n }\n return 0;\n};\n\nexport type BREAK_OPPORTUNITIES = typeof BREAK_NOT_ALLOWED | typeof BREAK_ALLOWED | typeof BREAK_MANDATORY;\n\nconst _lineBreakAtIndex = (\n codePoints: number[],\n classTypes: number[],\n indicies: number[],\n index: number,\n forbiddenBreaks?: boolean[]\n): BREAK_OPPORTUNITIES => {\n if (indicies[index] === 0) {\n return BREAK_NOT_ALLOWED;\n }\n\n let currentIndex = index - 1;\n if (Array.isArray(forbiddenBreaks) && forbiddenBreaks[currentIndex] === true) {\n return BREAK_NOT_ALLOWED;\n }\n\n let beforeIndex = currentIndex - 1;\n let afterIndex = currentIndex + 1;\n let current = classTypes[currentIndex];\n\n // LB4 Always break after hard line breaks.\n // LB5 Treat CR followed by LF, as well as CR, LF, and NL as hard line breaks.\n let before = beforeIndex >= 0 ? classTypes[beforeIndex] : 0;\n let next = classTypes[afterIndex];\n\n if (current === CR && next === LF) {\n return BREAK_NOT_ALLOWED;\n }\n\n if (HARD_LINE_BREAKS.indexOf(current) !== -1) {\n return BREAK_MANDATORY;\n }\n\n // LB6 Do not break before hard line breaks.\n if (HARD_LINE_BREAKS.indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB7 Do not break before spaces or zero width space.\n if (SPACE.indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB8 Break before any character following a zero-width space, even if one or more spaces intervene.\n if (previousNonSpaceClassType(currentIndex, classTypes) === ZW) {\n return BREAK_ALLOWED;\n }\n\n // LB8a Do not break after a zero width joiner.\n if (UnicodeTrie.get(codePoints[currentIndex]) === ZWJ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // zwj emojis\n if ((current === EB || current === EM) && UnicodeTrie.get(codePoints[afterIndex]) === ZWJ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB11 Do not break before or after Word joiner and related characters.\n if (current === WJ || next === WJ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB12 Do not break after NBSP and related characters.\n if (current === GL) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB12a Do not break before NBSP and related characters, except after spaces and hyphens.\n if ([SP, BA, HY].indexOf(current) === -1 && next === GL) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB13 Do not break before ‘]’ or ‘!’ or ‘;’ or ‘/’, even after spaces.\n if ([CL, CP, EX, IS, SY].indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB14 Do not break after ‘[’, even after spaces.\n if (previousNonSpaceClassType(currentIndex, classTypes) === OP) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB15 Do not break within ‘”[’, even with intervening spaces.\n if (isAdjacentWithSpaceIgnored(QU, OP, currentIndex, classTypes)) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB16 Do not break between closing punctuation and a nonstarter (lb=NS), even with intervening spaces.\n if (isAdjacentWithSpaceIgnored([CL, CP], NS, currentIndex, classTypes)) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB17 Do not break within ‘——’, even with intervening spaces.\n if (isAdjacentWithSpaceIgnored(B2, B2, currentIndex, classTypes)) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB18 Break after spaces.\n if (current === SP) {\n return BREAK_ALLOWED;\n }\n\n // LB19 Do not break before or after quotation marks, such as ‘ ” ’.\n if (current === QU || next === QU) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB20 Break before and after unresolved CB.\n if (next === CB || current === CB) {\n return BREAK_ALLOWED;\n }\n\n // LB21 Do not break before hyphen-minus, other hyphens, fixed-width spaces, small kana, and other non-starters, or after acute accents.\n if ([BA, HY, NS].indexOf(next) !== -1 || current === BB) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB21a Don't break after Hebrew + Hyphen.\n if (before === HL && HYPHEN.indexOf(current) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB21b Don’t break between Solidus and Hebrew letters.\n if (current === SY && next === HL) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB22 Do not break before ellipsis.\n if (next === IN) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB23 Do not break between digits and letters.\n if ((ALPHABETICS.indexOf(next) !== -1 && current === NU) || (ALPHABETICS.indexOf(current) !== -1 && next === NU)) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB23a Do not break between numeric prefixes and ideographs, or between ideographs and numeric postfixes.\n if (\n (current === PR && [ID, EB, EM].indexOf(next) !== -1) ||\n ([ID, EB, EM].indexOf(current) !== -1 && next === PO)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB24 Do not break between numeric prefix/postfix and letters, or between letters and prefix/postfix.\n if (\n (ALPHABETICS.indexOf(current) !== -1 && PREFIX_POSTFIX.indexOf(next) !== -1) ||\n (PREFIX_POSTFIX.indexOf(current) !== -1 && ALPHABETICS.indexOf(next) !== -1)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB25 Do not break between the following pairs of classes relevant to numbers:\n if (\n // (PR | PO) × ( OP | HY )? NU\n ([PR, PO].indexOf(current) !== -1 &&\n (next === NU || ([OP, HY].indexOf(next) !== -1 && classTypes[afterIndex + 1] === NU))) ||\n // ( OP | HY ) × NU\n ([OP, HY].indexOf(current) !== -1 && next === NU) ||\n // NU ×\t(NU | SY | IS)\n (current === NU && [NU, SY, IS].indexOf(next) !== -1)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // NU (NU | SY | IS)* × (NU | SY | IS | CL | CP)\n if ([NU, SY, IS, CL, CP].indexOf(next) !== -1) {\n let prevIndex = currentIndex;\n while (prevIndex >= 0) {\n let type = classTypes[prevIndex];\n if (type === NU) {\n return BREAK_NOT_ALLOWED;\n } else if ([SY, IS].indexOf(type) !== -1) {\n prevIndex--;\n } else {\n break;\n }\n }\n }\n\n // NU (NU | SY | IS)* (CL | CP)? × (PO | PR))\n if ([PR, PO].indexOf(next) !== -1) {\n let prevIndex = [CL, CP].indexOf(current) !== -1 ? beforeIndex : currentIndex;\n while (prevIndex >= 0) {\n let type = classTypes[prevIndex];\n if (type === NU) {\n return BREAK_NOT_ALLOWED;\n } else if ([SY, IS].indexOf(type) !== -1) {\n prevIndex--;\n } else {\n break;\n }\n }\n }\n\n // LB26 Do not break a Korean syllable.\n if (\n (JL === current && [JL, JV, H2, H3].indexOf(next) !== -1) ||\n ([JV, H2].indexOf(current) !== -1 && [JV, JT].indexOf(next) !== -1) ||\n ([JT, H3].indexOf(current) !== -1 && next === JT)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB27 Treat a Korean Syllable Block the same as ID.\n if (\n (KOREAN_SYLLABLE_BLOCK.indexOf(current) !== -1 && [IN, PO].indexOf(next) !== -1) ||\n (KOREAN_SYLLABLE_BLOCK.indexOf(next) !== -1 && current === PR)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB28 Do not break between alphabetics (“at”).\n if (ALPHABETICS.indexOf(current) !== -1 && ALPHABETICS.indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB29 Do not break between numeric punctuation and alphabetics (“e.g.”).\n if (current === IS && ALPHABETICS.indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB30 Do not break between letters, numbers, or ordinary symbols and opening or closing parentheses.\n if (\n (ALPHABETICS.concat(NU).indexOf(current) !== -1 &&\n next === OP &&\n ea_OP.indexOf(codePoints[afterIndex]) === -1) ||\n (ALPHABETICS.concat(NU).indexOf(next) !== -1 && current === CP)\n ) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB30a Break between two regional indicator symbols if and only if there are an even number of regional\n // indicators preceding the position of the break.\n if (current === RI && next === RI) {\n let i = indicies[currentIndex];\n let count = 1;\n while (i > 0) {\n i--;\n if (classTypes[i] === RI) {\n count++;\n } else {\n break;\n }\n }\n if (count % 2 !== 0) {\n return BREAK_NOT_ALLOWED;\n }\n }\n\n // LB30b Do not break between an emoji base and an emoji modifier.\n if (current === EB && next === EM) {\n return BREAK_NOT_ALLOWED;\n }\n\n return BREAK_ALLOWED;\n};\n\nexport const lineBreakAtIndex = (codePoints: number[], index: number): BREAK_OPPORTUNITIES => {\n // LB2 Never break at the start of text.\n if (index === 0) {\n return BREAK_NOT_ALLOWED;\n }\n\n // LB3 Always break at the end of text.\n if (index >= codePoints.length) {\n return BREAK_MANDATORY;\n }\n\n const [indices, classTypes] = codePointsToCharacterClasses(codePoints);\n\n return _lineBreakAtIndex(codePoints, classTypes, indices, index);\n};\n\nexport type LINE_BREAK = 'auto' | 'normal' | 'strict';\nexport type WORD_BREAK = 'normal' | 'break-all' | 'break-word' | 'keep-all';\n\ninterface IOptions {\n lineBreak?: LINE_BREAK;\n wordBreak?: WORD_BREAK;\n}\n\nconst cssFormattedClasses = (codePoints: number[], options?: IOptions): [number[], number[], boolean[] | undefined] => {\n if (!options) {\n options = {lineBreak: 'normal', wordBreak: 'normal'};\n }\n let [indicies, classTypes, isLetterNumber] = codePointsToCharacterClasses(codePoints, options.lineBreak);\n\n if (options.wordBreak === 'break-all' || options.wordBreak === 'break-word') {\n classTypes = classTypes.map((type) => ([NU, AL, SA].indexOf(type) !== -1 ? ID : type));\n }\n\n const forbiddenBreakpoints =\n options.wordBreak === 'keep-all'\n ? isLetterNumber.map((letterNumber, i) => {\n return letterNumber && codePoints[i] >= 0x4e00 && codePoints[i] <= 0x9fff;\n })\n : undefined;\n\n return [indicies, classTypes, forbiddenBreakpoints];\n};\n\nexport const inlineBreakOpportunities = (str: string, options?: IOptions): string => {\n const codePoints = toCodePoints(str);\n let output = BREAK_NOT_ALLOWED;\n const [indicies, classTypes, forbiddenBreakpoints] = cssFormattedClasses(codePoints, options);\n\n codePoints.forEach((codePoint, i) => {\n output +=\n fromCodePoint(codePoint) +\n (i >= codePoints.length - 1\n ? BREAK_MANDATORY\n : _lineBreakAtIndex(codePoints, classTypes, indicies, i + 1, forbiddenBreakpoints));\n });\n\n return output;\n};\n\nclass Break {\n private readonly codePoints: number[];\n readonly required: boolean;\n readonly start: number;\n readonly end: number;\n\n constructor(codePoints: number[], lineBreak: string, start: number, end: number) {\n this.codePoints = codePoints;\n this.required = lineBreak === BREAK_MANDATORY;\n this.start = start;\n this.end = end;\n }\n\n slice(): string {\n return fromCodePoint(...this.codePoints.slice(this.start, this.end));\n }\n}\n\nexport type LineBreak =\n | {\n done: true;\n value: null;\n }\n | {\n done: false;\n value: Break;\n };\n\ninterface ILineBreakIterator {\n next: () => LineBreak;\n}\n\nexport const LineBreaker = (str: string, options?: IOptions): ILineBreakIterator => {\n const codePoints = toCodePoints(str);\n const [indicies, classTypes, forbiddenBreakpoints] = cssFormattedClasses(codePoints, options);\n const length = codePoints.length;\n let lastEnd = 0;\n let nextIndex = 0;\n\n return {\n next: () => {\n if (nextIndex >= length) {\n return {done: true, value: null};\n }\n let lineBreak = BREAK_NOT_ALLOWED;\n while (\n nextIndex < length &&\n (lineBreak = _lineBreakAtIndex(codePoints, classTypes, indicies, ++nextIndex, forbiddenBreakpoints)) ===\n BREAK_NOT_ALLOWED\n ) {}\n\n if (lineBreak !== BREAK_NOT_ALLOWED || nextIndex === length) {\n const value = new Break(codePoints, lineBreak, lastEnd, nextIndex);\n lastEnd = nextIndex;\n return {value, done: false};\n }\n\n return {done: true, value: null};\n },\n };\n};\n","// https://www.w3.org/TR/css-syntax-3\n\nimport {fromCodePoint, toCodePoints} from 'css-line-break';\n\nexport const enum TokenType {\n STRING_TOKEN,\n BAD_STRING_TOKEN,\n LEFT_PARENTHESIS_TOKEN,\n RIGHT_PARENTHESIS_TOKEN,\n COMMA_TOKEN,\n HASH_TOKEN,\n DELIM_TOKEN,\n AT_KEYWORD_TOKEN,\n PREFIX_MATCH_TOKEN,\n DASH_MATCH_TOKEN,\n INCLUDE_MATCH_TOKEN,\n LEFT_CURLY_BRACKET_TOKEN,\n RIGHT_CURLY_BRACKET_TOKEN,\n SUFFIX_MATCH_TOKEN,\n SUBSTRING_MATCH_TOKEN,\n DIMENSION_TOKEN,\n PERCENTAGE_TOKEN,\n NUMBER_TOKEN,\n FUNCTION,\n FUNCTION_TOKEN,\n IDENT_TOKEN,\n COLUMN_TOKEN,\n URL_TOKEN,\n BAD_URL_TOKEN,\n CDC_TOKEN,\n CDO_TOKEN,\n COLON_TOKEN,\n SEMICOLON_TOKEN,\n LEFT_SQUARE_BRACKET_TOKEN,\n RIGHT_SQUARE_BRACKET_TOKEN,\n UNICODE_RANGE_TOKEN,\n WHITESPACE_TOKEN,\n EOF_TOKEN\n}\n\ninterface IToken {\n type: TokenType;\n}\n\nexport interface Token extends IToken {\n type:\n | TokenType.BAD_URL_TOKEN\n | TokenType.BAD_STRING_TOKEN\n | TokenType.LEFT_PARENTHESIS_TOKEN\n | TokenType.RIGHT_PARENTHESIS_TOKEN\n | TokenType.COMMA_TOKEN\n | TokenType.SUBSTRING_MATCH_TOKEN\n | TokenType.PREFIX_MATCH_TOKEN\n | TokenType.SUFFIX_MATCH_TOKEN\n | TokenType.COLON_TOKEN\n | TokenType.SEMICOLON_TOKEN\n | TokenType.LEFT_SQUARE_BRACKET_TOKEN\n | TokenType.RIGHT_SQUARE_BRACKET_TOKEN\n | TokenType.LEFT_CURLY_BRACKET_TOKEN\n | TokenType.RIGHT_CURLY_BRACKET_TOKEN\n | TokenType.DASH_MATCH_TOKEN\n | TokenType.INCLUDE_MATCH_TOKEN\n | TokenType.COLUMN_TOKEN\n | TokenType.WHITESPACE_TOKEN\n | TokenType.CDC_TOKEN\n | TokenType.CDO_TOKEN\n | TokenType.EOF_TOKEN;\n}\n\nexport interface StringValueToken extends IToken {\n type:\n | TokenType.STRING_TOKEN\n | TokenType.DELIM_TOKEN\n | TokenType.FUNCTION_TOKEN\n | TokenType.IDENT_TOKEN\n | TokenType.URL_TOKEN\n | TokenType.AT_KEYWORD_TOKEN;\n value: string;\n}\n\nexport interface HashToken extends IToken {\n type: TokenType.HASH_TOKEN;\n flags: number;\n value: string;\n}\n\nexport interface NumberValueToken extends IToken {\n type: TokenType.PERCENTAGE_TOKEN | TokenType.NUMBER_TOKEN;\n flags: number;\n number: number;\n}\n\nexport interface DimensionToken extends IToken {\n type: TokenType.DIMENSION_TOKEN;\n flags: number;\n unit: string;\n number: number;\n}\n\nexport interface UnicodeRangeToken extends IToken {\n type: TokenType.UNICODE_RANGE_TOKEN;\n start: number;\n end: number;\n}\n\nexport type CSSToken = Token | StringValueToken | NumberValueToken | DimensionToken | UnicodeRangeToken | HashToken;\n\nexport const FLAG_UNRESTRICTED = 1 << 0;\nexport const FLAG_ID = 1 << 1;\nexport const FLAG_INTEGER = 1 << 2;\nexport const FLAG_NUMBER = 1 << 3;\n\nconst LINE_FEED = 0x000a;\nconst SOLIDUS = 0x002f;\nconst REVERSE_SOLIDUS = 0x005c;\nconst CHARACTER_TABULATION = 0x0009;\nconst SPACE = 0x0020;\nconst QUOTATION_MARK = 0x0022;\nconst EQUALS_SIGN = 0x003d;\nconst NUMBER_SIGN = 0x0023;\nconst DOLLAR_SIGN = 0x0024;\nconst PERCENTAGE_SIGN = 0x0025;\nconst APOSTROPHE = 0x0027;\nconst LEFT_PARENTHESIS = 0x0028;\nconst RIGHT_PARENTHESIS = 0x0029;\nconst LOW_LINE = 0x005f;\nconst HYPHEN_MINUS = 0x002d;\nconst EXCLAMATION_MARK = 0x0021;\nconst LESS_THAN_SIGN = 0x003c;\nconst GREATER_THAN_SIGN = 0x003e;\nconst COMMERCIAL_AT = 0x0040;\nconst LEFT_SQUARE_BRACKET = 0x005b;\nconst RIGHT_SQUARE_BRACKET = 0x005d;\nconst CIRCUMFLEX_ACCENT = 0x003d;\nconst LEFT_CURLY_BRACKET = 0x007b;\nconst QUESTION_MARK = 0x003f;\nconst RIGHT_CURLY_BRACKET = 0x007d;\nconst VERTICAL_LINE = 0x007c;\nconst TILDE = 0x007e;\nconst CONTROL = 0x0080;\nconst REPLACEMENT_CHARACTER = 0xfffd;\nconst ASTERISK = 0x002a;\nconst PLUS_SIGN = 0x002b;\nconst COMMA = 0x002c;\nconst COLON = 0x003a;\nconst SEMICOLON = 0x003b;\nconst FULL_STOP = 0x002e;\nconst NULL = 0x0000;\nconst BACKSPACE = 0x0008;\nconst LINE_TABULATION = 0x000b;\nconst SHIFT_OUT = 0x000e;\nconst INFORMATION_SEPARATOR_ONE = 0x001f;\nconst DELETE = 0x007f;\nconst EOF = -1;\nconst ZERO = 0x0030;\nconst a = 0x0061;\nconst e = 0x0065;\nconst f = 0x0066;\nconst u = 0x0075;\nconst z = 0x007a;\nconst A = 0x0041;\nconst E = 0x0045;\nconst F = 0x0046;\nconst U = 0x0055;\nconst Z = 0x005a;\n\nconst isDigit = (codePoint: number) => codePoint >= ZERO && codePoint <= 0x0039;\nconst isSurrogateCodePoint = (codePoint: number) => codePoint >= 0xd800 && codePoint <= 0xdfff;\nconst isHex = (codePoint: number) =>\n isDigit(codePoint) || (codePoint >= A && codePoint <= F) || (codePoint >= a && codePoint <= f);\nconst isLowerCaseLetter = (codePoint: number) => codePoint >= a && codePoint <= z;\nconst isUpperCaseLetter = (codePoint: number) => codePoint >= A && codePoint <= Z;\nconst isLetter = (codePoint: number) => isLowerCaseLetter(codePoint) || isUpperCaseLetter(codePoint);\nconst isNonASCIICodePoint = (codePoint: number) => codePoint >= CONTROL;\nconst isWhiteSpace = (codePoint: number): boolean =>\n codePoint === LINE_FEED || codePoint === CHARACTER_TABULATION || codePoint === SPACE;\nconst isNameStartCodePoint = (codePoint: number): boolean =>\n isLetter(codePoint) || isNonASCIICodePoint(codePoint) || codePoint === LOW_LINE;\nconst isNameCodePoint = (codePoint: number): boolean =>\n isNameStartCodePoint(codePoint) || isDigit(codePoint) || codePoint === HYPHEN_MINUS;\nconst isNonPrintableCodePoint = (codePoint: number): boolean => {\n return (\n (codePoint >= NULL && codePoint <= BACKSPACE) ||\n codePoint === LINE_TABULATION ||\n (codePoint >= SHIFT_OUT && codePoint <= INFORMATION_SEPARATOR_ONE) ||\n codePoint === DELETE\n );\n};\nconst isValidEscape = (c1: number, c2: number): boolean => {\n if (c1 !== REVERSE_SOLIDUS) {\n return false;\n }\n\n return c2 !== LINE_FEED;\n};\nconst isIdentifierStart = (c1: number, c2: number, c3: number): boolean => {\n if (c1 === HYPHEN_MINUS) {\n return isNameStartCodePoint(c2) || isValidEscape(c2, c3);\n } else if (isNameStartCodePoint(c1)) {\n return true;\n } else if (c1 === REVERSE_SOLIDUS && isValidEscape(c1, c2)) {\n return true;\n }\n return false;\n};\n\nconst isNumberStart = (c1: number, c2: number, c3: number): boolean => {\n if (c1 === PLUS_SIGN || c1 === HYPHEN_MINUS) {\n if (isDigit(c2)) {\n return true;\n }\n\n return c2 === FULL_STOP && isDigit(c3);\n }\n\n if (c1 === FULL_STOP) {\n return isDigit(c2);\n }\n\n return isDigit(c1);\n};\n\nconst stringToNumber = (codePoints: number[]): number => {\n let c = 0;\n let sign = 1;\n if (codePoints[c] === PLUS_SIGN || codePoints[c] === HYPHEN_MINUS) {\n if (codePoints[c] === HYPHEN_MINUS) {\n sign = -1;\n }\n c++;\n }\n\n const integers = [];\n\n while (isDigit(codePoints[c])) {\n integers.push(codePoints[c++]);\n }\n\n const int = integers.length ? parseInt(fromCodePoint(...integers), 10) : 0;\n\n if (codePoints[c] === FULL_STOP) {\n c++;\n }\n\n const fraction = [];\n while (isDigit(codePoints[c])) {\n fraction.push(codePoints[c++]);\n }\n\n const fracd = fraction.length;\n const frac = fracd ? parseInt(fromCodePoint(...fraction), 10) : 0;\n\n if (codePoints[c] === E || codePoints[c] === e) {\n c++;\n }\n\n let expsign = 1;\n\n if (codePoints[c] === PLUS_SIGN || codePoints[c] === HYPHEN_MINUS) {\n if (codePoints[c] === HYPHEN_MINUS) {\n expsign = -1;\n }\n c++;\n }\n\n const exponent = [];\n\n while (isDigit(codePoints[c])) {\n exponent.push(codePoints[c++]);\n }\n\n const exp = exponent.length ? parseInt(fromCodePoint(...exponent), 10) : 0;\n\n return sign * (int + frac * Math.pow(10, -fracd)) * Math.pow(10, expsign * exp);\n};\n\nconst LEFT_PARENTHESIS_TOKEN: Token = {\n type: TokenType.LEFT_PARENTHESIS_TOKEN\n};\nconst RIGHT_PARENTHESIS_TOKEN: Token = {\n type: TokenType.RIGHT_PARENTHESIS_TOKEN\n};\nconst COMMA_TOKEN: Token = {type: TokenType.COMMA_TOKEN};\nconst SUFFIX_MATCH_TOKEN: Token = {type: TokenType.SUFFIX_MATCH_TOKEN};\nconst PREFIX_MATCH_TOKEN: Token = {type: TokenType.PREFIX_MATCH_TOKEN};\nconst COLUMN_TOKEN: Token = {type: TokenType.COLUMN_TOKEN};\nconst DASH_MATCH_TOKEN: Token = {type: TokenType.DASH_MATCH_TOKEN};\nconst INCLUDE_MATCH_TOKEN: Token = {type: TokenType.INCLUDE_MATCH_TOKEN};\nconst LEFT_CURLY_BRACKET_TOKEN: Token = {\n type: TokenType.LEFT_CURLY_BRACKET_TOKEN\n};\nconst RIGHT_CURLY_BRACKET_TOKEN: Token = {\n type: TokenType.RIGHT_CURLY_BRACKET_TOKEN\n};\nconst SUBSTRING_MATCH_TOKEN: Token = {type: TokenType.SUBSTRING_MATCH_TOKEN};\nconst BAD_URL_TOKEN: Token = {type: TokenType.BAD_URL_TOKEN};\nconst BAD_STRING_TOKEN: Token = {type: TokenType.BAD_STRING_TOKEN};\nconst CDO_TOKEN: Token = {type: TokenType.CDO_TOKEN};\nconst CDC_TOKEN: Token = {type: TokenType.CDC_TOKEN};\nconst COLON_TOKEN: Token = {type: TokenType.COLON_TOKEN};\nconst SEMICOLON_TOKEN: Token = {type: TokenType.SEMICOLON_TOKEN};\nconst LEFT_SQUARE_BRACKET_TOKEN: Token = {\n type: TokenType.LEFT_SQUARE_BRACKET_TOKEN\n};\nconst RIGHT_SQUARE_BRACKET_TOKEN: Token = {\n type: TokenType.RIGHT_SQUARE_BRACKET_TOKEN\n};\nconst WHITESPACE_TOKEN: Token = {type: TokenType.WHITESPACE_TOKEN};\nexport const EOF_TOKEN: Token = {type: TokenType.EOF_TOKEN};\n\nexport class Tokenizer {\n private _value: number[];\n\n constructor() {\n this._value = [];\n }\n\n write(chunk: string): void {\n this._value = this._value.concat(toCodePoints(chunk));\n }\n\n read(): CSSToken[] {\n const tokens = [];\n let token = this.consumeToken();\n while (token !== EOF_TOKEN) {\n tokens.push(token);\n token = this.consumeToken();\n }\n return tokens;\n }\n\n private consumeToken(): CSSToken {\n const codePoint = this.consumeCodePoint();\n\n switch (codePoint) {\n case QUOTATION_MARK:\n return this.consumeStringToken(QUOTATION_MARK);\n case NUMBER_SIGN:\n const c1 = this.peekCodePoint(0);\n const c2 = this.peekCodePoint(1);\n const c3 = this.peekCodePoint(2);\n if (isNameCodePoint(c1) || isValidEscape(c2, c3)) {\n const flags = isIdentifierStart(c1, c2, c3) ? FLAG_ID : FLAG_UNRESTRICTED;\n const value = this.consumeName();\n\n return {type: TokenType.HASH_TOKEN, value, flags};\n }\n break;\n case DOLLAR_SIGN:\n if (this.peekCodePoint(0) === EQUALS_SIGN) {\n this.consumeCodePoint();\n return SUFFIX_MATCH_TOKEN;\n }\n break;\n case APOSTROPHE:\n return this.consumeStringToken(APOSTROPHE);\n case LEFT_PARENTHESIS:\n return LEFT_PARENTHESIS_TOKEN;\n case RIGHT_PARENTHESIS:\n return RIGHT_PARENTHESIS_TOKEN;\n case ASTERISK:\n if (this.peekCodePoint(0) === EQUALS_SIGN) {\n this.consumeCodePoint();\n return SUBSTRING_MATCH_TOKEN;\n }\n break;\n case PLUS_SIGN:\n if (isNumberStart(codePoint, this.peekCodePoint(0), this.peekCodePoint(1))) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeNumericToken();\n }\n break;\n case COMMA:\n return COMMA_TOKEN;\n case HYPHEN_MINUS:\n const e1 = codePoint;\n const e2 = this.peekCodePoint(0);\n const e3 = this.peekCodePoint(1);\n\n if (isNumberStart(e1, e2, e3)) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeNumericToken();\n }\n\n if (isIdentifierStart(e1, e2, e3)) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeIdentLikeToken();\n }\n\n if (e2 === HYPHEN_MINUS && e3 === GREATER_THAN_SIGN) {\n this.consumeCodePoint();\n this.consumeCodePoint();\n return CDC_TOKEN;\n }\n break;\n\n case FULL_STOP:\n if (isNumberStart(codePoint, this.peekCodePoint(0), this.peekCodePoint(1))) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeNumericToken();\n }\n break;\n case SOLIDUS:\n if (this.peekCodePoint(0) === ASTERISK) {\n this.consumeCodePoint();\n while (true) {\n let c = this.consumeCodePoint();\n if (c === ASTERISK) {\n c = this.consumeCodePoint();\n if (c === SOLIDUS) {\n return this.consumeToken();\n }\n }\n if (c === EOF) {\n return this.consumeToken();\n }\n }\n }\n break;\n case COLON:\n return COLON_TOKEN;\n case SEMICOLON:\n return SEMICOLON_TOKEN;\n case LESS_THAN_SIGN:\n if (\n this.peekCodePoint(0) === EXCLAMATION_MARK &&\n this.peekCodePoint(1) === HYPHEN_MINUS &&\n this.peekCodePoint(2) === HYPHEN_MINUS\n ) {\n this.consumeCodePoint();\n this.consumeCodePoint();\n return CDO_TOKEN;\n }\n break;\n case COMMERCIAL_AT:\n const a1 = this.peekCodePoint(0);\n const a2 = this.peekCodePoint(1);\n const a3 = this.peekCodePoint(2);\n if (isIdentifierStart(a1, a2, a3)) {\n const value = this.consumeName();\n return {type: TokenType.AT_KEYWORD_TOKEN, value};\n }\n break;\n case LEFT_SQUARE_BRACKET:\n return LEFT_SQUARE_BRACKET_TOKEN;\n case REVERSE_SOLIDUS:\n if (isValidEscape(codePoint, this.peekCodePoint(0))) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeIdentLikeToken();\n }\n break;\n case RIGHT_SQUARE_BRACKET:\n return RIGHT_SQUARE_BRACKET_TOKEN;\n case CIRCUMFLEX_ACCENT:\n if (this.peekCodePoint(0) === EQUALS_SIGN) {\n this.consumeCodePoint();\n return PREFIX_MATCH_TOKEN;\n }\n break;\n case LEFT_CURLY_BRACKET:\n return LEFT_CURLY_BRACKET_TOKEN;\n case RIGHT_CURLY_BRACKET:\n return RIGHT_CURLY_BRACKET_TOKEN;\n case u:\n case U:\n const u1 = this.peekCodePoint(0);\n const u2 = this.peekCodePoint(1);\n if (u1 === PLUS_SIGN && (isHex(u2) || u2 === QUESTION_MARK)) {\n this.consumeCodePoint();\n this.consumeUnicodeRangeToken();\n }\n this.reconsumeCodePoint(codePoint);\n return this.consumeIdentLikeToken();\n case VERTICAL_LINE:\n if (this.peekCodePoint(0) === EQUALS_SIGN) {\n this.consumeCodePoint();\n return DASH_MATCH_TOKEN;\n }\n if (this.peekCodePoint(0) === VERTICAL_LINE) {\n this.consumeCodePoint();\n return COLUMN_TOKEN;\n }\n break;\n case TILDE:\n if (this.peekCodePoint(0) === EQUALS_SIGN) {\n this.consumeCodePoint();\n return INCLUDE_MATCH_TOKEN;\n }\n break;\n case EOF:\n return EOF_TOKEN;\n }\n\n if (isWhiteSpace(codePoint)) {\n this.consumeWhiteSpace();\n return WHITESPACE_TOKEN;\n }\n\n if (isDigit(codePoint)) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeNumericToken();\n }\n\n if (isNameStartCodePoint(codePoint)) {\n this.reconsumeCodePoint(codePoint);\n return this.consumeIdentLikeToken();\n }\n\n return {type: TokenType.DELIM_TOKEN, value: fromCodePoint(codePoint)};\n }\n\n private consumeCodePoint(): number {\n const value = this._value.shift();\n\n return typeof value === 'undefined' ? -1 : value;\n }\n\n private reconsumeCodePoint(codePoint: number) {\n this._value.unshift(codePoint);\n }\n\n private peekCodePoint(delta: number): number {\n if (delta >= this._value.length) {\n return -1;\n }\n\n return this._value[delta];\n }\n\n private consumeUnicodeRangeToken(): UnicodeRangeToken {\n const digits = [];\n let codePoint = this.consumeCodePoint();\n while (isHex(codePoint) && digits.length < 6) {\n digits.push(codePoint);\n codePoint = this.consumeCodePoint();\n }\n let questionMarks = false;\n while (codePoint === QUESTION_MARK && digits.length < 6) {\n digits.push(codePoint);\n codePoint = this.consumeCodePoint();\n questionMarks = true;\n }\n\n if (questionMarks) {\n const start = parseInt(\n fromCodePoint(...digits.map((digit) => (digit === QUESTION_MARK ? ZERO : digit))),\n 16\n );\n const end = parseInt(fromCodePoint(...digits.map((digit) => (digit === QUESTION_MARK ? F : digit))), 16);\n return {type: TokenType.UNICODE_RANGE_TOKEN, start, end};\n }\n\n const start = parseInt(fromCodePoint(...digits), 16);\n if (this.peekCodePoint(0) === HYPHEN_MINUS && isHex(this.peekCodePoint(1))) {\n this.consumeCodePoint();\n codePoint = this.consumeCodePoint();\n const endDigits = [];\n while (isHex(codePoint) && endDigits.length < 6) {\n endDigits.push(codePoint);\n codePoint = this.consumeCodePoint();\n }\n const end = parseInt(fromCodePoint(...endDigits), 16);\n\n return {type: TokenType.UNICODE_RANGE_TOKEN, start, end};\n } else {\n return {type: TokenType.UNICODE_RANGE_TOKEN, start, end: start};\n }\n }\n\n private consumeIdentLikeToken(): StringValueToken | Token {\n const value = this.consumeName();\n if (value.toLowerCase() === 'url' && this.peekCodePoint(0) === LEFT_PARENTHESIS) {\n this.consumeCodePoint();\n return this.consumeUrlToken();\n } else if (this.peekCodePoint(0) === LEFT_PARENTHESIS) {\n this.consumeCodePoint();\n return {type: TokenType.FUNCTION_TOKEN, value};\n }\n\n return {type: TokenType.IDENT_TOKEN, value};\n }\n\n private consumeUrlToken(): StringValueToken | Token {\n const value = [];\n this.consumeWhiteSpace();\n\n if (this.peekCodePoint(0) === EOF) {\n return {type: TokenType.URL_TOKEN, value: ''};\n }\n\n const next = this.peekCodePoint(0);\n if (next === APOSTROPHE || next === QUOTATION_MARK) {\n const stringToken = this.consumeStringToken(this.consumeCodePoint());\n if (stringToken.type === TokenType.STRING_TOKEN) {\n this.consumeWhiteSpace();\n\n if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) {\n this.consumeCodePoint();\n return {type: TokenType.URL_TOKEN, value: stringToken.value};\n }\n }\n\n this.consumeBadUrlRemnants();\n return BAD_URL_TOKEN;\n }\n\n while (true) {\n const codePoint = this.consumeCodePoint();\n if (codePoint === EOF || codePoint === RIGHT_PARENTHESIS) {\n return {type: TokenType.URL_TOKEN, value: fromCodePoint(...value)};\n } else if (isWhiteSpace(codePoint)) {\n this.consumeWhiteSpace();\n if (this.peekCodePoint(0) === EOF || this.peekCodePoint(0) === RIGHT_PARENTHESIS) {\n this.consumeCodePoint();\n return {type: TokenType.URL_TOKEN, value: fromCodePoint(...value)};\n }\n this.consumeBadUrlRemnants();\n return BAD_URL_TOKEN;\n } else if (\n codePoint === QUOTATION_MARK ||\n codePoint === APOSTROPHE ||\n codePoint === LEFT_PARENTHESIS ||\n isNonPrintableCodePoint(codePoint)\n ) {\n this.consumeBadUrlRemnants();\n return BAD_URL_TOKEN;\n } else if (codePoint === REVERSE_SOLIDUS) {\n if (isValidEscape(codePoint, this.peekCodePoint(0))) {\n value.push(this.consumeEscapedCodePoint());\n } else {\n this.consumeBadUrlRemnants();\n return BAD_URL_TOKEN;\n }\n } else {\n value.push(codePoint);\n }\n }\n }\n\n private consumeWhiteSpace(): void {\n while (isWhiteSpace(this.peekCodePoint(0))) {\n this.consumeCodePoint();\n }\n }\n\n private consumeBadUrlRemnants(): void {\n while (true) {\n const codePoint = this.consumeCodePoint();\n if (codePoint === RIGHT_PARENTHESIS || codePoint === EOF) {\n return;\n }\n\n if (isValidEscape(codePoint, this.peekCodePoint(0))) {\n this.consumeEscapedCodePoint();\n }\n }\n }\n\n private consumeStringSlice(count: number): string {\n const SLICE_STACK_SIZE = 50000;\n let value = '';\n while (count > 0) {\n const amount = Math.min(SLICE_STACK_SIZE, count);\n value += fromCodePoint(...this._value.splice(0, amount));\n count -= amount;\n }\n this._value.shift();\n\n return value;\n }\n\n private consumeStringToken(endingCodePoint: number): StringValueToken | Token {\n let value = '';\n let i = 0;\n\n do {\n const codePoint = this._value[i];\n if (codePoint === EOF || codePoint === undefined || codePoint === endingCodePoint) {\n value += this.consumeStringSlice(i);\n return {type: TokenType.STRING_TOKEN, value};\n }\n\n if (codePoint === LINE_FEED) {\n this._value.splice(0, i);\n return BAD_STRING_TOKEN;\n }\n\n if (codePoint === REVERSE_SOLIDUS) {\n const next = this._value[i + 1];\n if (next !== EOF && next !== undefined) {\n if (next === LINE_FEED) {\n value += this.consumeStringSlice(i);\n i = -1;\n this._value.shift();\n } else if (isValidEscape(codePoint, next)) {\n value += this.consumeStringSlice(i);\n value += fromCodePoint(this.consumeEscapedCodePoint());\n i = -1;\n }\n }\n }\n\n i++;\n } while (true);\n }\n\n private consumeNumber() {\n const repr = [];\n let type = FLAG_INTEGER;\n let c1 = this.peekCodePoint(0);\n if (c1 === PLUS_SIGN || c1 === HYPHEN_MINUS) {\n repr.push(this.consumeCodePoint());\n }\n\n while (isDigit(this.peekCodePoint(0))) {\n repr.push(this.consumeCodePoint());\n }\n c1 = this.peekCodePoint(0);\n let c2 = this.peekCodePoint(1);\n if (c1 === FULL_STOP && isDigit(c2)) {\n repr.push(this.consumeCodePoint(), this.consumeCodePoint());\n type = FLAG_NUMBER;\n while (isDigit(this.peekCodePoint(0))) {\n repr.push(this.consumeCodePoint());\n }\n }\n\n c1 = this.peekCodePoint(0);\n c2 = this.peekCodePoint(1);\n const c3 = this.peekCodePoint(2);\n if ((c1 === E || c1 === e) && (((c2 === PLUS_SIGN || c2 === HYPHEN_MINUS) && isDigit(c3)) || isDigit(c2))) {\n repr.push(this.consumeCodePoint(), this.consumeCodePoint());\n type = FLAG_NUMBER;\n while (isDigit(this.peekCodePoint(0))) {\n repr.push(this.consumeCodePoint());\n }\n }\n\n return [stringToNumber(repr), type];\n }\n\n private consumeNumericToken(): NumberValueToken | DimensionToken {\n const [number, flags] = this.consumeNumber();\n const c1 = this.peekCodePoint(0);\n const c2 = this.peekCodePoint(1);\n const c3 = this.peekCodePoint(2);\n\n if (isIdentifierStart(c1, c2, c3)) {\n const unit = this.consumeName();\n return {type: TokenType.DIMENSION_TOKEN, number, flags, unit};\n }\n\n if (c1 === PERCENTAGE_SIGN) {\n this.consumeCodePoint();\n return {type: TokenType.PERCENTAGE_TOKEN, number, flags};\n }\n\n return {type: TokenType.NUMBER_TOKEN, number, flags};\n }\n\n private consumeEscapedCodePoint(): number {\n const codePoint = this.consumeCodePoint();\n\n if (isHex(codePoint)) {\n let hex = fromCodePoint(codePoint);\n while (isHex(this.peekCodePoint(0)) && hex.length < 6) {\n hex += fromCodePoint(this.consumeCodePoint());\n }\n\n if (isWhiteSpace(this.peekCodePoint(0))) {\n this.consumeCodePoint();\n }\n\n const hexCodePoint = parseInt(hex, 16);\n\n if (hexCodePoint === 0 || isSurrogateCodePoint(hexCodePoint) || hexCodePoint > 0x10ffff) {\n return REPLACEMENT_CHARACTER;\n }\n\n return hexCodePoint;\n }\n\n if (codePoint === EOF) {\n return REPLACEMENT_CHARACTER;\n }\n\n return codePoint;\n }\n\n private consumeName(): string {\n let result = '';\n while (true) {\n const codePoint = this.consumeCodePoint();\n if (isNameCodePoint(codePoint)) {\n result += fromCodePoint(codePoint);\n } else if (isValidEscape(codePoint, this.peekCodePoint(0))) {\n result += fromCodePoint(this.consumeEscapedCodePoint());\n } else {\n this.reconsumeCodePoint(codePoint);\n return result;\n }\n }\n }\n}\n","import {\n CSSToken,\n DimensionToken,\n EOF_TOKEN,\n NumberValueToken,\n StringValueToken,\n Tokenizer,\n TokenType\n} from './tokenizer';\n\nexport type CSSBlockType =\n | TokenType.LEFT_PARENTHESIS_TOKEN\n | TokenType.LEFT_SQUARE_BRACKET_TOKEN\n | TokenType.LEFT_CURLY_BRACKET_TOKEN;\n\nexport interface CSSBlock {\n type: CSSBlockType;\n values: CSSValue[];\n}\n\nexport interface CSSFunction {\n type: TokenType.FUNCTION;\n name: string;\n values: CSSValue[];\n}\n\nexport type CSSValue = CSSFunction | CSSToken | CSSBlock;\n\nexport class Parser {\n private _tokens: CSSToken[];\n\n constructor(tokens: CSSToken[]) {\n this._tokens = tokens;\n }\n\n static create(value: string): Parser {\n const tokenizer = new Tokenizer();\n tokenizer.write(value);\n return new Parser(tokenizer.read());\n }\n\n static parseValue(value: string): CSSValue {\n return Parser.create(value).parseComponentValue();\n }\n\n static parseValues(value: string): CSSValue[] {\n return Parser.create(value).parseComponentValues();\n }\n\n parseComponentValue(): CSSValue {\n let token = this.consumeToken();\n while (token.type === TokenType.WHITESPACE_TOKEN) {\n token = this.consumeToken();\n }\n\n if (token.type === TokenType.EOF_TOKEN) {\n throw new SyntaxError(`Error parsing CSS component value, unexpected EOF`);\n }\n\n this.reconsumeToken(token);\n const value = this.consumeComponentValue();\n\n do {\n token = this.consumeToken();\n } while (token.type === TokenType.WHITESPACE_TOKEN);\n\n if (token.type === TokenType.EOF_TOKEN) {\n return value;\n }\n\n throw new SyntaxError(`Error parsing CSS component value, multiple values found when expecting only one`);\n }\n\n parseComponentValues(): CSSValue[] {\n const values = [];\n while (true) {\n const value = this.consumeComponentValue();\n if (value.type === TokenType.EOF_TOKEN) {\n return values;\n }\n values.push(value);\n values.push();\n }\n }\n\n private consumeComponentValue(): CSSValue {\n const token = this.consumeToken();\n\n switch (token.type) {\n case TokenType.LEFT_CURLY_BRACKET_TOKEN:\n case TokenType.LEFT_SQUARE_BRACKET_TOKEN:\n case TokenType.LEFT_PARENTHESIS_TOKEN:\n return this.consumeSimpleBlock(token.type);\n case TokenType.FUNCTION_TOKEN:\n return this.consumeFunction(token);\n }\n\n return token;\n }\n\n private consumeSimpleBlock(type: CSSBlockType): CSSBlock {\n const block: CSSBlock = {type, values: []};\n\n let token = this.consumeToken();\n while (true) {\n if (token.type === TokenType.EOF_TOKEN || isEndingTokenFor(token, type)) {\n return block;\n }\n\n this.reconsumeToken(token);\n block.values.push(this.consumeComponentValue());\n token = this.consumeToken();\n }\n }\n\n private consumeFunction(functionToken: StringValueToken): CSSFunction {\n const cssFunction: CSSFunction = {\n name: functionToken.value,\n values: [],\n type: TokenType.FUNCTION\n };\n\n while (true) {\n const token = this.consumeToken();\n if (token.type === TokenType.EOF_TOKEN || token.type === TokenType.RIGHT_PARENTHESIS_TOKEN) {\n return cssFunction;\n }\n\n this.reconsumeToken(token);\n cssFunction.values.push(this.consumeComponentValue());\n }\n }\n\n private consumeToken(): CSSToken {\n const token = this._tokens.shift();\n return typeof token === 'undefined' ? EOF_TOKEN : token;\n }\n\n private reconsumeToken(token: CSSToken): void {\n this._tokens.unshift(token);\n }\n}\n\nexport const isDimensionToken = (token: CSSValue): token is DimensionToken => token.type === TokenType.DIMENSION_TOKEN;\nexport const isNumberToken = (token: CSSValue): token is NumberValueToken => token.type === TokenType.NUMBER_TOKEN;\nexport const isIdentToken = (token: CSSValue): token is StringValueToken => token.type === TokenType.IDENT_TOKEN;\nexport const isStringToken = (token: CSSValue): token is StringValueToken => token.type === TokenType.STRING_TOKEN;\nexport const isIdentWithValue = (token: CSSValue, value: string): boolean =>\n isIdentToken(token) && token.value === value;\n\nexport const nonWhiteSpace = (token: CSSValue): boolean => token.type !== TokenType.WHITESPACE_TOKEN;\nexport const nonFunctionArgSeparator = (token: CSSValue): boolean =>\n token.type !== TokenType.WHITESPACE_TOKEN && token.type !== TokenType.COMMA_TOKEN;\n\nexport const parseFunctionArgs = (tokens: CSSValue[]): CSSValue[][] => {\n const args: CSSValue[][] = [];\n let arg: CSSValue[] = [];\n tokens.forEach((token) => {\n if (token.type === TokenType.COMMA_TOKEN) {\n if (arg.length === 0) {\n throw new Error(`Error parsing function args, zero tokens for arg`);\n }\n args.push(arg);\n arg = [];\n return;\n }\n\n if (token.type !== TokenType.WHITESPACE_TOKEN) {\n arg.push(token);\n }\n });\n if (arg.length) {\n args.push(arg);\n }\n\n return args;\n};\n\nconst isEndingTokenFor = (token: CSSToken, type: CSSBlockType): boolean => {\n if (type === TokenType.LEFT_CURLY_BRACKET_TOKEN && token.type === TokenType.RIGHT_CURLY_BRACKET_TOKEN) {\n return true;\n }\n if (type === TokenType.LEFT_SQUARE_BRACKET_TOKEN && token.type === TokenType.RIGHT_SQUARE_BRACKET_TOKEN) {\n return true;\n }\n\n return type === TokenType.LEFT_PARENTHESIS_TOKEN && token.type === TokenType.RIGHT_PARENTHESIS_TOKEN;\n};\n","import {CSSValue} from '../syntax/parser';\nimport {DimensionToken, NumberValueToken, TokenType} from '../syntax/tokenizer';\n\nexport type Length = DimensionToken | NumberValueToken;\n\nexport const isLength = (token: CSSValue): token is Length =>\n token.type === TokenType.NUMBER_TOKEN || token.type === TokenType.DIMENSION_TOKEN;\n","import {DimensionToken, FLAG_INTEGER, NumberValueToken, TokenType} from '../syntax/tokenizer';\nimport {CSSValue, isDimensionToken} from '../syntax/parser';\nimport {isLength} from './length';\nexport type LengthPercentage = DimensionToken | NumberValueToken;\nexport type LengthPercentageTuple = [LengthPercentage] | [LengthPercentage, LengthPercentage];\n\nexport const isLengthPercentage = (token: CSSValue): token is LengthPercentage =>\n token.type === TokenType.PERCENTAGE_TOKEN || isLength(token);\nexport const parseLengthPercentageTuple = (tokens: LengthPercentage[]): LengthPercentageTuple =>\n tokens.length > 1 ? [tokens[0], tokens[1]] : [tokens[0]];\nexport const ZERO_LENGTH: NumberValueToken = {\n type: TokenType.NUMBER_TOKEN,\n number: 0,\n flags: FLAG_INTEGER\n};\n\nexport const FIFTY_PERCENT: NumberValueToken = {\n type: TokenType.PERCENTAGE_TOKEN,\n number: 50,\n flags: FLAG_INTEGER\n};\n\nexport const HUNDRED_PERCENT: NumberValueToken = {\n type: TokenType.PERCENTAGE_TOKEN,\n number: 100,\n flags: FLAG_INTEGER\n};\n\nexport const getAbsoluteValueForTuple = (\n tuple: LengthPercentageTuple,\n width: number,\n height: number\n): [number, number] => {\n const [x, y] = tuple;\n return [getAbsoluteValue(x, width), getAbsoluteValue(typeof y !== 'undefined' ? y : x, height)];\n};\nexport const getAbsoluteValue = (token: LengthPercentage, parent: number): number => {\n if (token.type === TokenType.PERCENTAGE_TOKEN) {\n return (token.number / 100) * parent;\n }\n\n if (isDimensionToken(token)) {\n switch (token.unit) {\n case 'rem':\n case 'em':\n return 16 * token.number; // TODO use correct font-size\n case 'px':\n default:\n return token.number;\n }\n }\n\n return token.number;\n};\n","import {CSSValue, isIdentToken} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {ITypeDescriptor} from '../ITypeDescriptor';\nimport {HUNDRED_PERCENT, ZERO_LENGTH} from './length-percentage';\nimport {GradientCorner} from './image';\nimport {Context} from '../../core/context';\n\nconst DEG = 'deg';\nconst GRAD = 'grad';\nconst RAD = 'rad';\nconst TURN = 'turn';\n\nexport const angle: ITypeDescriptor<number> = {\n name: 'angle',\n parse: (_context: Context, value: CSSValue): number => {\n if (value.type === TokenType.DIMENSION_TOKEN) {\n switch (value.unit) {\n case DEG:\n return (Math.PI * value.number) / 180;\n case GRAD:\n return (Math.PI / 200) * value.number;\n case RAD:\n return value.number;\n case TURN:\n return Math.PI * 2 * value.number;\n }\n }\n\n throw new Error(`Unsupported angle type`);\n }\n};\n\nexport const isAngle = (value: CSSValue): boolean => {\n if (value.type === TokenType.DIMENSION_TOKEN) {\n if (value.unit === DEG || value.unit === GRAD || value.unit === RAD || value.unit === TURN) {\n return true;\n }\n }\n return false;\n};\n\nexport const parseNamedSide = (tokens: CSSValue[]): number | GradientCorner => {\n const sideOrCorner = tokens\n .filter(isIdentToken)\n .map((ident) => ident.value)\n .join(' ');\n\n switch (sideOrCorner) {\n case 'to bottom right':\n case 'to right bottom':\n case 'left top':\n case 'top left':\n return [ZERO_LENGTH, ZERO_LENGTH];\n case 'to top':\n case 'bottom':\n return deg(0);\n case 'to bottom left':\n case 'to left bottom':\n case 'right top':\n case 'top right':\n return [ZERO_LENGTH, HUNDRED_PERCENT];\n case 'to right':\n case 'left':\n return deg(90);\n case 'to top left':\n case 'to left top':\n case 'right bottom':\n case 'bottom right':\n return [HUNDRED_PERCENT, HUNDRED_PERCENT];\n case 'to bottom':\n case 'top':\n return deg(180);\n case 'to top right':\n case 'to right top':\n case 'left bottom':\n case 'bottom left':\n return [HUNDRED_PERCENT, ZERO_LENGTH];\n case 'to left':\n case 'right':\n return deg(270);\n }\n\n return 0;\n};\n\nexport const deg = (deg: number): number => (Math.PI * deg) / 180;\n","import {CSSValue, nonFunctionArgSeparator, Parser} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {ITypeDescriptor} from '../ITypeDescriptor';\nimport {angle, deg} from './angle';\nimport {getAbsoluteValue, isLengthPercentage} from './length-percentage';\nimport {Context} from '../../core/context';\nexport type Color = number;\n\nexport const color: ITypeDescriptor<Color> = {\n name: 'color',\n parse: (context: Context, value: CSSValue): Color => {\n if (value.type === TokenType.FUNCTION) {\n const colorFunction = SUPPORTED_COLOR_FUNCTIONS[value.name];\n if (typeof colorFunction === 'undefined') {\n throw new Error(`Attempting to parse an unsupported color function \"${value.name}\"`);\n }\n return colorFunction(context, value.values);\n }\n\n if (value.type === TokenType.HASH_TOKEN) {\n if (value.value.length === 3) {\n const r = value.value.substring(0, 1);\n const g = value.value.substring(1, 2);\n const b = value.value.substring(2, 3);\n return pack(parseInt(r + r, 16), parseInt(g + g, 16), parseInt(b + b, 16), 1);\n }\n\n if (value.value.length === 4) {\n const r = value.value.substring(0, 1);\n const g = value.value.substring(1, 2);\n const b = value.value.substring(2, 3);\n const a = value.value.substring(3, 4);\n return pack(parseInt(r + r, 16), parseInt(g + g, 16), parseInt(b + b, 16), parseInt(a + a, 16) / 255);\n }\n\n if (value.value.length === 6) {\n const r = value.value.substring(0, 2);\n const g = value.value.substring(2, 4);\n const b = value.value.substring(4, 6);\n return pack(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1);\n }\n\n if (value.value.length === 8) {\n const r = value.value.substring(0, 2);\n const g = value.value.substring(2, 4);\n const b = value.value.substring(4, 6);\n const a = value.value.substring(6, 8);\n return pack(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), parseInt(a, 16) / 255);\n }\n }\n\n if (value.type === TokenType.IDENT_TOKEN) {\n const namedColor = COLORS[value.value.toUpperCase()];\n if (typeof namedColor !== 'undefined') {\n return namedColor;\n }\n }\n\n return COLORS.TRANSPARENT;\n }\n};\n\nexport const isTransparent = (color: Color): boolean => (0xff & color) === 0;\n\nexport const asString = (color: Color): string => {\n const alpha = 0xff & color;\n const blue = 0xff & (color >> 8);\n const green = 0xff & (color >> 16);\n const red = 0xff & (color >> 24);\n return alpha < 255 ? `rgba(${red},${green},${blue},${alpha / 255})` : `rgb(${red},${green},${blue})`;\n};\n\nexport const pack = (r: number, g: number, b: number, a: number): Color =>\n ((r << 24) | (g << 16) | (b << 8) | (Math.round(a * 255) << 0)) >>> 0;\n\nconst getTokenColorValue = (token: CSSValue, i: number): number => {\n if (token.type === TokenType.NUMBER_TOKEN) {\n return token.number;\n }\n\n if (token.type === TokenType.PERCENTAGE_TOKEN) {\n const max = i === 3 ? 1 : 255;\n return i === 3 ? (token.number / 100) * max : Math.round((token.number / 100) * max);\n }\n\n return 0;\n};\n\nconst rgb = (_context: Context, args: CSSValue[]): number => {\n const tokens = args.filter(nonFunctionArgSeparator);\n\n if (tokens.length === 3) {\n const [r, g, b] = tokens.map(getTokenColorValue);\n return pack(r, g, b, 1);\n }\n\n if (tokens.length === 4) {\n const [r, g, b, a] = tokens.map(getTokenColorValue);\n return pack(r, g, b, a);\n }\n\n return 0;\n};\n\nfunction hue2rgb(t1: number, t2: number, hue: number): number {\n if (hue < 0) {\n hue += 1;\n }\n if (hue >= 1) {\n hue -= 1;\n }\n\n if (hue < 1 / 6) {\n return (t2 - t1) * hue * 6 + t1;\n } else if (hue < 1 / 2) {\n return t2;\n } else if (hue < 2 / 3) {\n return (t2 - t1) * 6 * (2 / 3 - hue) + t1;\n } else {\n return t1;\n }\n}\n\nconst hsl = (context: Context, args: CSSValue[]): number => {\n const tokens = args.filter(nonFunctionArgSeparator);\n const [hue, saturation, lightness, alpha] = tokens;\n\n const h = (hue.type === TokenType.NUMBER_TOKEN ? deg(hue.number) : angle.parse(context, hue)) / (Math.PI * 2);\n const s = isLengthPercentage(saturation) ? saturation.number / 100 : 0;\n const l = isLengthPercentage(lightness) ? lightness.number / 100 : 0;\n const a = typeof alpha !== 'undefined' && isLengthPercentage(alpha) ? getAbsoluteValue(alpha, 1) : 1;\n\n if (s === 0) {\n return pack(l * 255, l * 255, l * 255, 1);\n }\n\n const t2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;\n\n const t1 = l * 2 - t2;\n const r = hue2rgb(t1, t2, h + 1 / 3);\n const g = hue2rgb(t1, t2, h);\n const b = hue2rgb(t1, t2, h - 1 / 3);\n return pack(r * 255, g * 255, b * 255, a);\n};\n\nconst SUPPORTED_COLOR_FUNCTIONS: {\n [key: string]: (context: Context, args: CSSValue[]) => number;\n} = {\n hsl: hsl,\n hsla: hsl,\n rgb: rgb,\n rgba: rgb\n};\n\nexport const parseColor = (context: Context, value: string): Color =>\n color.parse(context, Parser.create(value).parseComponentValue());\n\nexport const COLORS: {[key: string]: Color} = {\n ALICEBLUE: 0xf0f8ffff,\n ANTIQUEWHITE: 0xfaebd7ff,\n AQUA: 0x00ffffff,\n AQUAMARINE: 0x7fffd4ff,\n AZURE: 0xf0ffffff,\n BEIGE: 0xf5f5dcff,\n BISQUE: 0xffe4c4ff,\n BLACK: 0x000000ff,\n BLANCHEDALMOND: 0xffebcdff,\n BLUE: 0x0000ffff,\n BLUEVIOLET: 0x8a2be2ff,\n BROWN: 0xa52a2aff,\n BURLYWOOD: 0xdeb887ff,\n CADETBLUE: 0x5f9ea0ff,\n CHARTREUSE: 0x7fff00ff,\n CHOCOLATE: 0xd2691eff,\n CORAL: 0xff7f50ff,\n CORNFLOWERBLUE: 0x6495edff,\n CORNSILK: 0xfff8dcff,\n CRIMSON: 0xdc143cff,\n CYAN: 0x00ffffff,\n DARKBLUE: 0x00008bff,\n DARKCYAN: 0x008b8bff,\n DARKGOLDENROD: 0xb886bbff,\n DARKGRAY: 0xa9a9a9ff,\n DARKGREEN: 0x006400ff,\n DARKGREY: 0xa9a9a9ff,\n DARKKHAKI: 0xbdb76bff,\n DARKMAGENTA: 0x8b008bff,\n DARKOLIVEGREEN: 0x556b2fff,\n DARKORANGE: 0xff8c00ff,\n DARKORCHID: 0x9932ccff,\n DARKRED: 0x8b0000ff,\n DARKSALMON: 0xe9967aff,\n DARKSEAGREEN: 0x8fbc8fff,\n DARKSLATEBLUE: 0x483d8bff,\n DARKSLATEGRAY: 0x2f4f4fff,\n DARKSLATEGREY: 0x2f4f4fff,\n DARKTURQUOISE: 0x00ced1ff,\n DARKVIOLET: 0x9400d3ff,\n DEEPPINK: 0xff1493ff,\n DEEPSKYBLUE: 0x00bfffff,\n DIMGRAY: 0x696969ff,\n DIMGREY: 0x696969ff,\n DODGERBLUE: 0x1e90ffff,\n FIREBRICK: 0xb22222ff,\n FLORALWHITE: 0xfffaf0ff,\n FORESTGREEN: 0x228b22ff,\n FUCHSIA: 0xff00ffff,\n GAINSBORO: 0xdcdcdcff,\n GHOSTWHITE: 0xf8f8ffff,\n GOLD: 0xffd700ff,\n GOLDENROD: 0xdaa520ff,\n GRAY: 0x808080ff,\n GREEN: 0x008000ff,\n GREENYELLOW: 0xadff2fff,\n GREY: 0x808080ff,\n HONEYDEW: 0xf0fff0ff,\n HOTPINK: 0xff69b4ff,\n INDIANRED: 0xcd5c5cff,\n INDIGO: 0x4b0082ff,\n IVORY: 0xfffff0ff,\n KHAKI: 0xf0e68cff,\n LAVENDER: 0xe6e6faff,\n LAVENDERBLUSH: 0xfff0f5ff,\n LAWNGREEN: 0x7cfc00ff,\n LEMONCHIFFON: 0xfffacdff,\n LIGHTBLUE: 0xadd8e6ff,\n LIGHTCORAL: 0xf08080ff,\n LIGHTCYAN: 0xe0ffffff,\n LIGHTGOLDENRODYELLOW: 0xfafad2ff,\n LIGHTGRAY: 0xd3d3d3ff,\n LIGHTGREEN: 0x90ee90ff,\n LIGHTGREY: 0xd3d3d3ff,\n LIGHTPINK: 0xffb6c1ff,\n LIGHTSALMON: 0xffa07aff,\n LIGHTSEAGREEN: 0x20b2aaff,\n LIGHTSKYBLUE: 0x87cefaff,\n LIGHTSLATEGRAY: 0x778899ff,\n LIGHTSLATEGREY: 0x778899ff,\n LIGHTSTEELBLUE: 0xb0c4deff,\n LIGHTYELLOW: 0xffffe0ff,\n LIME: 0x00ff00ff,\n LIMEGREEN: 0x32cd32ff,\n LINEN: 0xfaf0e6ff,\n MAGENTA: 0xff00ffff,\n MAROON: 0x800000ff,\n MEDIUMAQUAMARINE: 0x66cdaaff,\n MEDIUMBLUE: 0x0000cdff,\n MEDIUMORCHID: 0xba55d3ff,\n MEDIUMPURPLE: 0x9370dbff,\n MEDIUMSEAGREEN: 0x3cb371ff,\n MEDIUMSLATEBLUE: 0x7b68eeff,\n MEDIUMSPRINGGREEN: 0x00fa9aff,\n MEDIUMTURQUOISE: 0x48d1ccff,\n MEDIUMVIOLETRED: 0xc71585ff,\n MIDNIGHTBLUE: 0x191970ff,\n MINTCREAM: 0xf5fffaff,\n MISTYROSE: 0xffe4e1ff,\n MOCCASIN: 0xffe4b5ff,\n NAVAJOWHITE: 0xffdeadff,\n NAVY: 0x000080ff,\n OLDLACE: 0xfdf5e6ff,\n OLIVE: 0x808000ff,\n OLIVEDRAB: 0x6b8e23ff,\n ORANGE: 0xffa500ff,\n ORANGERED: 0xff4500ff,\n ORCHID: 0xda70d6ff,\n PALEGOLDENROD: 0xeee8aaff,\n PALEGREEN: 0x98fb98ff,\n PALETURQUOISE: 0xafeeeeff,\n PALEVIOLETRED: 0xdb7093ff,\n PAPAYAWHIP: 0xffefd5ff,\n PEACHPUFF: 0xffdab9ff,\n PERU: 0xcd853fff,\n PINK: 0xffc0cbff,\n PLUM: 0xdda0ddff,\n POWDERBLUE: 0xb0e0e6ff,\n PURPLE: 0x800080ff,\n REBECCAPURPLE: 0x663399ff,\n RED: 0xff0000ff,\n ROSYBROWN: 0xbc8f8fff,\n ROYALBLUE: 0x4169e1ff,\n SADDLEBROWN: 0x8b4513ff,\n SALMON: 0xfa8072ff,\n SANDYBROWN: 0xf4a460ff,\n SEAGREEN: 0x2e8b57ff,\n SEASHELL: 0xfff5eeff,\n SIENNA: 0xa0522dff,\n SILVER: 0xc0c0c0ff,\n SKYBLUE: 0x87ceebff,\n SLATEBLUE: 0x6a5acdff,\n SLATEGRAY: 0x708090ff,\n SLATEGREY: 0x708090ff,\n SNOW: 0xfffafaff,\n SPRINGGREEN: 0x00ff7fff,\n STEELBLUE: 0x4682b4ff,\n TAN: 0xd2b48cff,\n TEAL: 0x008080ff,\n THISTLE: 0xd8bfd8ff,\n TOMATO: 0xff6347ff,\n TRANSPARENT: 0x00000000,\n TURQUOISE: 0x40e0d0ff,\n VIOLET: 0xee82eeff,\n WHEAT: 0xf5deb3ff,\n WHITE: 0xffffffff,\n WHITESMOKE: 0xf5f5f5ff,\n YELLOW: 0xffff00ff,\n YELLOWGREEN: 0x9acd32ff\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const enum BACKGROUND_CLIP {\n BORDER_BOX = 0,\n PADDING_BOX = 1,\n CONTENT_BOX = 2\n}\n\nexport type BackgroundClip = BACKGROUND_CLIP[];\n\nexport const backgroundClip: IPropertyListDescriptor<BackgroundClip> = {\n name: 'background-clip',\n initialValue: 'border-box',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): BackgroundClip => {\n return tokens.map((token) => {\n if (isIdentToken(token)) {\n switch (token.value) {\n case 'padding-box':\n return BACKGROUND_CLIP.PADDING_BOX;\n case 'content-box':\n return BACKGROUND_CLIP.CONTENT_BOX;\n }\n }\n return BACKGROUND_CLIP.BORDER_BOX;\n });\n }\n};\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nexport const backgroundColor: IPropertyTypeValueDescriptor = {\n name: `background-color`,\n initialValue: 'transparent',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'color'\n};\n","import {CSSValue} from '../../syntax/parser';\nimport {\n CSSRadialExtent,\n CSSRadialGradientImage,\n CSSRadialShape,\n GradientColorStop,\n GradientCorner,\n UnprocessedGradientColorStop\n} from '../image';\nimport {color as colorType} from '../color';\nimport {getAbsoluteValue, HUNDRED_PERCENT, isLengthPercentage, ZERO_LENGTH} from '../length-percentage';\nimport {Context} from '../../../core/context';\n\nexport const parseColorStop = (context: Context, args: CSSValue[]): UnprocessedGradientColorStop => {\n const color = colorType.parse(context, args[0]);\n const stop = args[1];\n return stop && isLengthPercentage(stop) ? {color, stop} : {color, stop: null};\n};\n\nexport const processColorStops = (stops: UnprocessedGradientColorStop[], lineLength: number): GradientColorStop[] => {\n const first = stops[0];\n const last = stops[stops.length - 1];\n if (first.stop === null) {\n first.stop = ZERO_LENGTH;\n }\n\n if (last.stop === null) {\n last.stop = HUNDRED_PERCENT;\n }\n\n const processStops: (number | null)[] = [];\n let previous = 0;\n for (let i = 0; i < stops.length; i++) {\n const stop = stops[i].stop;\n if (stop !== null) {\n const absoluteValue = getAbsoluteValue(stop, lineLength);\n if (absoluteValue > previous) {\n processStops.push(absoluteValue);\n } else {\n processStops.push(previous);\n }\n previous = absoluteValue;\n } else {\n processStops.push(null);\n }\n }\n\n let gapBegin = null;\n for (let i = 0; i < processStops.length; i++) {\n const stop = processStops[i];\n if (stop === null) {\n if (gapBegin === null) {\n gapBegin = i;\n }\n } else if (gapBegin !== null) {\n const gapLength = i - gapBegin;\n const beforeGap = processStops[gapBegin - 1] as number;\n const gapValue = (stop - beforeGap) / (gapLength + 1);\n for (let g = 1; g <= gapLength; g++) {\n processStops[gapBegin + g - 1] = gapValue * g;\n }\n gapBegin = null;\n }\n }\n\n return stops.map(({color}, i) => {\n return {color, stop: Math.max(Math.min(1, (processStops[i] as number) / lineLength), 0)};\n });\n};\n\nconst getAngleFromCorner = (corner: GradientCorner, width: number, height: number): number => {\n const centerX = width / 2;\n const centerY = height / 2;\n const x = getAbsoluteValue(corner[0], width) - centerX;\n const y = centerY - getAbsoluteValue(corner[1], height);\n\n return (Math.atan2(y, x) + Math.PI * 2) % (Math.PI * 2);\n};\n\nexport const calculateGradientDirection = (\n angle: number | GradientCorner,\n width: number,\n height: number\n): [number, number, number, number, number] => {\n const radian = typeof angle === 'number' ? angle : getAngleFromCorner(angle, width, height);\n\n const lineLength = Math.abs(width * Math.sin(radian)) + Math.abs(height * Math.cos(radian));\n\n const halfWidth = width / 2;\n const halfHeight = height / 2;\n const halfLineLength = lineLength / 2;\n\n const yDiff = Math.sin(radian - Math.PI / 2) * halfLineLength;\n const xDiff = Math.cos(radian - Math.PI / 2) * halfLineLength;\n\n return [lineLength, halfWidth - xDiff, halfWidth + xDiff, halfHeight - yDiff, halfHeight + yDiff];\n};\n\nconst distance = (a: number, b: number): number => Math.sqrt(a * a + b * b);\n\nconst findCorner = (width: number, height: number, x: number, y: number, closest: boolean): [number, number] => {\n const corners = [\n [0, 0],\n [0, height],\n [width, 0],\n [width, height]\n ];\n\n return corners.reduce(\n (stat, corner) => {\n const [cx, cy] = corner;\n const d = distance(x - cx, y - cy);\n if (closest ? d < stat.optimumDistance : d > stat.optimumDistance) {\n return {\n optimumCorner: corner,\n optimumDistance: d\n };\n }\n\n return stat;\n },\n {\n optimumDistance: closest ? Infinity : -Infinity,\n optimumCorner: null\n }\n ).optimumCorner as [number, number];\n};\n\nexport const calculateRadius = (\n gradient: CSSRadialGradientImage,\n x: number,\n y: number,\n width: number,\n height: number\n): [number, number] => {\n let rx = 0;\n let ry = 0;\n\n switch (gradient.size) {\n case CSSRadialExtent.CLOSEST_SIDE:\n // The ending shape is sized so that that it exactly meets the side of the gradient box closest to the gradient’s center.\n // If the shape is an ellipse, it exactly meets the closest side in each dimension.\n if (gradient.shape === CSSRadialShape.CIRCLE) {\n rx = ry = Math.min(Math.abs(x), Math.abs(x - width), Math.abs(y), Math.abs(y - height));\n } else if (gradient.shape === CSSRadialShape.ELLIPSE) {\n rx = Math.min(Math.abs(x), Math.abs(x - width));\n ry = Math.min(Math.abs(y), Math.abs(y - height));\n }\n break;\n\n case CSSRadialExtent.CLOSEST_CORNER:\n // The ending shape is sized so that that it passes through the corner of the gradient box closest to the gradient’s center.\n // If the shape is an ellipse, the ending shape is given the same aspect-ratio it would have if closest-side were specified.\n if (gradient.shape === CSSRadialShape.CIRCLE) {\n rx = ry = Math.min(\n distance(x, y),\n distance(x, y - height),\n distance(x - width, y),\n distance(x - width, y - height)\n );\n } else if (gradient.shape === CSSRadialShape.ELLIPSE) {\n // Compute the ratio ry/rx (which is to be the same as for \"closest-side\")\n const c = Math.min(Math.abs(y), Math.abs(y - height)) / Math.min(Math.abs(x), Math.abs(x - width));\n const [cx, cy] = findCorner(width, height, x, y, true);\n rx = distance(cx - x, (cy - y) / c);\n ry = c * rx;\n }\n break;\n\n case CSSRadialExtent.FARTHEST_SIDE:\n // Same as closest-side, except the ending shape is sized based on the farthest side(s)\n if (gradient.shape === CSSRadialShape.CIRCLE) {\n rx = ry = Math.max(Math.abs(x), Math.abs(x - width), Math.abs(y), Math.abs(y - height));\n } else if (gradient.shape === CSSRadialShape.ELLIPSE) {\n rx = Math.max(Math.abs(x), Math.abs(x - width));\n ry = Math.max(Math.abs(y), Math.abs(y - height));\n }\n break;\n\n case CSSRadialExtent.FARTHEST_CORNER:\n // Same as closest-corner, except the ending shape is sized based on the farthest corner.\n // If the shape is an ellipse, the ending shape is given the same aspect ratio it would have if farthest-side were specified.\n if (gradient.shape === CSSRadialShape.CIRCLE) {\n rx = ry = Math.max(\n distance(x, y),\n distance(x, y - height),\n distance(x - width, y),\n distance(x - width, y - height)\n );\n } else if (gradient.shape === CSSRadialShape.ELLIPSE) {\n // Compute the ratio ry/rx (which is to be the same as for \"farthest-side\")\n const c = Math.max(Math.abs(y), Math.abs(y - height)) / Math.max(Math.abs(x), Math.abs(x - width));\n const [cx, cy] = findCorner(width, height, x, y, false);\n rx = distance(cx - x, (cy - y) / c);\n ry = c * rx;\n }\n break;\n }\n\n if (Array.isArray(gradient.size)) {\n rx = getAbsoluteValue(gradient.size[0], width);\n ry = gradient.size.length === 2 ? getAbsoluteValue(gradient.size[1], height) : rx;\n }\n\n return [rx, ry];\n};\n","import {CSSValue, parseFunctionArgs} from '../../syntax/parser';\nimport {TokenType} from '../../syntax/tokenizer';\nimport {isAngle, angle as angleType, parseNamedSide, deg} from '../angle';\nimport {CSSImageType, CSSLinearGradientImage, GradientCorner, UnprocessedGradientColorStop} from '../image';\nimport {parseColorStop} from './gradient';\nimport {Context} from '../../../core/context';\n\nexport const linearGradient = (context: Context, tokens: CSSValue[]): CSSLinearGradientImage => {\n let angle: number | GradientCorner = deg(180);\n const stops: UnprocessedGradientColorStop[] = [];\n\n parseFunctionArgs(tokens).forEach((arg, i) => {\n if (i === 0) {\n const firstToken = arg[0];\n if (firstToken.type === TokenType.IDENT_TOKEN && firstToken.value === 'to') {\n angle = parseNamedSide(arg);\n return;\n } else if (isAngle(firstToken)) {\n angle = angleType.parse(context, firstToken);\n return;\n }\n }\n const colorStop = parseColorStop(context, arg);\n stops.push(colorStop);\n });\n\n return {angle, stops, type: CSSImageType.LINEAR_GRADIENT};\n};\n","import {CSSValue, parseFunctionArgs} from '../../syntax/parser';\nimport {CSSImageType, CSSLinearGradientImage, GradientCorner, UnprocessedGradientColorStop} from '../image';\nimport {TokenType} from '../../syntax/tokenizer';\nimport {isAngle, angle as angleType, parseNamedSide, deg} from '../angle';\nimport {parseColorStop} from './gradient';\nimport {Context} from '../../../core/context';\n\nexport const prefixLinearGradient = (context: Context, tokens: CSSValue[]): CSSLinearGradientImage => {\n let angle: number | GradientCorner = deg(180);\n const stops: UnprocessedGradientColorStop[] = [];\n\n parseFunctionArgs(tokens).forEach((arg, i) => {\n if (i === 0) {\n const firstToken = arg[0];\n if (\n firstToken.type === TokenType.IDENT_TOKEN &&\n ['top', 'left', 'right', 'bottom'].indexOf(firstToken.value) !== -1\n ) {\n angle = parseNamedSide(arg);\n return;\n } else if (isAngle(firstToken)) {\n angle = (angleType.parse(context, firstToken) + deg(270)) % deg(360);\n return;\n }\n }\n const colorStop = parseColorStop(context, arg);\n stops.push(colorStop);\n });\n\n return {\n angle,\n stops,\n type: CSSImageType.LINEAR_GRADIENT\n };\n};\n","import {CSSValue, isIdentToken, isNumberToken, nonFunctionArgSeparator, parseFunctionArgs} from '../../syntax/parser';\nimport {\n CSSImageType,\n CSSLinearGradientImage,\n CSSRadialExtent,\n CSSRadialGradientImage,\n CSSRadialShape,\n CSSRadialSize,\n UnprocessedGradientColorStop\n} from '../image';\nimport {deg} from '../angle';\nimport {TokenType} from '../../syntax/tokenizer';\nimport {color as colorType} from '../color';\nimport {HUNDRED_PERCENT, LengthPercentage, ZERO_LENGTH} from '../length-percentage';\nimport {Context} from '../../../core/context';\n\nexport const webkitGradient = (\n context: Context,\n tokens: CSSValue[]\n): CSSLinearGradientImage | CSSRadialGradientImage => {\n const angle = deg(180);\n const stops: UnprocessedGradientColorStop[] = [];\n let type = CSSImageType.LINEAR_GRADIENT;\n const shape: CSSRadialShape = CSSRadialShape.CIRCLE;\n const size: CSSRadialSize = CSSRadialExtent.FARTHEST_CORNER;\n const position: LengthPercentage[] = [];\n parseFunctionArgs(tokens).forEach((arg, i) => {\n const firstToken = arg[0];\n if (i === 0) {\n if (isIdentToken(firstToken) && firstToken.value === 'linear') {\n type = CSSImageType.LINEAR_GRADIENT;\n return;\n } else if (isIdentToken(firstToken) && firstToken.value === 'radial') {\n type = CSSImageType.RADIAL_GRADIENT;\n return;\n }\n }\n\n if (firstToken.type === TokenType.FUNCTION) {\n if (firstToken.name === 'from') {\n const color = colorType.parse(context, firstToken.values[0]);\n stops.push({stop: ZERO_LENGTH, color});\n } else if (firstToken.name === 'to') {\n const color = colorType.parse(context, firstToken.values[0]);\n stops.push({stop: HUNDRED_PERCENT, color});\n } else if (firstToken.name === 'color-stop') {\n const values = firstToken.values.filter(nonFunctionArgSeparator);\n if (values.length === 2) {\n const color = colorType.parse(context, values[1]);\n const stop = values[0];\n if (isNumberToken(stop)) {\n stops.push({\n stop: {type: TokenType.PERCENTAGE_TOKEN, number: stop.number * 100, flags: stop.flags},\n color\n });\n }\n }\n }\n }\n });\n\n return type === CSSImageType.LINEAR_GRADIENT\n ? {\n angle: (angle + deg(180)) % deg(360),\n stops,\n type\n }\n : {size, shape, stops, position, type};\n};\n","import {CSSValue, isIdentToken, parseFunctionArgs} from '../../syntax/parser';\nimport {\n CSSImageType,\n CSSRadialExtent,\n CSSRadialGradientImage,\n CSSRadialShape,\n CSSRadialSize,\n UnprocessedGradientColorStop\n} from '../image';\nimport {parseColorStop} from './gradient';\nimport {FIFTY_PERCENT, HUNDRED_PERCENT, isLengthPercentage, LengthPercentage, ZERO_LENGTH} from '../length-percentage';\nimport {isLength} from '../length';\nimport {Context} from '../../../core/context';\nexport const CLOSEST_SIDE = 'closest-side';\nexport const FARTHEST_SIDE = 'farthest-side';\nexport const CLOSEST_CORNER = 'closest-corner';\nexport const FARTHEST_CORNER = 'farthest-corner';\nexport const CIRCLE = 'circle';\nexport const ELLIPSE = 'ellipse';\nexport const COVER = 'cover';\nexport const CONTAIN = 'contain';\n\nexport const radialGradient = (context: Context, tokens: CSSValue[]): CSSRadialGradientImage => {\n let shape: CSSRadialShape = CSSRadialShape.CIRCLE;\n let size: CSSRadialSize = CSSRadialExtent.FARTHEST_CORNER;\n const stops: UnprocessedGradientColorStop[] = [];\n const position: LengthPercentage[] = [];\n parseFunctionArgs(tokens).forEach((arg, i) => {\n let isColorStop = true;\n if (i === 0) {\n let isAtPosition = false;\n isColorStop = arg.reduce((acc, token) => {\n if (isAtPosition) {\n if (isIdentToken(token)) {\n switch (token.value) {\n case 'center':\n position.push(FIFTY_PERCENT);\n return acc;\n case 'top':\n case 'left':\n position.push(ZERO_LENGTH);\n return acc;\n case 'right':\n case 'bottom':\n position.push(HUNDRED_PERCENT);\n return acc;\n }\n } else if (isLengthPercentage(token) || isLength(token)) {\n position.push(token);\n }\n } else if (isIdentToken(token)) {\n switch (token.value) {\n case CIRCLE:\n shape = CSSRadialShape.CIRCLE;\n return false;\n case ELLIPSE:\n shape = CSSRadialShape.ELLIPSE;\n return false;\n case 'at':\n isAtPosition = true;\n return false;\n case CLOSEST_SIDE:\n size = CSSRadialExtent.CLOSEST_SIDE;\n return false;\n case COVER:\n case FARTHEST_SIDE:\n size = CSSRadialExtent.FARTHEST_SIDE;\n return false;\n case CONTAIN:\n case CLOSEST_CORNER:\n size = CSSRadialExtent.CLOSEST_CORNER;\n return false;\n case FARTHEST_CORNER:\n size = CSSRadialExtent.FARTHEST_CORNER;\n return false;\n }\n } else if (isLength(token) || isLengthPercentage(token)) {\n if (!Array.isArray(size)) {\n size = [];\n }\n size.push(token);\n return false;\n }\n return acc;\n }, isColorStop);\n }\n\n if (isColorStop) {\n const colorStop = parseColorStop(context, arg);\n stops.push(colorStop);\n }\n });\n\n return {size, shape, stops, position, type: CSSImageType.RADIAL_GRADIENT};\n};\n","import {CSSValue, isIdentToken, parseFunctionArgs} from '../../syntax/parser';\nimport {\n CSSImageType,\n CSSRadialExtent,\n CSSRadialGradientImage,\n CSSRadialShape,\n CSSRadialSize,\n UnprocessedGradientColorStop\n} from '../image';\nimport {parseColorStop} from './gradient';\nimport {FIFTY_PERCENT, HUNDRED_PERCENT, isLengthPercentage, LengthPercentage, ZERO_LENGTH} from '../length-percentage';\nimport {isLength} from '../length';\nimport {\n CIRCLE,\n CLOSEST_CORNER,\n CLOSEST_SIDE,\n CONTAIN,\n COVER,\n ELLIPSE,\n FARTHEST_CORNER,\n FARTHEST_SIDE\n} from './radial-gradient';\nimport {Context} from '../../../core/context';\n\nexport const prefixRadialGradient = (context: Context, tokens: CSSValue[]): CSSRadialGradientImage => {\n let shape: CSSRadialShape = CSSRadialShape.CIRCLE;\n let size: CSSRadialSize = CSSRadialExtent.FARTHEST_CORNER;\n const stops: UnprocessedGradientColorStop[] = [];\n const position: LengthPercentage[] = [];\n\n parseFunctionArgs(tokens).forEach((arg, i) => {\n let isColorStop = true;\n if (i === 0) {\n isColorStop = arg.reduce((acc, token) => {\n if (isIdentToken(token)) {\n switch (token.value) {\n case 'center':\n position.push(FIFTY_PERCENT);\n return false;\n case 'top':\n case 'left':\n position.push(ZERO_LENGTH);\n return false;\n case 'right':\n case 'bottom':\n position.push(HUNDRED_PERCENT);\n return false;\n }\n } else if (isLengthPercentage(token) || isLength(token)) {\n position.push(token);\n return false;\n }\n\n return acc;\n }, isColorStop);\n } else if (i === 1) {\n isColorStop = arg.reduce((acc, token) => {\n if (isIdentToken(token)) {\n switch (token.value) {\n case CIRCLE:\n shape = CSSRadialShape.CIRCLE;\n return false;\n case ELLIPSE:\n shape = CSSRadialShape.ELLIPSE;\n return false;\n case CONTAIN:\n case CLOSEST_SIDE:\n size = CSSRadialExtent.CLOSEST_SIDE;\n return false;\n case FARTHEST_SIDE:\n size = CSSRadialExtent.FARTHEST_SIDE;\n return false;\n case CLOSEST_CORNER:\n size = CSSRadialExtent.CLOSEST_CORNER;\n return false;\n case COVER:\n case FARTHEST_CORNER:\n size = CSSRadialExtent.FARTHEST_CORNER;\n return false;\n }\n } else if (isLength(token) || isLengthPercentage(token)) {\n if (!Array.isArray(size)) {\n size = [];\n }\n size.push(token);\n return false;\n }\n\n return acc;\n }, isColorStop);\n }\n\n if (isColorStop) {\n const colorStop = parseColorStop(context, arg);\n stops.push(colorStop);\n }\n });\n\n return {size, shape, stops, position, type: CSSImageType.RADIAL_GRADIENT};\n};\n","import {CSSValue} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Color} from './color';\nimport {linearGradient} from './functions/linear-gradient';\nimport {prefixLinearGradient} from './functions/-prefix-linear-gradient';\nimport {ITypeDescriptor} from '../ITypeDescriptor';\nimport {LengthPercentage} from './length-percentage';\nimport {webkitGradient} from './functions/-webkit-gradient';\nimport {radialGradient} from './functions/radial-gradient';\nimport {prefixRadialGradient} from './functions/-prefix-radial-gradient';\nimport {Context} from '../../core/context';\n\nexport const enum CSSImageType {\n URL,\n LINEAR_GRADIENT,\n RADIAL_GRADIENT\n}\n\nexport const isLinearGradient = (background: ICSSImage): background is CSSLinearGradientImage => {\n return background.type === CSSImageType.LINEAR_GRADIENT;\n};\n\nexport const isRadialGradient = (background: ICSSImage): background is CSSRadialGradientImage => {\n return background.type === CSSImageType.RADIAL_GRADIENT;\n};\n\nexport interface UnprocessedGradientColorStop {\n color: Color;\n stop: LengthPercentage | null;\n}\n\nexport interface GradientColorStop {\n color: Color;\n stop: number;\n}\n\nexport interface ICSSImage {\n type: CSSImageType;\n}\n\nexport interface CSSURLImage extends ICSSImage {\n url: string;\n type: CSSImageType.URL;\n}\n\n// interface ICSSGeneratedImage extends ICSSImage {}\n\nexport type GradientCorner = [LengthPercentage, LengthPercentage];\n\ninterface ICSSGradientImage extends ICSSImage {\n stops: UnprocessedGradientColorStop[];\n}\n\nexport interface CSSLinearGradientImage extends ICSSGradientImage {\n angle: number | GradientCorner;\n type: CSSImageType.LINEAR_GRADIENT;\n}\n\nexport const enum CSSRadialShape {\n CIRCLE,\n ELLIPSE\n}\n\nexport const enum CSSRadialExtent {\n CLOSEST_SIDE,\n FARTHEST_SIDE,\n CLOSEST_CORNER,\n FARTHEST_CORNER\n}\n\nexport type CSSRadialSize = CSSRadialExtent | LengthPercentage[];\n\nexport interface CSSRadialGradientImage extends ICSSGradientImage {\n type: CSSImageType.RADIAL_GRADIENT;\n shape: CSSRadialShape;\n size: CSSRadialSize;\n position: LengthPercentage[];\n}\n\nexport const image: ITypeDescriptor<ICSSImage> = {\n name: 'image',\n parse: (context: Context, value: CSSValue): ICSSImage => {\n if (value.type === TokenType.URL_TOKEN) {\n const image: CSSURLImage = {url: value.value, type: CSSImageType.URL};\n context.cache.addImage(value.value);\n return image;\n }\n\n if (value.type === TokenType.FUNCTION) {\n const imageFunction = SUPPORTED_IMAGE_FUNCTIONS[value.name];\n if (typeof imageFunction === 'undefined') {\n throw new Error(`Attempting to parse an unsupported image function \"${value.name}\"`);\n }\n return imageFunction(context, value.values);\n }\n\n throw new Error(`Unsupported image type ${value.type}`);\n }\n};\n\nexport function isSupportedImage(value: CSSValue): boolean {\n return (\n !(value.type === TokenType.IDENT_TOKEN && value.value === 'none') &&\n (value.type !== TokenType.FUNCTION || !!SUPPORTED_IMAGE_FUNCTIONS[value.name])\n );\n}\n\nconst SUPPORTED_IMAGE_FUNCTIONS: Record<string, (context: Context, args: CSSValue[]) => ICSSImage> = {\n 'linear-gradient': linearGradient,\n '-moz-linear-gradient': prefixLinearGradient,\n '-ms-linear-gradient': prefixLinearGradient,\n '-o-linear-gradient': prefixLinearGradient,\n '-webkit-linear-gradient': prefixLinearGradient,\n 'radial-gradient': radialGradient,\n '-moz-radial-gradient': prefixRadialGradient,\n '-ms-radial-gradient': prefixRadialGradient,\n '-o-radial-gradient': prefixRadialGradient,\n '-webkit-radial-gradient': prefixRadialGradient,\n '-webkit-gradient': webkitGradient\n};\n","import {TokenType} from '../syntax/tokenizer';\nimport {ICSSImage, image, isSupportedImage} from '../types/image';\nimport {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, nonFunctionArgSeparator} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport const backgroundImage: IPropertyListDescriptor<ICSSImage[]> = {\n name: 'background-image',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (context: Context, tokens: CSSValue[]) => {\n if (tokens.length === 0) {\n return [];\n }\n\n const first = tokens[0];\n\n if (first.type === TokenType.IDENT_TOKEN && first.value === 'none') {\n return [];\n }\n\n return tokens\n .filter((value) => nonFunctionArgSeparator(value) && isSupportedImage(value))\n .map((value) => image.parse(context, value));\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport const enum BACKGROUND_ORIGIN {\n BORDER_BOX = 0,\n PADDING_BOX = 1,\n CONTENT_BOX = 2\n}\n\nexport type BackgroundOrigin = BACKGROUND_ORIGIN[];\n\nexport const backgroundOrigin: IPropertyListDescriptor<BackgroundOrigin> = {\n name: 'background-origin',\n initialValue: 'border-box',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): BackgroundOrigin => {\n return tokens.map((token) => {\n if (isIdentToken(token)) {\n switch (token.value) {\n case 'padding-box':\n return BACKGROUND_ORIGIN.PADDING_BOX;\n case 'content-box':\n return BACKGROUND_ORIGIN.CONTENT_BOX;\n }\n }\n return BACKGROUND_ORIGIN.BORDER_BOX;\n });\n }\n};\n","import {PropertyDescriptorParsingType, IPropertyListDescriptor} from '../IPropertyDescriptor';\nimport {CSSValue, parseFunctionArgs} from '../syntax/parser';\nimport {isLengthPercentage, LengthPercentageTuple, parseLengthPercentageTuple} from '../types/length-percentage';\nimport {Context} from '../../core/context';\nexport type BackgroundPosition = BackgroundImagePosition[];\n\nexport type BackgroundImagePosition = LengthPercentageTuple;\n\nexport const backgroundPosition: IPropertyListDescriptor<BackgroundPosition> = {\n name: 'background-position',\n initialValue: '0% 0%',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (_context: Context, tokens: CSSValue[]): BackgroundPosition => {\n return parseFunctionArgs(tokens)\n .map((values: CSSValue[]) => values.filter(isLengthPercentage))\n .map(parseLengthPercentageTuple);\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken, parseFunctionArgs} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport type BackgroundRepeat = BACKGROUND_REPEAT[];\n\nexport const enum BACKGROUND_REPEAT {\n REPEAT = 0,\n NO_REPEAT = 1,\n REPEAT_X = 2,\n REPEAT_Y = 3\n}\n\nexport const backgroundRepeat: IPropertyListDescriptor<BackgroundRepeat> = {\n name: 'background-repeat',\n initialValue: 'repeat',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): BackgroundRepeat => {\n return parseFunctionArgs(tokens)\n .map((values) =>\n values\n .filter(isIdentToken)\n .map((token) => token.value)\n .join(' ')\n )\n .map(parseBackgroundRepeat);\n }\n};\n\nconst parseBackgroundRepeat = (value: string): BACKGROUND_REPEAT => {\n switch (value) {\n case 'no-repeat':\n return BACKGROUND_REPEAT.NO_REPEAT;\n case 'repeat-x':\n case 'repeat no-repeat':\n return BACKGROUND_REPEAT.REPEAT_X;\n case 'repeat-y':\n case 'no-repeat repeat':\n return BACKGROUND_REPEAT.REPEAT_Y;\n case 'repeat':\n default:\n return BACKGROUND_REPEAT.REPEAT;\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken, parseFunctionArgs} from '../syntax/parser';\nimport {isLengthPercentage, LengthPercentage} from '../types/length-percentage';\nimport {StringValueToken} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\n\nexport enum BACKGROUND_SIZE {\n AUTO = 'auto',\n CONTAIN = 'contain',\n COVER = 'cover'\n}\n\nexport type BackgroundSizeInfo = LengthPercentage | StringValueToken;\nexport type BackgroundSize = BackgroundSizeInfo[][];\n\nexport const backgroundSize: IPropertyListDescriptor<BackgroundSize> = {\n name: 'background-size',\n initialValue: '0',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): BackgroundSize => {\n return parseFunctionArgs(tokens).map((values) => values.filter(isBackgroundSizeInfoToken));\n }\n};\n\nconst isBackgroundSizeInfoToken = (value: CSSValue): value is BackgroundSizeInfo =>\n isIdentToken(value) || isLengthPercentage(value);\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nconst borderColorForSide = (side: string): IPropertyTypeValueDescriptor => ({\n name: `border-${side}-color`,\n initialValue: 'transparent',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'color'\n});\n\nexport const borderTopColor: IPropertyTypeValueDescriptor = borderColorForSide('top');\nexport const borderRightColor: IPropertyTypeValueDescriptor = borderColorForSide('right');\nexport const borderBottomColor: IPropertyTypeValueDescriptor = borderColorForSide('bottom');\nexport const borderLeftColor: IPropertyTypeValueDescriptor = borderColorForSide('left');\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {isLengthPercentage, LengthPercentageTuple, parseLengthPercentageTuple} from '../types/length-percentage';\nimport {Context} from '../../core/context';\nexport type BorderRadius = LengthPercentageTuple;\n\nconst borderRadiusForSide = (side: string): IPropertyListDescriptor<BorderRadius> => ({\n name: `border-radius-${side}`,\n initialValue: '0 0',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): BorderRadius =>\n parseLengthPercentageTuple(tokens.filter(isLengthPercentage))\n});\n\nexport const borderTopLeftRadius: IPropertyListDescriptor<BorderRadius> = borderRadiusForSide('top-left');\nexport const borderTopRightRadius: IPropertyListDescriptor<BorderRadius> = borderRadiusForSide('top-right');\nexport const borderBottomRightRadius: IPropertyListDescriptor<BorderRadius> = borderRadiusForSide('bottom-right');\nexport const borderBottomLeftRadius: IPropertyListDescriptor<BorderRadius> = borderRadiusForSide('bottom-left');\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum BORDER_STYLE {\n NONE = 0,\n SOLID = 1,\n DASHED = 2,\n DOTTED = 3,\n DOUBLE = 4\n}\n\nconst borderStyleForSide = (side: string): IPropertyIdentValueDescriptor<BORDER_STYLE> => ({\n name: `border-${side}-style`,\n initialValue: 'solid',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, style: string): BORDER_STYLE => {\n switch (style) {\n case 'none':\n return BORDER_STYLE.NONE;\n case 'dashed':\n return BORDER_STYLE.DASHED;\n case 'dotted':\n return BORDER_STYLE.DOTTED;\n case 'double':\n return BORDER_STYLE.DOUBLE;\n }\n return BORDER_STYLE.SOLID;\n }\n});\n\nexport const borderTopStyle: IPropertyIdentValueDescriptor<BORDER_STYLE> = borderStyleForSide('top');\nexport const borderRightStyle: IPropertyIdentValueDescriptor<BORDER_STYLE> = borderStyleForSide('right');\nexport const borderBottomStyle: IPropertyIdentValueDescriptor<BORDER_STYLE> = borderStyleForSide('bottom');\nexport const borderLeftStyle: IPropertyIdentValueDescriptor<BORDER_STYLE> = borderStyleForSide('left');\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isDimensionToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nconst borderWidthForSide = (side: string): IPropertyValueDescriptor<number> => ({\n name: `border-${side}-width`,\n initialValue: '0',\n type: PropertyDescriptorParsingType.VALUE,\n prefix: false,\n parse: (_context: Context, token: CSSValue): number => {\n if (isDimensionToken(token)) {\n return token.number;\n }\n return 0;\n }\n});\n\nexport const borderTopWidth: IPropertyValueDescriptor<number> = borderWidthForSide('top');\nexport const borderRightWidth: IPropertyValueDescriptor<number> = borderWidthForSide('right');\nexport const borderBottomWidth: IPropertyValueDescriptor<number> = borderWidthForSide('bottom');\nexport const borderLeftWidth: IPropertyValueDescriptor<number> = borderWidthForSide('left');\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nexport const color: IPropertyTypeValueDescriptor = {\n name: `color`,\n initialValue: 'transparent',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'color'\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\n\nexport const enum DIRECTION {\n LTR = 0,\n RTL = 1\n}\n\nexport const direction: IPropertyIdentValueDescriptor<DIRECTION> = {\n name: 'direction',\n initialValue: 'ltr',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, direction: string) => {\n switch (direction) {\n case 'rtl':\n return DIRECTION.RTL;\n case 'ltr':\n default:\n return DIRECTION.LTR;\n }\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const enum DISPLAY {\n NONE = 0,\n BLOCK = 1 << 1,\n INLINE = 1 << 2,\n RUN_IN = 1 << 3,\n FLOW = 1 << 4,\n FLOW_ROOT = 1 << 5,\n TABLE = 1 << 6,\n FLEX = 1 << 7,\n GRID = 1 << 8,\n RUBY = 1 << 9,\n SUBGRID = 1 << 10,\n LIST_ITEM = 1 << 11,\n TABLE_ROW_GROUP = 1 << 12,\n TABLE_HEADER_GROUP = 1 << 13,\n TABLE_FOOTER_GROUP = 1 << 14,\n TABLE_ROW = 1 << 15,\n TABLE_CELL = 1 << 16,\n TABLE_COLUMN_GROUP = 1 << 17,\n TABLE_COLUMN = 1 << 18,\n TABLE_CAPTION = 1 << 19,\n RUBY_BASE = 1 << 20,\n RUBY_TEXT = 1 << 21,\n RUBY_BASE_CONTAINER = 1 << 22,\n RUBY_TEXT_CONTAINER = 1 << 23,\n CONTENTS = 1 << 24,\n INLINE_BLOCK = 1 << 25,\n INLINE_LIST_ITEM = 1 << 26,\n INLINE_TABLE = 1 << 27,\n INLINE_FLEX = 1 << 28,\n INLINE_GRID = 1 << 29\n}\n\nexport type Display = number;\n\nexport const display: IPropertyListDescriptor<Display> = {\n name: 'display',\n initialValue: 'inline-block',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): Display => {\n return tokens.filter(isIdentToken).reduce((bit, token) => {\n return bit | parseDisplayValue(token.value);\n }, DISPLAY.NONE);\n }\n};\n\nconst parseDisplayValue = (display: string): Display => {\n switch (display) {\n case 'block':\n case '-webkit-box':\n return DISPLAY.BLOCK;\n case 'inline':\n return DISPLAY.INLINE;\n case 'run-in':\n return DISPLAY.RUN_IN;\n case 'flow':\n return DISPLAY.FLOW;\n case 'flow-root':\n return DISPLAY.FLOW_ROOT;\n case 'table':\n return DISPLAY.TABLE;\n case 'flex':\n case '-webkit-flex':\n return DISPLAY.FLEX;\n case 'grid':\n case '-ms-grid':\n return DISPLAY.GRID;\n case 'ruby':\n return DISPLAY.RUBY;\n case 'subgrid':\n return DISPLAY.SUBGRID;\n case 'list-item':\n return DISPLAY.LIST_ITEM;\n case 'table-row-group':\n return DISPLAY.TABLE_ROW_GROUP;\n case 'table-header-group':\n return DISPLAY.TABLE_HEADER_GROUP;\n case 'table-footer-group':\n return DISPLAY.TABLE_FOOTER_GROUP;\n case 'table-row':\n return DISPLAY.TABLE_ROW;\n case 'table-cell':\n return DISPLAY.TABLE_CELL;\n case 'table-column-group':\n return DISPLAY.TABLE_COLUMN_GROUP;\n case 'table-column':\n return DISPLAY.TABLE_COLUMN;\n case 'table-caption':\n return DISPLAY.TABLE_CAPTION;\n case 'ruby-base':\n return DISPLAY.RUBY_BASE;\n case 'ruby-text':\n return DISPLAY.RUBY_TEXT;\n case 'ruby-base-container':\n return DISPLAY.RUBY_BASE_CONTAINER;\n case 'ruby-text-container':\n return DISPLAY.RUBY_TEXT_CONTAINER;\n case 'contents':\n return DISPLAY.CONTENTS;\n case 'inline-block':\n return DISPLAY.INLINE_BLOCK;\n case 'inline-list-item':\n return DISPLAY.INLINE_LIST_ITEM;\n case 'inline-table':\n return DISPLAY.INLINE_TABLE;\n case 'inline-flex':\n return DISPLAY.INLINE_FLEX;\n case 'inline-grid':\n return DISPLAY.INLINE_GRID;\n }\n\n return DISPLAY.NONE;\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum FLOAT {\n NONE = 0,\n LEFT = 1,\n RIGHT = 2,\n INLINE_START = 3,\n INLINE_END = 4\n}\n\nexport const float: IPropertyIdentValueDescriptor<FLOAT> = {\n name: 'float',\n initialValue: 'none',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, float: string) => {\n switch (float) {\n case 'left':\n return FLOAT.LEFT;\n case 'right':\n return FLOAT.RIGHT;\n case 'inline-start':\n return FLOAT.INLINE_START;\n case 'inline-end':\n return FLOAT.INLINE_END;\n }\n return FLOAT.NONE;\n }\n};\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\nexport const letterSpacing: IPropertyValueDescriptor<number> = {\n name: 'letter-spacing',\n initialValue: '0',\n prefix: false,\n type: PropertyDescriptorParsingType.VALUE,\n parse: (_context: Context, token: CSSValue) => {\n if (token.type === TokenType.IDENT_TOKEN && token.value === 'normal') {\n return 0;\n }\n\n if (token.type === TokenType.NUMBER_TOKEN) {\n return token.number;\n }\n\n if (token.type === TokenType.DIMENSION_TOKEN) {\n return token.number;\n }\n\n return 0;\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport enum LINE_BREAK {\n NORMAL = 'normal',\n STRICT = 'strict'\n}\n\nexport const lineBreak: IPropertyIdentValueDescriptor<LINE_BREAK> = {\n name: 'line-break',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, lineBreak: string): LINE_BREAK => {\n switch (lineBreak) {\n case 'strict':\n return LINE_BREAK.STRICT;\n case 'normal':\n default:\n return LINE_BREAK.NORMAL;\n }\n }\n};\n","import {IPropertyTokenValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {getAbsoluteValue, isLengthPercentage} from '../types/length-percentage';\nexport const lineHeight: IPropertyTokenValueDescriptor = {\n name: 'line-height',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.TOKEN_VALUE\n};\n\nexport const computeLineHeight = (token: CSSValue, fontSize: number): number => {\n if (isIdentToken(token) && token.value === 'normal') {\n return 1.2 * fontSize;\n } else if (token.type === TokenType.NUMBER_TOKEN) {\n return fontSize * token.number;\n } else if (isLengthPercentage(token)) {\n return getAbsoluteValue(token, fontSize);\n }\n\n return fontSize;\n};\n","import {TokenType} from '../syntax/tokenizer';\nimport {ICSSImage, image} from '../types/image';\nimport {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport const listStyleImage: IPropertyValueDescriptor<ICSSImage | null> = {\n name: 'list-style-image',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.VALUE,\n prefix: false,\n parse: (context: Context, token: CSSValue) => {\n if (token.type === TokenType.IDENT_TOKEN && token.value === 'none') {\n return null;\n }\n\n return image.parse(context, token);\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum LIST_STYLE_POSITION {\n INSIDE = 0,\n OUTSIDE = 1\n}\n\nexport const listStylePosition: IPropertyIdentValueDescriptor<LIST_STYLE_POSITION> = {\n name: 'list-style-position',\n initialValue: 'outside',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, position: string) => {\n switch (position) {\n case 'inside':\n return LIST_STYLE_POSITION.INSIDE;\n case 'outside':\n default:\n return LIST_STYLE_POSITION.OUTSIDE;\n }\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum LIST_STYLE_TYPE {\n NONE = -1,\n DISC = 0,\n CIRCLE = 1,\n SQUARE = 2,\n DECIMAL = 3,\n CJK_DECIMAL = 4,\n DECIMAL_LEADING_ZERO = 5,\n LOWER_ROMAN = 6,\n UPPER_ROMAN = 7,\n LOWER_GREEK = 8,\n LOWER_ALPHA = 9,\n UPPER_ALPHA = 10,\n ARABIC_INDIC = 11,\n ARMENIAN = 12,\n BENGALI = 13,\n CAMBODIAN = 14,\n CJK_EARTHLY_BRANCH = 15,\n CJK_HEAVENLY_STEM = 16,\n CJK_IDEOGRAPHIC = 17,\n DEVANAGARI = 18,\n ETHIOPIC_NUMERIC = 19,\n GEORGIAN = 20,\n GUJARATI = 21,\n GURMUKHI = 22,\n HEBREW = 22,\n HIRAGANA = 23,\n HIRAGANA_IROHA = 24,\n JAPANESE_FORMAL = 25,\n JAPANESE_INFORMAL = 26,\n KANNADA = 27,\n KATAKANA = 28,\n KATAKANA_IROHA = 29,\n KHMER = 30,\n KOREAN_HANGUL_FORMAL = 31,\n KOREAN_HANJA_FORMAL = 32,\n KOREAN_HANJA_INFORMAL = 33,\n LAO = 34,\n LOWER_ARMENIAN = 35,\n MALAYALAM = 36,\n MONGOLIAN = 37,\n MYANMAR = 38,\n ORIYA = 39,\n PERSIAN = 40,\n SIMP_CHINESE_FORMAL = 41,\n SIMP_CHINESE_INFORMAL = 42,\n TAMIL = 43,\n TELUGU = 44,\n THAI = 45,\n TIBETAN = 46,\n TRAD_CHINESE_FORMAL = 47,\n TRAD_CHINESE_INFORMAL = 48,\n UPPER_ARMENIAN = 49,\n DISCLOSURE_OPEN = 50,\n DISCLOSURE_CLOSED = 51\n}\n\nexport const listStyleType: IPropertyIdentValueDescriptor<LIST_STYLE_TYPE> = {\n name: 'list-style-type',\n initialValue: 'none',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, type: string) => {\n switch (type) {\n case 'disc':\n return LIST_STYLE_TYPE.DISC;\n case 'circle':\n return LIST_STYLE_TYPE.CIRCLE;\n case 'square':\n return LIST_STYLE_TYPE.SQUARE;\n case 'decimal':\n return LIST_STYLE_TYPE.DECIMAL;\n case 'cjk-decimal':\n return LIST_STYLE_TYPE.CJK_DECIMAL;\n case 'decimal-leading-zero':\n return LIST_STYLE_TYPE.DECIMAL_LEADING_ZERO;\n case 'lower-roman':\n return LIST_STYLE_TYPE.LOWER_ROMAN;\n case 'upper-roman':\n return LIST_STYLE_TYPE.UPPER_ROMAN;\n case 'lower-greek':\n return LIST_STYLE_TYPE.LOWER_GREEK;\n case 'lower-alpha':\n return LIST_STYLE_TYPE.LOWER_ALPHA;\n case 'upper-alpha':\n return LIST_STYLE_TYPE.UPPER_ALPHA;\n case 'arabic-indic':\n return LIST_STYLE_TYPE.ARABIC_INDIC;\n case 'armenian':\n return LIST_STYLE_TYPE.ARMENIAN;\n case 'bengali':\n return LIST_STYLE_TYPE.BENGALI;\n case 'cambodian':\n return LIST_STYLE_TYPE.CAMBODIAN;\n case 'cjk-earthly-branch':\n return LIST_STYLE_TYPE.CJK_EARTHLY_BRANCH;\n case 'cjk-heavenly-stem':\n return LIST_STYLE_TYPE.CJK_HEAVENLY_STEM;\n case 'cjk-ideographic':\n return LIST_STYLE_TYPE.CJK_IDEOGRAPHIC;\n case 'devanagari':\n return LIST_STYLE_TYPE.DEVANAGARI;\n case 'ethiopic-numeric':\n return LIST_STYLE_TYPE.ETHIOPIC_NUMERIC;\n case 'georgian':\n return LIST_STYLE_TYPE.GEORGIAN;\n case 'gujarati':\n return LIST_STYLE_TYPE.GUJARATI;\n case 'gurmukhi':\n return LIST_STYLE_TYPE.GURMUKHI;\n case 'hebrew':\n return LIST_STYLE_TYPE.HEBREW;\n case 'hiragana':\n return LIST_STYLE_TYPE.HIRAGANA;\n case 'hiragana-iroha':\n return LIST_STYLE_TYPE.HIRAGANA_IROHA;\n case 'japanese-formal':\n return LIST_STYLE_TYPE.JAPANESE_FORMAL;\n case 'japanese-informal':\n return LIST_STYLE_TYPE.JAPANESE_INFORMAL;\n case 'kannada':\n return LIST_STYLE_TYPE.KANNADA;\n case 'katakana':\n return LIST_STYLE_TYPE.KATAKANA;\n case 'katakana-iroha':\n return LIST_STYLE_TYPE.KATAKANA_IROHA;\n case 'khmer':\n return LIST_STYLE_TYPE.KHMER;\n case 'korean-hangul-formal':\n return LIST_STYLE_TYPE.KOREAN_HANGUL_FORMAL;\n case 'korean-hanja-formal':\n return LIST_STYLE_TYPE.KOREAN_HANJA_FORMAL;\n case 'korean-hanja-informal':\n return LIST_STYLE_TYPE.KOREAN_HANJA_INFORMAL;\n case 'lao':\n return LIST_STYLE_TYPE.LAO;\n case 'lower-armenian':\n return LIST_STYLE_TYPE.LOWER_ARMENIAN;\n case 'malayalam':\n return LIST_STYLE_TYPE.MALAYALAM;\n case 'mongolian':\n return LIST_STYLE_TYPE.MONGOLIAN;\n case 'myanmar':\n return LIST_STYLE_TYPE.MYANMAR;\n case 'oriya':\n return LIST_STYLE_TYPE.ORIYA;\n case 'persian':\n return LIST_STYLE_TYPE.PERSIAN;\n case 'simp-chinese-formal':\n return LIST_STYLE_TYPE.SIMP_CHINESE_FORMAL;\n case 'simp-chinese-informal':\n return LIST_STYLE_TYPE.SIMP_CHINESE_INFORMAL;\n case 'tamil':\n return LIST_STYLE_TYPE.TAMIL;\n case 'telugu':\n return LIST_STYLE_TYPE.TELUGU;\n case 'thai':\n return LIST_STYLE_TYPE.THAI;\n case 'tibetan':\n return LIST_STYLE_TYPE.TIBETAN;\n case 'trad-chinese-formal':\n return LIST_STYLE_TYPE.TRAD_CHINESE_FORMAL;\n case 'trad-chinese-informal':\n return LIST_STYLE_TYPE.TRAD_CHINESE_INFORMAL;\n case 'upper-armenian':\n return LIST_STYLE_TYPE.UPPER_ARMENIAN;\n case 'disclosure-open':\n return LIST_STYLE_TYPE.DISCLOSURE_OPEN;\n case 'disclosure-closed':\n return LIST_STYLE_TYPE.DISCLOSURE_CLOSED;\n case 'none':\n default:\n return LIST_STYLE_TYPE.NONE;\n }\n }\n};\n","import {IPropertyTokenValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nconst marginForSide = (side: string): IPropertyTokenValueDescriptor => ({\n name: `margin-${side}`,\n initialValue: '0',\n prefix: false,\n type: PropertyDescriptorParsingType.TOKEN_VALUE\n});\n\nexport const marginTop: IPropertyTokenValueDescriptor = marginForSide('top');\nexport const marginRight: IPropertyTokenValueDescriptor = marginForSide('right');\nexport const marginBottom: IPropertyTokenValueDescriptor = marginForSide('bottom');\nexport const marginLeft: IPropertyTokenValueDescriptor = marginForSide('left');\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const enum OVERFLOW {\n VISIBLE = 0,\n HIDDEN = 1,\n SCROLL = 2,\n CLIP = 3,\n AUTO = 4\n}\n\nexport const overflow: IPropertyListDescriptor<OVERFLOW[]> = {\n name: 'overflow',\n initialValue: 'visible',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): OVERFLOW[] => {\n return tokens.filter(isIdentToken).map((overflow) => {\n switch (overflow.value) {\n case 'hidden':\n return OVERFLOW.HIDDEN;\n case 'scroll':\n return OVERFLOW.SCROLL;\n case 'clip':\n return OVERFLOW.CLIP;\n case 'auto':\n return OVERFLOW.AUTO;\n case 'visible':\n default:\n return OVERFLOW.VISIBLE;\n }\n });\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum OVERFLOW_WRAP {\n NORMAL = 'normal',\n BREAK_WORD = 'break-word'\n}\n\nexport const overflowWrap: IPropertyIdentValueDescriptor<OVERFLOW_WRAP> = {\n name: 'overflow-wrap',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, overflow: string) => {\n switch (overflow) {\n case 'break-word':\n return OVERFLOW_WRAP.BREAK_WORD;\n case 'normal':\n default:\n return OVERFLOW_WRAP.NORMAL;\n }\n }\n};\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nconst paddingForSide = (side: string): IPropertyTypeValueDescriptor => ({\n name: `padding-${side}`,\n initialValue: '0',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'length-percentage'\n});\n\nexport const paddingTop: IPropertyTypeValueDescriptor = paddingForSide('top');\nexport const paddingRight: IPropertyTypeValueDescriptor = paddingForSide('right');\nexport const paddingBottom: IPropertyTypeValueDescriptor = paddingForSide('bottom');\nexport const paddingLeft: IPropertyTypeValueDescriptor = paddingForSide('left');\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum TEXT_ALIGN {\n LEFT = 0,\n CENTER = 1,\n RIGHT = 2\n}\n\nexport const textAlign: IPropertyIdentValueDescriptor<TEXT_ALIGN> = {\n name: 'text-align',\n initialValue: 'left',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, textAlign: string) => {\n switch (textAlign) {\n case 'right':\n return TEXT_ALIGN.RIGHT;\n case 'center':\n case 'justify':\n return TEXT_ALIGN.CENTER;\n case 'left':\n default:\n return TEXT_ALIGN.LEFT;\n }\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum POSITION {\n STATIC = 0,\n RELATIVE = 1,\n ABSOLUTE = 2,\n FIXED = 3,\n STICKY = 4\n}\n\nexport const position: IPropertyIdentValueDescriptor<POSITION> = {\n name: 'position',\n initialValue: 'static',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, position: string) => {\n switch (position) {\n case 'relative':\n return POSITION.RELATIVE;\n case 'absolute':\n return POSITION.ABSOLUTE;\n case 'fixed':\n return POSITION.FIXED;\n case 'sticky':\n return POSITION.STICKY;\n }\n\n return POSITION.STATIC;\n }\n};\n","import {PropertyDescriptorParsingType, IPropertyListDescriptor} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentWithValue, parseFunctionArgs} from '../syntax/parser';\nimport {ZERO_LENGTH} from '../types/length-percentage';\nimport {color, Color, COLORS} from '../types/color';\nimport {isLength, Length} from '../types/length';\nimport {Context} from '../../core/context';\n\nexport type TextShadow = TextShadowItem[];\ninterface TextShadowItem {\n color: Color;\n offsetX: Length;\n offsetY: Length;\n blur: Length;\n}\n\nexport const textShadow: IPropertyListDescriptor<TextShadow> = {\n name: 'text-shadow',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (context: Context, tokens: CSSValue[]): TextShadow => {\n if (tokens.length === 1 && isIdentWithValue(tokens[0], 'none')) {\n return [];\n }\n\n return parseFunctionArgs(tokens).map((values: CSSValue[]) => {\n const shadow: TextShadowItem = {\n color: COLORS.TRANSPARENT,\n offsetX: ZERO_LENGTH,\n offsetY: ZERO_LENGTH,\n blur: ZERO_LENGTH\n };\n let c = 0;\n for (let i = 0; i < values.length; i++) {\n const token = values[i];\n if (isLength(token)) {\n if (c === 0) {\n shadow.offsetX = token;\n } else if (c === 1) {\n shadow.offsetY = token;\n } else {\n shadow.blur = token;\n }\n c++;\n } else {\n shadow.color = color.parse(context, token);\n }\n }\n return shadow;\n });\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum TEXT_TRANSFORM {\n NONE = 0,\n LOWERCASE = 1,\n UPPERCASE = 2,\n CAPITALIZE = 3\n}\n\nexport const textTransform: IPropertyIdentValueDescriptor<TEXT_TRANSFORM> = {\n name: 'text-transform',\n initialValue: 'none',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, textTransform: string) => {\n switch (textTransform) {\n case 'uppercase':\n return TEXT_TRANSFORM.UPPERCASE;\n case 'lowercase':\n return TEXT_TRANSFORM.LOWERCASE;\n case 'capitalize':\n return TEXT_TRANSFORM.CAPITALIZE;\n }\n\n return TEXT_TRANSFORM.NONE;\n }\n};\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {NumberValueToken, TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\nexport type Matrix = [number, number, number, number, number, number];\nexport type Transform = Matrix | null;\n\nexport const transform: IPropertyValueDescriptor<Transform> = {\n name: 'transform',\n initialValue: 'none',\n prefix: true,\n type: PropertyDescriptorParsingType.VALUE,\n parse: (_context: Context, token: CSSValue) => {\n if (token.type === TokenType.IDENT_TOKEN && token.value === 'none') {\n return null;\n }\n\n if (token.type === TokenType.FUNCTION) {\n const transformFunction = SUPPORTED_TRANSFORM_FUNCTIONS[token.name];\n if (typeof transformFunction === 'undefined') {\n throw new Error(`Attempting to parse an unsupported transform function \"${token.name}\"`);\n }\n return transformFunction(token.values);\n }\n\n return null;\n }\n};\n\nconst matrix = (args: CSSValue[]): Transform => {\n const values = args.filter((arg) => arg.type === TokenType.NUMBER_TOKEN).map((arg: NumberValueToken) => arg.number);\n\n return values.length === 6 ? (values as Matrix) : null;\n};\n\n// doesn't support 3D transforms at the moment\nconst matrix3d = (args: CSSValue[]): Transform => {\n const values = args.filter((arg) => arg.type === TokenType.NUMBER_TOKEN).map((arg: NumberValueToken) => arg.number);\n\n const [a1, b1, {}, {}, a2, b2, {}, {}, {}, {}, {}, {}, a4, b4, {}, {}] = values;\n\n return values.length === 16 ? [a1, b1, a2, b2, a4, b4] : null;\n};\n\nconst SUPPORTED_TRANSFORM_FUNCTIONS: {\n [key: string]: (args: CSSValue[]) => Transform;\n} = {\n matrix: matrix,\n matrix3d: matrix3d\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {isLengthPercentage, LengthPercentage} from '../types/length-percentage';\nimport {FLAG_INTEGER, TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\nexport type TransformOrigin = [LengthPercentage, LengthPercentage];\n\nconst DEFAULT_VALUE: LengthPercentage = {\n type: TokenType.PERCENTAGE_TOKEN,\n number: 50,\n flags: FLAG_INTEGER\n};\nconst DEFAULT: TransformOrigin = [DEFAULT_VALUE, DEFAULT_VALUE];\n\nexport const transformOrigin: IPropertyListDescriptor<TransformOrigin> = {\n name: 'transform-origin',\n initialValue: '50% 50%',\n prefix: true,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]) => {\n const origins: LengthPercentage[] = tokens.filter(isLengthPercentage);\n\n if (origins.length !== 2) {\n return DEFAULT;\n }\n\n return [origins[0], origins[1]];\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum VISIBILITY {\n VISIBLE = 0,\n HIDDEN = 1,\n COLLAPSE = 2\n}\n\nexport const visibility: IPropertyIdentValueDescriptor<VISIBILITY> = {\n name: 'visible',\n initialValue: 'none',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, visibility: string) => {\n switch (visibility) {\n case 'hidden':\n return VISIBILITY.HIDDEN;\n case 'collapse':\n return VISIBILITY.COLLAPSE;\n case 'visible':\n default:\n return VISIBILITY.VISIBLE;\n }\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport enum WORD_BREAK {\n NORMAL = 'normal',\n BREAK_ALL = 'break-all',\n KEEP_ALL = 'keep-all'\n}\n\nexport const wordBreak: IPropertyIdentValueDescriptor<WORD_BREAK> = {\n name: 'word-break',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, wordBreak: string): WORD_BREAK => {\n switch (wordBreak) {\n case 'break-all':\n return WORD_BREAK.BREAK_ALL;\n case 'keep-all':\n return WORD_BREAK.KEEP_ALL;\n case 'normal':\n default:\n return WORD_BREAK.NORMAL;\n }\n }\n};\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isNumberToken} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\n\ninterface zIndex {\n order: number;\n auto: boolean;\n}\n\nexport const zIndex: IPropertyValueDescriptor<zIndex> = {\n name: 'z-index',\n initialValue: 'auto',\n prefix: false,\n type: PropertyDescriptorParsingType.VALUE,\n parse: (_context: Context, token: CSSValue): zIndex => {\n if (token.type === TokenType.IDENT_TOKEN) {\n return {auto: true, order: 0};\n }\n\n if (isNumberToken(token)) {\n return {auto: false, order: token.number};\n }\n\n throw new Error(`Invalid z-index number parsed`);\n }\n};\n","import {CSSValue} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {ITypeDescriptor} from '../ITypeDescriptor';\nimport {Context} from '../../core/context';\n\nexport const time: ITypeDescriptor<number> = {\n name: 'time',\n parse: (_context: Context, value: CSSValue): number => {\n if (value.type === TokenType.DIMENSION_TOKEN) {\n switch (value.unit.toLowerCase()) {\n case 's':\n return 1000 * value.number;\n case 'ms':\n return value.number;\n }\n }\n\n throw new Error(`Unsupported time type`);\n }\n};\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isNumberToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const opacity: IPropertyValueDescriptor<number> = {\n name: 'opacity',\n initialValue: '1',\n type: PropertyDescriptorParsingType.VALUE,\n prefix: false,\n parse: (_context: Context, token: CSSValue): number => {\n if (isNumberToken(token)) {\n return token.number;\n }\n return 1;\n }\n};\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nexport const textDecorationColor: IPropertyTypeValueDescriptor = {\n name: `text-decoration-color`,\n initialValue: 'transparent',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'color'\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport const enum TEXT_DECORATION_LINE {\n NONE = 0,\n UNDERLINE = 1,\n OVERLINE = 2,\n LINE_THROUGH = 3,\n BLINK = 4\n}\n\nexport type TextDecorationLine = TEXT_DECORATION_LINE[];\n\nexport const textDecorationLine: IPropertyListDescriptor<TextDecorationLine> = {\n name: 'text-decoration-line',\n initialValue: 'none',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): TextDecorationLine => {\n return tokens\n .filter(isIdentToken)\n .map((token) => {\n switch (token.value) {\n case 'underline':\n return TEXT_DECORATION_LINE.UNDERLINE;\n case 'overline':\n return TEXT_DECORATION_LINE.OVERLINE;\n case 'line-through':\n return TEXT_DECORATION_LINE.LINE_THROUGH;\n case 'none':\n return TEXT_DECORATION_LINE.BLINK;\n }\n return TEXT_DECORATION_LINE.NONE;\n })\n .filter((line) => line !== TEXT_DECORATION_LINE.NONE);\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\n\nexport type FONT_FAMILY = string;\n\nexport type FontFamily = FONT_FAMILY[];\n\nexport const fontFamily: IPropertyListDescriptor<FontFamily> = {\n name: `font-family`,\n initialValue: '',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]) => {\n const accumulator: string[] = [];\n const results: string[] = [];\n tokens.forEach((token) => {\n switch (token.type) {\n case TokenType.IDENT_TOKEN:\n case TokenType.STRING_TOKEN:\n accumulator.push(token.value);\n break;\n case TokenType.NUMBER_TOKEN:\n accumulator.push(token.number.toString());\n break;\n case TokenType.COMMA_TOKEN:\n results.push(accumulator.join(' '));\n accumulator.length = 0;\n break;\n }\n });\n if (accumulator.length) {\n results.push(accumulator.join(' '));\n }\n return results.map((result) => (result.indexOf(' ') === -1 ? result : `'${result}'`));\n }\n};\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\n\nexport const fontSize: IPropertyTypeValueDescriptor = {\n name: `font-size`,\n initialValue: '0',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'length'\n};\n","import {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken, isNumberToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const fontWeight: IPropertyValueDescriptor<number> = {\n name: 'font-weight',\n initialValue: 'normal',\n type: PropertyDescriptorParsingType.VALUE,\n prefix: false,\n parse: (_context: Context, token: CSSValue): number => {\n if (isNumberToken(token)) {\n return token.number;\n }\n\n if (isIdentToken(token)) {\n switch (token.value) {\n case 'bold':\n return 700;\n case 'normal':\n default:\n return 400;\n }\n }\n\n return 400;\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const fontVariant: IPropertyListDescriptor<string[]> = {\n name: 'font-variant',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (_context: Context, tokens: CSSValue[]): string[] => {\n return tokens.filter(isIdentToken).map((token) => token.value);\n }\n};\n","import {IPropertyIdentValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const enum FONT_STYLE {\n NORMAL = 'normal',\n ITALIC = 'italic',\n OBLIQUE = 'oblique'\n}\n\nexport const fontStyle: IPropertyIdentValueDescriptor<FONT_STYLE> = {\n name: 'font-style',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.IDENT_VALUE,\n parse: (_context: Context, overflow: string) => {\n switch (overflow) {\n case 'oblique':\n return FONT_STYLE.OBLIQUE;\n case 'italic':\n return FONT_STYLE.ITALIC;\n case 'normal':\n default:\n return FONT_STYLE.NORMAL;\n }\n }\n};\n","export const contains = (bit: number, value: number): boolean => (bit & value) !== 0;\n","import {TokenType} from '../syntax/tokenizer';\nimport {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport type Content = CSSValue[];\n\nexport const content: IPropertyListDescriptor<Content> = {\n name: 'content',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (_context: Context, tokens: CSSValue[]) => {\n if (tokens.length === 0) {\n return [];\n }\n\n const first = tokens[0];\n\n if (first.type === TokenType.IDENT_TOKEN && first.value === 'none') {\n return [];\n }\n\n return tokens;\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isNumberToken, nonWhiteSpace} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\n\nexport interface COUNTER_INCREMENT {\n counter: string;\n increment: number;\n}\n\nexport type CounterIncrement = COUNTER_INCREMENT[] | null;\n\nexport const counterIncrement: IPropertyListDescriptor<CounterIncrement> = {\n name: 'counter-increment',\n initialValue: 'none',\n prefix: true,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]) => {\n if (tokens.length === 0) {\n return null;\n }\n\n const first = tokens[0];\n\n if (first.type === TokenType.IDENT_TOKEN && first.value === 'none') {\n return null;\n }\n\n const increments = [];\n const filtered = tokens.filter(nonWhiteSpace);\n\n for (let i = 0; i < filtered.length; i++) {\n const counter = filtered[i];\n const next = filtered[i + 1];\n if (counter.type === TokenType.IDENT_TOKEN) {\n const increment = next && isNumberToken(next) ? next.number : 1;\n increments.push({counter: counter.value, increment});\n }\n }\n\n return increments;\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken, isNumberToken, nonWhiteSpace} from '../syntax/parser';\nimport {Context} from '../../core/context';\n\nexport interface COUNTER_RESET {\n counter: string;\n reset: number;\n}\n\nexport type CounterReset = COUNTER_RESET[];\n\nexport const counterReset: IPropertyListDescriptor<CounterReset> = {\n name: 'counter-reset',\n initialValue: 'none',\n prefix: true,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]) => {\n if (tokens.length === 0) {\n return [];\n }\n\n const resets = [];\n const filtered = tokens.filter(nonWhiteSpace);\n\n for (let i = 0; i < filtered.length; i++) {\n const counter = filtered[i];\n const next = filtered[i + 1];\n if (isIdentToken(counter) && counter.value !== 'none') {\n const reset = next && isNumberToken(next) ? next.number : 0;\n resets.push({counter: counter.value, reset});\n }\n }\n\n return resets;\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nimport {CSSValue, isDimensionToken} from '../syntax/parser';\nimport {time} from '../types/time';\n\nexport const duration: IPropertyListDescriptor<number[]> = {\n name: 'duration',\n initialValue: '0s',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (context: Context, tokens: CSSValue[]) => {\n return tokens.filter(isDimensionToken).map((token) => time.parse(context, token));\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isStringToken} from '../syntax/parser';\nimport {TokenType} from '../syntax/tokenizer';\nimport {Context} from '../../core/context';\n\nexport interface QUOTE {\n open: string;\n close: string;\n}\n\nexport type Quotes = QUOTE[] | null;\n\nexport const quotes: IPropertyListDescriptor<Quotes> = {\n name: 'quotes',\n initialValue: 'none',\n prefix: true,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]) => {\n if (tokens.length === 0) {\n return null;\n }\n\n const first = tokens[0];\n\n if (first.type === TokenType.IDENT_TOKEN && first.value === 'none') {\n return null;\n }\n\n const quotes = [];\n const filtered = tokens.filter(isStringToken);\n\n if (filtered.length % 2 !== 0) {\n return null;\n }\n\n for (let i = 0; i < filtered.length; i += 2) {\n const open = filtered[i].value;\n const close = filtered[i + 1].value;\n quotes.push({open, close});\n }\n\n return quotes;\n }\n};\n\nexport const getQuote = (quotes: Quotes, depth: number, open: boolean): string => {\n if (!quotes) {\n return '';\n }\n\n const quote = quotes[Math.min(depth, quotes.length - 1)];\n if (!quote) {\n return '';\n }\n\n return open ? quote.open : quote.close;\n};\n","import {PropertyDescriptorParsingType, IPropertyListDescriptor} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentWithValue, parseFunctionArgs} from '../syntax/parser';\nimport {ZERO_LENGTH} from '../types/length-percentage';\nimport {color, Color} from '../types/color';\nimport {isLength, Length} from '../types/length';\nimport {Context} from '../../core/context';\n\nexport type BoxShadow = BoxShadowItem[];\ninterface BoxShadowItem {\n inset: boolean;\n color: Color;\n offsetX: Length;\n offsetY: Length;\n blur: Length;\n spread: Length;\n}\n\nexport const boxShadow: IPropertyListDescriptor<BoxShadow> = {\n name: 'box-shadow',\n initialValue: 'none',\n type: PropertyDescriptorParsingType.LIST,\n prefix: false,\n parse: (context: Context, tokens: CSSValue[]): BoxShadow => {\n if (tokens.length === 1 && isIdentWithValue(tokens[0], 'none')) {\n return [];\n }\n\n return parseFunctionArgs(tokens).map((values: CSSValue[]) => {\n const shadow: BoxShadowItem = {\n color: 0x000000ff,\n offsetX: ZERO_LENGTH,\n offsetY: ZERO_LENGTH,\n blur: ZERO_LENGTH,\n spread: ZERO_LENGTH,\n inset: false\n };\n let c = 0;\n for (let i = 0; i < values.length; i++) {\n const token = values[i];\n if (isIdentWithValue(token, 'inset')) {\n shadow.inset = true;\n } else if (isLength(token)) {\n if (c === 0) {\n shadow.offsetX = token;\n } else if (c === 1) {\n shadow.offsetY = token;\n } else if (c === 2) {\n shadow.blur = token;\n } else {\n shadow.spread = token;\n }\n c++;\n } else {\n shadow.color = color.parse(context, token);\n }\n }\n return shadow;\n });\n }\n};\n","import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {CSSValue, isIdentToken} from '../syntax/parser';\nimport {Context} from '../../core/context';\nexport const enum PAINT_ORDER_LAYER {\n FILL,\n STROKE,\n MARKERS\n}\n\nexport type PaintOrder = PAINT_ORDER_LAYER[];\n\nexport const paintOrder: IPropertyListDescriptor<PaintOrder> = {\n name: 'paint-order',\n initialValue: 'normal',\n prefix: false,\n type: PropertyDescriptorParsingType.LIST,\n parse: (_context: Context, tokens: CSSValue[]): PaintOrder => {\n const DEFAULT_VALUE = [PAINT_ORDER_LAYER.FILL, PAINT_ORDER_LAYER.STROKE, PAINT_ORDER_LAYER.MARKERS];\n const layers: PaintOrder = [];\n\n tokens.filter(isIdentToken).forEach((token) => {\n switch (token.value) {\n case 'stroke':\n layers.push(PAINT_ORDER_LAYER.STROKE);\n break;\n case 'fill':\n layers.push(PAINT_ORDER_LAYER.FILL);\n break;\n case 'markers':\n layers.push(PAINT_ORDER_LAYER.MARKERS);\n break;\n }\n });\n DEFAULT_VALUE.forEach((value) => {\n if (layers.indexOf(value) === -1) {\n layers.push(value);\n }\n });\n\n return layers;\n }\n};\n","import {IPropertyTypeValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nexport const webkitTextStrokeColor: IPropertyTypeValueDescriptor = {\n name: `-webkit-text-stroke-color`,\n initialValue: 'currentcolor',\n prefix: false,\n type: PropertyDescriptorParsingType.TYPE_VALUE,\n format: 'color'\n};\n","import {CSSValue, isDimensionToken} from '../syntax/parser';\nimport {IPropertyValueDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';\nimport {Context} from '../../core/context';\nexport const webkitTextStrokeWidth: IPropertyValueDescriptor<number> = {\n name: `-webkit-text-stroke-width`,\n initialValue: '0',\n type: PropertyDescriptorParsingType.VALUE,\n prefix: false,\n parse: (_context: Context, token: CSSValue): number => {\n if (isDimensionToken(token)) {\n return token.number;\n }\n return 0;\n }\n};\n","import {CSSPropertyDescriptor, PropertyDescriptorParsingType} from './IPropertyDescriptor';\nimport {backgroundClip} from './property-descriptors/background-clip';\nimport {backgroundColor} from './property-descriptors/background-color';\nimport {backgroundImage} from './property-descriptors/background-image';\nimport {backgroundOrigin} from './property-descriptors/background-origin';\nimport {backgroundPosition} from './property-descriptors/background-position';\nimport {backgroundRepeat} from './property-descriptors/background-repeat';\nimport {backgroundSize} from './property-descriptors/background-size';\nimport {\n borderBottomColor,\n borderLeftColor,\n borderRightColor,\n borderTopColor\n} from './property-descriptors/border-color';\nimport {\n borderBottomLeftRadius,\n borderBottomRightRadius,\n borderTopLeftRadius,\n borderTopRightRadius\n} from './property-descriptors/border-radius';\nimport {\n borderBottomStyle,\n borderLeftStyle,\n borderRightStyle,\n borderTopStyle\n} from './property-descriptors/border-style';\nimport {\n borderBottomWidth,\n borderLeftWidth,\n borderRightWidth,\n borderTopWidth\n} from './property-descriptors/border-width';\nimport {color} from './property-descriptors/color';\nimport {direction} from './property-descriptors/direction';\nimport {display, DISPLAY} from './property-descriptors/display';\nimport {float, FLOAT} from './property-descriptors/float';\nimport {letterSpacing} from './property-descriptors/letter-spacing';\nimport {lineBreak} from './property-descriptors/line-break';\nimport {lineHeight} from './property-descriptors/line-height';\nimport {listStyleImage} from './property-descriptors/list-style-image';\nimport {listStylePosition} from './property-descriptors/list-style-position';\nimport {listStyleType} from './property-descriptors/list-style-type';\nimport {marginBottom, marginLeft, marginRight, marginTop} from './property-descriptors/margin';\nimport {overflow, OVERFLOW} from './property-descriptors/overflow';\nimport {overflowWrap} from './property-descriptors/overflow-wrap';\nimport {paddingBottom, paddingLeft, paddingRight, paddingTop} from './property-descriptors/padding';\nimport {textAlign} from './property-descriptors/text-align';\nimport {position, POSITION} from './property-descriptors/position';\nimport {textShadow} from './property-descriptors/text-shadow';\nimport {textTransform} from './property-descriptors/text-transform';\nimport {transform} from './property-descriptors/transform';\nimport {transformOrigin} from './property-descriptors/transform-origin';\nimport {visibility, VISIBILITY} from './property-descriptors/visibility';\nimport {wordBreak} from './property-descriptors/word-break';\nimport {zIndex} from './property-descriptors/z-index';\nimport {CSSValue, isIdentToken, Parser} from './syntax/parser';\nimport {Tokenizer} from './syntax/tokenizer';\nimport {Color, color as colorType, isTransparent} from './types/color';\nimport {angle} from './types/angle';\nimport {image} from './types/image';\nimport {time} from './types/time';\nimport {opacity} from './property-descriptors/opacity';\nimport {textDecorationColor} from './property-descriptors/text-decoration-color';\nimport {textDecorationLine} from './property-descriptors/text-decoration-line';\nimport {isLengthPercentage, LengthPercentage, ZERO_LENGTH} from './types/length-percentage';\nimport {fontFamily} from './property-descriptors/font-family';\nimport {fontSize} from './property-descriptors/font-size';\nimport {isLength} from './types/length';\nimport {fontWeight} from './property-descriptors/font-weight';\nimport {fontVariant} from './property-descriptors/font-variant';\nimport {fontStyle} from './property-descriptors/font-style';\nimport {contains} from '../core/bitwise';\nimport {content} from './property-descriptors/content';\nimport {counterIncrement} from './property-descriptors/counter-increment';\nimport {counterReset} from './property-descriptors/counter-reset';\nimport {duration} from './property-descriptors/duration';\nimport {quotes} from './property-descriptors/quotes';\nimport {boxShadow} from './property-descriptors/box-shadow';\nimport {paintOrder} from './property-descriptors/paint-order';\nimport {webkitTextStrokeColor} from './property-descriptors/webkit-text-stroke-color';\nimport {webkitTextStrokeWidth} from './property-descriptors/webkit-text-stroke-width';\nimport {Context} from '../core/context';\n\nexport class CSSParsedDeclaration {\n animationDuration: ReturnType<typeof duration.parse>;\n backgroundClip: ReturnType<typeof backgroundClip.parse>;\n backgroundColor: Color;\n backgroundImage: ReturnType<typeof backgroundImage.parse>;\n backgroundOrigin: ReturnType<typeof backgroundOrigin.parse>;\n backgroundPosition: ReturnType<typeof backgroundPosition.parse>;\n backgroundRepeat: ReturnType<typeof backgroundRepeat.parse>;\n backgroundSize: ReturnType<typeof backgroundSize.parse>;\n borderTopColor: Color;\n borderRightColor: Color;\n borderBottomColor: Color;\n borderLeftColor: Color;\n borderTopLeftRadius: ReturnType<typeof borderTopLeftRadius.parse>;\n borderTopRightRadius: ReturnType<typeof borderTopRightRadius.parse>;\n borderBottomRightRadius: ReturnType<typeof borderBottomRightRadius.parse>;\n borderBottomLeftRadius: ReturnType<typeof borderBottomLeftRadius.parse>;\n borderTopStyle: ReturnType<typeof borderTopStyle.parse>;\n borderRightStyle: ReturnType<typeof borderRightStyle.parse>;\n borderBottomStyle: ReturnType<typeof borderBottomStyle.parse>;\n borderLeftStyle: ReturnType<typeof borderLeftStyle.parse>;\n borderTopWidth: ReturnType<typeof borderTopWidth.parse>;\n borderRightWidth: ReturnType<typeof borderRightWidth.parse>;\n borderBottomWidth: ReturnType<typeof borderBottomWidth.parse>;\n borderLeftWidth: ReturnType<typeof borderLeftWidth.parse>;\n boxShadow: ReturnType<typeof boxShadow.parse>;\n color: Color;\n direction: ReturnType<typeof direction.parse>;\n display: ReturnType<typeof display.parse>;\n float: ReturnType<typeof float.parse>;\n fontFamily: ReturnType<typeof fontFamily.parse>;\n fontSize: LengthPercentage;\n fontStyle: ReturnType<typeof fontStyle.parse>;\n fontVariant: ReturnType<typeof fontVariant.parse>;\n fontWeight: ReturnType<typeof fontWeight.parse>;\n letterSpacing: ReturnType<typeof letterSpacing.parse>;\n lineBreak: ReturnType<typeof lineBreak.parse>;\n lineHeight: CSSValue;\n listStyleImage: ReturnType<typeof listStyleImage.parse>;\n listStylePosition: ReturnType<typeof listStylePosition.parse>;\n listStyleType: ReturnType<typeof listStyleType.parse>;\n marginTop: CSSValue;\n marginRight: CSSValue;\n marginBottom: CSSValue;\n marginLeft: CSSValue;\n opacity: ReturnType<typeof opacity.parse>;\n overflowX: OVERFLOW;\n overflowY: OVERFLOW;\n overflowWrap: ReturnType<typeof overflowWrap.parse>;\n paddingTop: LengthPercentage;\n paddingRight: LengthPercentage;\n paddingBottom: LengthPercentage;\n paddingLeft: LengthPercentage;\n paintOrder: ReturnType<typeof paintOrder.parse>;\n position: ReturnType<typeof position.parse>;\n textAlign: ReturnType<typeof textAlign.parse>;\n textDecorationColor: Color;\n textDecorationLine: ReturnType<typeof textDecorationLine.parse>;\n textShadow: ReturnType<typeof textShadow.parse>;\n textTransform: ReturnType<typeof textTransform.parse>;\n transform: ReturnType<typeof transform.parse>;\n transformOrigin: ReturnType<typeof transformOrigin.parse>;\n visibility: ReturnType<typeof visibility.parse>;\n webkitTextStrokeColor: Color;\n webkitTextStrokeWidth: ReturnType<typeof webkitTextStrokeWidth.parse>;\n wordBreak: ReturnType<typeof wordBreak.parse>;\n zIndex: ReturnType<typeof zIndex.parse>;\n\n constructor(context: Context, declaration: CSSStyleDeclaration) {\n this.animationDuration = parse(context, duration, declaration.animationDuration);\n this.backgroundClip = parse(context, backgroundClip, declaration.backgroundClip);\n this.backgroundColor = parse(context, backgroundColor, declaration.backgroundColor);\n this.backgroundImage = parse(context, backgroundImage, declaration.backgroundImage);\n this.backgroundOrigin = parse(context, backgroundOrigin, declaration.backgroundOrigin);\n this.backgroundPosition = parse(context, backgroundPosition, declaration.backgroundPosition);\n this.backgroundRepeat = parse(context, backgroundRepeat, declaration.backgroundRepeat);\n this.backgroundSize = parse(context, backgroundSize, declaration.backgroundSize);\n this.borderTopColor = parse(context, borderTopColor, declaration.borderTopColor);\n this.borderRightColor = parse(context, borderRightColor, declaration.borderRightColor);\n this.borderBottomColor = parse(context, borderBottomColor, declaration.borderBottomColor);\n this.borderLeftColor = parse(context, borderLeftColor, declaration.borderLeftColor);\n this.borderTopLeftRadius = parse(context, borderTopLeftRadius, declaration.borderTopLeftRadius);\n this.borderTopRightRadius = parse(context, borderTopRightRadius, declaration.borderTopRightRadius);\n this.borderBottomRightRadius = parse(context, borderBottomRightRadius, declaration.borderBottomRightRadius);\n this.borderBottomLeftRadius = parse(context, borderBottomLeftRadius, declaration.borderBottomLeftRadius);\n this.borderTopStyle = parse(context, borderTopStyle, declaration.borderTopStyle);\n this.borderRightStyle = parse(context, borderRightStyle, declaration.borderRightStyle);\n this.borderBottomStyle = parse(context, borderBottomStyle, declaration.borderBottomStyle);\n this.borderLeftStyle = parse(context, borderLeftStyle, declaration.borderLeftStyle);\n this.borderTopWidth = parse(context, borderTopWidth, declaration.borderTopWidth);\n this.borderRightWidth = parse(context, borderRightWidth, declaration.borderRightWidth);\n this.borderBottomWidth = parse(context, borderBottomWidth, declaration.borderBottomWidth);\n this.borderLeftWidth = parse(context, borderLeftWidth, declaration.borderLeftWidth);\n this.boxShadow = parse(context, boxShadow, declaration.boxShadow);\n this.color = parse(context, color, declaration.color);\n this.direction = parse(context, direction, declaration.direction);\n this.display = parse(context, display, declaration.display);\n this.float = parse(context, float, declaration.cssFloat);\n this.fontFamily = parse(context, fontFamily, declaration.fontFamily);\n this.fontSize = parse(context, fontSize, declaration.fontSize);\n this.fontStyle = parse(context, fontStyle, declaration.fontStyle);\n this.fontVariant = parse(context, fontVariant, declaration.fontVariant);\n this.fontWeight = parse(context, fontWeight, declaration.fontWeight);\n this.letterSpacing = parse(context, letterSpacing, declaration.letterSpacing);\n this.lineBreak = parse(context, lineBreak, declaration.lineBreak);\n this.lineHeight = parse(context, lineHeight, declaration.lineHeight);\n this.listStyleImage = parse(context, listStyleImage, declaration.listStyleImage);\n this.listStylePosition = parse(context, listStylePosition, declaration.listStylePosition);\n this.listStyleType = parse(context, listStyleType, declaration.listStyleType);\n this.marginTop = parse(context, marginTop, declaration.marginTop);\n this.marginRight = parse(context, marginRight, declaration.marginRight);\n this.marginBottom = parse(context, marginBottom, declaration.marginBottom);\n this.marginLeft = parse(context, marginLeft, declaration.marginLeft);\n this.opacity = parse(context, opacity, declaration.opacity);\n const overflowTuple = parse(context, overflow, declaration.overflow);\n this.overflowX = overflowTuple[0];\n this.overflowY = overflowTuple[overflowTuple.length > 1 ? 1 : 0];\n this.overflowWrap = parse(context, overflowWrap, declaration.overflowWrap);\n this.paddingTop = parse(context, paddingTop, declaration.paddingTop);\n this.paddingRight = parse(context, paddingRight, declaration.paddingRight);\n this.paddingBottom = parse(context, paddingBottom, declaration.paddingBottom);\n this.paddingLeft = parse(context, paddingLeft, declaration.paddingLeft);\n this.paintOrder = parse(context, paintOrder, declaration.paintOrder);\n this.position = parse(context, position, declaration.position);\n this.textAlign = parse(context, textAlign, declaration.textAlign);\n this.textDecorationColor = parse(\n context,\n textDecorationColor,\n declaration.textDecorationColor ?? declaration.color\n );\n this.textDecorationLine = parse(\n context,\n textDecorationLine,\n declaration.textDecorationLine ?? declaration.textDecoration\n );\n this.textShadow = parse(context, textShadow, declaration.textShadow);\n this.textTransform = parse(context, textTransform, declaration.textTransform);\n this.transform = parse(context, transform, declaration.transform);\n this.transformOrigin = parse(context, transformOrigin, declaration.transformOrigin);\n this.visibility = parse(context, visibility, declaration.visibility);\n this.webkitTextStrokeColor = parse(context, webkitTextStrokeColor, declaration.webkitTextStrokeColor);\n this.webkitTextStrokeWidth = parse(context, webkitTextStrokeWidth, declaration.webkitTextStrokeWidth);\n this.wordBreak = parse(context, wordBreak, declaration.wordBreak);\n this.zIndex = parse(context, zIndex, declaration.zIndex);\n }\n\n isVisible(): boolean {\n return this.display > 0 && this.opacity > 0 && this.visibility === VISIBILITY.VISIBLE;\n }\n\n isTransparent(): boolean {\n return isTransparent(this.backgroundColor);\n }\n\n isTransformed(): boolean {\n return this.transform !== null;\n }\n\n isPositioned(): boolean {\n return this.position !== POSITION.STATIC;\n }\n\n isPositionedWithZIndex(): boolean {\n return this.isPositioned() && !this.zIndex.auto;\n }\n\n isFloating(): boolean {\n return this.float !== FLOAT.NONE;\n }\n\n isInlineLevel(): boolean {\n return (\n contains(this.display, DISPLAY.INLINE) ||\n contains(this.display, DISPLAY.INLINE_BLOCK) ||\n contains(this.display, DISPLAY.INLINE_FLEX) ||\n contains(this.display, DISPLAY.INLINE_GRID) ||\n contains(this.display, DISPLAY.INLINE_LIST_ITEM) ||\n contains(this.display, DISPLAY.INLINE_TABLE)\n );\n }\n}\n\nexport class CSSParsedPseudoDeclaration {\n content: ReturnType<typeof content.parse>;\n quotes: ReturnType<typeof quotes.parse>;\n\n constructor(context: Context, declaration: CSSStyleDeclaration) {\n this.content = parse(context, content, declaration.content);\n this.quotes = parse(context, quotes, declaration.quotes);\n }\n}\n\nexport class CSSParsedCounterDeclaration {\n counterIncrement: ReturnType<typeof counterIncrement.parse>;\n counterReset: ReturnType<typeof counterReset.parse>;\n\n constructor(context: Context, declaration: CSSStyleDeclaration) {\n this.counterIncrement = parse(context, counterIncrement, declaration.counterIncrement);\n this.counterReset = parse(context, counterReset, declaration.counterReset);\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst parse = (context: Context, descriptor: CSSPropertyDescriptor<any>, style?: string | null) => {\n const tokenizer = new Tokenizer();\n const value = style !== null && typeof style !== 'undefined' ? style.toString() : descriptor.initialValue;\n tokenizer.write(value);\n const parser = new Parser(tokenizer.read());\n switch (descriptor.type) {\n case PropertyDescriptorParsingType.IDENT_VALUE:\n const token = parser.parseComponentValue();\n return descriptor.parse(context, isIdentToken(token) ? token.value : descriptor.initialValue);\n case PropertyDescriptorParsingType.VALUE:\n return descriptor.parse(context, parser.parseComponentValue());\n case PropertyDescriptorParsingType.LIST:\n return descriptor.parse(context, parser.parseComponentValues());\n case PropertyDescriptorParsingType.TOKEN_VALUE:\n return parser.parseComponentValue();\n case PropertyDescriptorParsingType.TYPE_VALUE:\n switch (descriptor.format) {\n case 'angle':\n return angle.parse(context, parser.parseComponentValue());\n case 'color':\n return colorType.parse(context, parser.parseComponentValue());\n case 'image':\n return image.parse(context, parser.parseComponentValue());\n case 'length':\n const length = parser.parseComponentValue();\n return isLength(length) ? length : ZERO_LENGTH;\n case 'length-percentage':\n const value = parser.parseComponentValue();\n return isLengthPercentage(value) ? value : ZERO_LENGTH;\n case 'time':\n return time.parse(context, parser.parseComponentValue());\n }\n break;\n }\n};\n","const elementDebuggerAttribute = 'data-html2canvas-debug';\nexport const enum DebuggerType {\n NONE,\n ALL,\n CLONE,\n PARSE,\n RENDER\n}\n\nconst getElementDebugType = (element: Element): DebuggerType => {\n const attribute = element.getAttribute(elementDebuggerAttribute);\n switch (attribute) {\n case 'all':\n return DebuggerType.ALL;\n case 'clone':\n return DebuggerType.CLONE;\n case 'parse':\n return DebuggerType.PARSE;\n case 'render':\n return DebuggerType.RENDER;\n default:\n return DebuggerType.NONE;\n }\n};\n\nexport const isDebugging = (element: Element, type: Omit<DebuggerType, DebuggerType.NONE>): boolean => {\n const elementType = getElementDebugType(element);\n return elementType === DebuggerType.ALL || type === elementType;\n};\n","import {CSSParsedDeclaration} from '../css/index';\nimport {TextContainer} from './text-container';\nimport {Bounds, parseBounds} from '../css/layout/bounds';\nimport {isHTMLElementNode} from './node-parser';\nimport {Context} from '../core/context';\nimport {DebuggerType, isDebugging} from '../core/debugger';\n\nexport const enum FLAGS {\n CREATES_STACKING_CONTEXT = 1 << 1,\n CREATES_REAL_STACKING_CONTEXT = 1 << 2,\n IS_LIST_OWNER = 1 << 3,\n DEBUG_RENDER = 1 << 4\n}\n\nexport class ElementContainer {\n readonly styles: CSSParsedDeclaration;\n readonly textNodes: TextContainer[] = [];\n readonly elements: ElementContainer[] = [];\n bounds: Bounds;\n flags = 0;\n\n constructor(protected readonly context: Context, element: Element) {\n if (isDebugging(element, DebuggerType.PARSE)) {\n debugger;\n }\n\n this.styles = new CSSParsedDeclaration(context, window.getComputedStyle(element, null));\n\n if (isHTMLElementNode(element)) {\n if (this.styles.animationDuration.some((duration) => duration > 0)) {\n element.style.animationDuration = '0s';\n }\n\n if (this.styles.transform !== null) {\n // getBoundingClientRect takes transforms into account\n element.style.transform = 'none';\n }\n }\n\n this.bounds = parseBounds(this.context, element);\n\n if (isDebugging(element, DebuggerType.RENDER)) {\n this.flags |= FLAGS.DEBUG_RENDER;\n }\n }\n}\n","export const base64 =\n 'AAAAAAAAAAAAEA4AGBkAAFAaAAACAAAAAAAIABAAGAAwADgACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAAQABIAEQATAAIABAACAAQAAgAEAAIABAAVABcAAgAEAAIABAACAAQAGAAaABwAHgAgACIAI4AlgAIABAAmwCjAKgAsAC2AL4AvQDFAMoA0gBPAVYBWgEIAAgACACMANoAYgFkAWwBdAF8AX0BhQGNAZUBlgGeAaMBlQGWAasBswF8AbsBwwF0AcsBYwHTAQgA2wG/AOMBdAF8AekB8QF0AfkB+wHiAHQBfAEIAAMC5gQIAAsCEgIIAAgAFgIeAggAIgIpAggAMQI5AkACygEIAAgASAJQAlgCYAIIAAgACAAKBQoFCgUTBRMFGQUrBSsFCAAIAAgACAAIAAgACAAIAAgACABdAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABoAmgCrwGvAQgAbgJ2AggAHgEIAAgACADnAXsCCAAIAAgAgwIIAAgACAAIAAgACACKAggAkQKZAggAPADJAAgAoQKkAqwCsgK6AsICCADJAggA0AIIAAgACAAIANYC3gIIAAgACAAIAAgACABAAOYCCAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAkASoB+QIEAAgACAA8AEMCCABCBQgACABJBVAFCAAIAAgACAAIAAgACAAIAAgACABTBVoFCAAIAFoFCABfBWUFCAAIAAgACAAIAAgAbQUIAAgACAAIAAgACABzBXsFfQWFBYoFigWKBZEFigWKBYoFmAWfBaYFrgWxBbkFCAAIAAgACAAIAAgACAAIAAgACAAIAMEFCAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAMgFCADQBQgACAAIAAgACAAIAAgACAAIAAgACAAIAO4CCAAIAAgAiQAIAAgACABAAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAD0AggACAD8AggACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIANYFCAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAMDvwAIAAgAJAIIAAgACAAIAAgACAAIAAgACwMTAwgACAB9BOsEGwMjAwgAKwMyAwsFYgE3A/MEPwMIAEUDTQNRAwgAWQOsAGEDCAAIAAgACAAIAAgACABpAzQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFOgU0BTUFNgU3BTgFOQU6BTQFNQU2BTcFOAU5BToFNAU1BTYFNwU4BTkFIQUoBSwFCAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABtAwgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABMAEwACAAIAAgACAAIABgACAAIAAgACAC/AAgACAAyAQgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACACAAIAAwAAgACAAIAAgACAAIAAgACAAIAAAARABIAAgACAAIABQASAAIAAgAIABwAEAAjgCIABsAqAC2AL0AigDQAtwC+IJIQqVAZUBWQqVAZUBlQGVAZUBlQGrC5UBlQGVAZUBlQGVAZUBlQGVAXsKlQGVAbAK6wsrDGUMpQzlDJUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAZUBlQGVAfAKAAuZA64AtwCJALoC6ADwAAgAuACgA/oEpgO6AqsD+AAIAAgAswMIAAgACAAIAIkAuwP5AfsBwwPLAwgACAAIAAgACADRA9kDCAAIAOED6QMIAAgACAAIAAgACADuA/YDCAAIAP4DyQAIAAgABgQIAAgAXQAOBAgACAAIAAgACAAIABMECAAIAAgACAAIAAgACAD8AAQBCAAIAAgAGgQiBCoECAExBAgAEAEIAAgACAAIAAgACAAIAAgACAAIAAgACAA4BAgACABABEYECAAIAAgATAQYAQgAVAQIAAgACAAIAAgACAAIAAgACAAIAFoECAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAOQEIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAB+BAcACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAEABhgSMBAgACAAIAAgAlAQIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAwAEAAQABAADAAMAAwADAAQABAAEAAQABAAEAAQABHATAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAdQMIAAgACAAIAAgACAAIAMkACAAIAAgAfQMIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACACFA4kDCAAIAAgACAAIAOcBCAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAIcDCAAIAAgACAAIAAgACAAIAAgACAAIAJEDCAAIAAgACADFAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABgBAgAZgQIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAbAQCBXIECAAIAHkECAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACABAAJwEQACjBKoEsgQIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAC6BMIECAAIAAgACAAIAAgACABmBAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAxwQIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAGYECAAIAAgAzgQIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgAigWKBYoFigWKBYoFigWKBd0FXwUIAOIF6gXxBYoF3gT5BQAGCAaKBYoFigWKBYoFigWKBYoFigWKBYoFigXWBIoFigWKBYoFigWKBYoFigWKBYsFEAaKBYoFigWKBYoFigWKBRQGCACKBYoFigWKBQgACAAIANEECAAIABgGigUgBggAJgYIAC4GMwaKBYoF0wQ3Bj4GigWKBYoFigWKBYoFigWKBYoFigWKBYoFigUIAAgACAAIAAgACAAIAAgAigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWKBYoFigWLBf///////wQABAAEAAQABAAEAAQABAAEAAQAAwAEAAQAAgAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAQADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAUAAAAFAAUAAAAFAAUAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAQABAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUAAQAAAAUABQAFAAUABQAFAAAAAAAFAAUAAAAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAFAAUAAQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABwAFAAUABQAFAAAABwAHAAcAAAAHAAcABwAFAAEAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAFAAUABQAFAAcABwAFAAUAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAQABAAAAAAAAAAAAAAAFAAUABQAFAAAABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAHAAcABwAHAAcAAAAHAAcAAAAAAAUABQAHAAUAAQAHAAEABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABwABAAUABQAFAAUAAAAAAAAAAAAAAAEAAQABAAEAAQABAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABwAFAAUAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUAAQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABQANAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAQABAAEAAQABAAEAAQABAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAABQAHAAUABQAFAAAAAAAAAAcABQAFAAUABQAFAAQABAAEAAQABAAEAAQABAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUAAAAFAAUABQAFAAUAAAAFAAUABQAAAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAAAAAAAAAAAAUABQAFAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAHAAUAAAAHAAcABwAFAAUABQAFAAUABQAFAAUABwAHAAcABwAFAAcABwAAAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABwAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAUABwAHAAUABQAFAAUAAAAAAAcABwAAAAAABwAHAAUAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAABQAFAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAABwAHAAcABQAFAAAAAAAAAAAABQAFAAAAAAAFAAUABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAFAAUABQAFAAUAAAAFAAUABwAAAAcABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAFAAUABwAFAAUABQAFAAAAAAAHAAcAAAAAAAcABwAFAAAAAAAAAAAAAAAAAAAABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAcABwAAAAAAAAAHAAcABwAAAAcABwAHAAUAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAABQAHAAcABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABwAHAAcABwAAAAUABQAFAAAABQAFAAUABQAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAcABQAHAAcABQAHAAcAAAAFAAcABwAAAAcABwAFAAUAAAAAAAAAAAAAAAAAAAAFAAUAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAUABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAFAAcABwAFAAUABQAAAAUAAAAHAAcABwAHAAcABwAHAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAHAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAABwAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAUAAAAFAAAAAAAAAAAABwAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABwAFAAUABQAFAAUAAAAFAAUAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABwAFAAUABQAFAAUABQAAAAUABQAHAAcABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABQAFAAAAAAAAAAAABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAcABQAFAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAHAAUABQAFAAUABQAFAAUABwAHAAcABwAHAAcABwAHAAUABwAHAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABwAHAAcABwAFAAUABwAHAAcAAAAAAAAAAAAHAAcABQAHAAcABwAHAAcABwAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAcABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABQAHAAUABQAFAAUABQAFAAUAAAAFAAAABQAAAAAABQAFAAUABQAFAAUABQAFAAcABwAHAAcABwAHAAUABQAFAAUABQAFAAUABQAFAAUAAAAAAAUABQAFAAUABQAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABwAFAAcABwAHAAcABwAFAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAUABQAFAAUABwAHAAUABQAHAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAcABQAFAAcABwAHAAUABwAFAAUABQAHAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAcABwAHAAcABwAHAAUABQAFAAUABQAFAAUABQAHAAcABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUAAAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAcABQAFAAUABQAFAAUABQAAAAAAAAAAAAUAAAAAAAAAAAAAAAAABQAAAAAABwAFAAUAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAAABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUAAAAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAUABQAHAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABwAHAAcABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAUABQAFAAUABQAHAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAcABwAFAAUABQAFAAcABwAFAAUABwAHAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAFAAcABwAFAAUABwAHAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAFAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAFAAUABQAAAAAABQAFAAAAAAAAAAAAAAAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABQAFAAcABwAAAAAAAAAAAAAABwAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABwAFAAcABwAFAAcABwAAAAcABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAAAAAAAAAAAAAAAAAFAAUABQAAAAUABQAAAAAAAAAAAAAABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABQAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABwAFAAUABQAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAcABQAFAAUABQAFAAUABQAFAAUABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAFAAUABQAHAAcABQAHAAUABQAAAAAAAAAAAAAAAAAFAAAABwAHAAcABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABwAHAAcABwAAAAAABwAHAAAAAAAHAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAAAAAAFAAUABQAFAAUABQAFAAAAAAAAAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAFAAUABQAFAAUABQAFAAUABwAHAAUABQAFAAcABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAHAAcABQAFAAUABQAFAAUABwAFAAcABwAFAAcABQAFAAcABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAHAAcABQAFAAUABQAAAAAABwAHAAcABwAFAAUABwAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABwAHAAUABQAFAAUABQAFAAUABQAHAAcABQAHAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABwAFAAcABwAFAAUABQAFAAUABQAHAAUAAAAAAAAAAAAAAAAAAAAAAAcABwAFAAUABQAFAAcABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAFAAUABQAFAAUABQAFAAUABQAHAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAFAAUABQAFAAAAAAAFAAUABwAHAAcABwAFAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABwAHAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABQAFAAUABQAFAAUABQAAAAUABQAFAAUABQAFAAcABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUAAAAHAAUABQAFAAUABQAFAAUABwAFAAUABwAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUAAAAAAAAABQAAAAUABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAcABwAHAAcAAAAFAAUAAAAHAAcABQAHAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABwAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAAAAAAAAAAAAAAAAAAABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAAAAUABQAFAAAAAAAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQAFAAUABQAAAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAAAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAFAAUABQAAAAAABQAFAAUABQAFAAUABQAAAAUABQAAAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAUABQAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAFAAUABQAFAAUABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAFAAUABQAFAAUADgAOAA4ADgAOAA4ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAA8ADwAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAcABwAHAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAAAAAAAAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAMAAwADAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAAAAAAAAAAAAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAKAAoACgAAAAAAAAAAAAsADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwACwAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAMAAwADAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAOAAAAAAAAAAAADgAOAA4AAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAAAA4ADgAOAA4ADgAOAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4AAAAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4AAAAAAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAAAA4AAAAOAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAADgAAAAAAAAAAAA4AAAAOAAAAAAAAAAAADgAOAA4AAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAAAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAA4ADgAOAA4ADgAOAA4ADgAOAAAADgAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4AAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4ADgAOAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAOAA4ADgAOAA4AAAAAAAAAAAAAAAAAAAAAAA4ADgAOAA4ADgAOAA4ADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4AAAAOAA4ADgAOAA4ADgAAAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4ADgAOAA4AAAAAAAAAAAA=';\nexport const byteLength = 19616;\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\n\nexport const decode = (base64: string): ArrayBuffer | number[] => {\n let bufferLength = base64.length * 0.75,\n len = base64.length,\n i,\n p = 0,\n encoded1,\n encoded2,\n encoded3,\n encoded4;\n\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n const buffer =\n typeof ArrayBuffer !== 'undefined' &&\n typeof Uint8Array !== 'undefined' &&\n typeof Uint8Array.prototype.slice !== 'undefined'\n ? new ArrayBuffer(bufferLength)\n : new Array(bufferLength);\n const bytes = Array.isArray(buffer) ? buffer : new Uint8Array(buffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n\n return buffer;\n};\n\nexport const polyUint16Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 2) {\n bytes.push((buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n\nexport const polyUint32Array = (buffer: number[]): number[] => {\n const length = buffer.length;\n const bytes = [];\n for (let i = 0; i < length; i += 4) {\n bytes.push((buffer[i + 3] << 24) | (buffer[i + 2] << 16) | (buffer[i + 1] << 8) | buffer[i]);\n }\n return bytes;\n};\n","import {decode, polyUint16Array, polyUint32Array} from './Util';\n\nexport type int = number;\n\n/** Shift size for getting the index-2 table offset. */\nexport const UTRIE2_SHIFT_2 = 5;\n\n/** Shift size for getting the index-1 table offset. */\nexport const UTRIE2_SHIFT_1 = 6 + 5;\n\n/**\n * Shift size for shifting left the index array values.\n * Increases possible data size with 16-bit index values at the cost\n * of compactability.\n * This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY.\n */\nexport const UTRIE2_INDEX_SHIFT = 2;\n\n/**\n * Difference between the two shift sizes,\n * for getting an index-1 offset from an index-2 offset. 6=11-5\n */\nexport const UTRIE2_SHIFT_1_2 = UTRIE2_SHIFT_1 - UTRIE2_SHIFT_2;\n\n/**\n * The part of the index-2 table for U+D800..U+DBFF stores values for\n * lead surrogate code _units_ not code _points_.\n * Values for lead surrogate code _points_ are indexed with this portion of the table.\n * Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.)\n */\nexport const UTRIE2_LSCP_INDEX_2_OFFSET = 0x10000 >> UTRIE2_SHIFT_2;\n\n/** Number of entries in a data block. 32=0x20 */\nexport const UTRIE2_DATA_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_2;\n/** Mask for getting the lower bits for the in-data-block offset. */\nexport const UTRIE2_DATA_MASK = UTRIE2_DATA_BLOCK_LENGTH - 1;\n\nexport const UTRIE2_LSCP_INDEX_2_LENGTH = 0x400 >> UTRIE2_SHIFT_2;\n/** Count the lengths of both BMP pieces. 2080=0x820 */\nexport const UTRIE2_INDEX_2_BMP_LENGTH = UTRIE2_LSCP_INDEX_2_OFFSET + UTRIE2_LSCP_INDEX_2_LENGTH;\n/**\n * The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.\n * Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2.\n */\nexport const UTRIE2_UTF8_2B_INDEX_2_OFFSET = UTRIE2_INDEX_2_BMP_LENGTH;\nexport const UTRIE2_UTF8_2B_INDEX_2_LENGTH = 0x800 >> 6; /* U+0800 is the first code point after 2-byte UTF-8 */\n/**\n * The index-1 table, only used for supplementary code points, at offset 2112=0x840.\n * Variable length, for code points up to highStart, where the last single-value range starts.\n * Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1.\n * (For 0x100000 supplementary code points U+10000..U+10ffff.)\n *\n * The part of the index-2 table for supplementary code points starts\n * after this index-1 table.\n *\n * Both the index-1 table and the following part of the index-2 table\n * are omitted completely if there is only BMP data.\n */\nexport const UTRIE2_INDEX_1_OFFSET = UTRIE2_UTF8_2B_INDEX_2_OFFSET + UTRIE2_UTF8_2B_INDEX_2_LENGTH;\n\n/**\n * Number of index-1 entries for the BMP. 32=0x20\n * This part of the index-1 table is omitted from the serialized form.\n */\nexport const UTRIE2_OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> UTRIE2_SHIFT_1;\n\n/** Number of entries in an index-2 block. 64=0x40 */\nexport const UTRIE2_INDEX_2_BLOCK_LENGTH = 1 << UTRIE2_SHIFT_1_2;\n/** Mask for getting the lower bits for the in-index-2-block offset. */\nexport const UTRIE2_INDEX_2_MASK = UTRIE2_INDEX_2_BLOCK_LENGTH - 1;\n\nconst slice16 = (view: number[] | Uint16Array, start: number, end?: number) => {\n if (view.slice) {\n return view.slice(start, end);\n }\n\n return new Uint16Array(Array.prototype.slice.call(view, start, end));\n};\n\nconst slice32 = (view: number[] | Uint32Array, start: number, end?: number) => {\n if (view.slice) {\n return view.slice(start, end);\n }\n\n return new Uint32Array(Array.prototype.slice.call(view, start, end));\n};\n\nexport const createTrieFromBase64 = (base64: string, _byteLength: number): Trie => {\n const buffer = decode(base64);\n const view32 = Array.isArray(buffer) ? polyUint32Array(buffer) : new Uint32Array(buffer);\n const view16 = Array.isArray(buffer) ? polyUint16Array(buffer) : new Uint16Array(buffer);\n const headerLength = 24;\n\n const index = slice16(view16, headerLength / 2, view32[4] / 2);\n const data =\n view32[5] === 2\n ? slice16(view16, (headerLength + view32[4]) / 2)\n : slice32(view32, Math.ceil((headerLength + view32[4]) / 4));\n\n return new Trie(view32[0], view32[1], view32[2], view32[3], index, data);\n};\n\nexport class Trie {\n initialValue: int;\n errorValue: int;\n highStart: int;\n highValueIndex: int;\n index: Uint16Array | number[];\n data: Uint32Array | Uint16Array | number[];\n\n constructor(\n initialValue: int,\n errorValue: int,\n highStart: int,\n highValueIndex: int,\n index: Uint16Array | number[],\n data: Uint32Array | Uint16Array | number[]\n ) {\n this.initialValue = initialValue;\n this.errorValue = errorValue;\n this.highStart = highStart;\n this.highValueIndex = highValueIndex;\n this.index = index;\n this.data = data;\n }\n\n /**\n * Get the value for a code point as stored in the Trie.\n *\n * @param codePoint the code point\n * @return the value\n */\n get(codePoint: number): number {\n let ix;\n if (codePoint >= 0) {\n if (codePoint < 0x0d800 || (codePoint > 0x0dbff && codePoint <= 0x0ffff)) {\n // Ordinary BMP code point, excluding leading surrogates.\n // BMP uses a single level lookup. BMP index starts at offset 0 in the Trie2 index.\n // 16 bit data is stored in the index array itself.\n ix = this.index[codePoint >> UTRIE2_SHIFT_2];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n\n if (codePoint <= 0xffff) {\n // Lead Surrogate Code Point. A Separate index section is stored for\n // lead surrogate code units and code points.\n // The main index has the code unit data.\n // For this function, we need the code point data.\n // Note: this expression could be refactored for slightly improved efficiency, but\n // surrogate code points will be so rare in practice that it's not worth it.\n ix = this.index[UTRIE2_LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> UTRIE2_SHIFT_2)];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n\n if (codePoint < this.highStart) {\n // Supplemental code point, use two-level lookup.\n ix = UTRIE2_INDEX_1_OFFSET - UTRIE2_OMITTED_BMP_INDEX_1_LENGTH + (codePoint >> UTRIE2_SHIFT_1);\n ix = this.index[ix];\n ix += (codePoint >> UTRIE2_SHIFT_2) & UTRIE2_INDEX_2_MASK;\n ix = this.index[ix];\n ix = (ix << UTRIE2_INDEX_SHIFT) + (codePoint & UTRIE2_DATA_MASK);\n return this.data[ix];\n }\n if (codePoint <= 0x10ffff) {\n return this.data[this.highValueIndex];\n }\n }\n\n // Fall through. The code point is outside of the legal range of 0..0x10ffff.\n return this.errorValue;\n }\n}\n","const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n// Use a lookup table to find the index.\nconst lookup = typeof Uint8Array === 'undefined' ? [] : new Uint8Array(256);\nfor (let i = 0; i < chars.length; i++) {\n lookup[chars.charCodeAt(i)] = i;\n}\n\nexport const encode = (arraybuffer: ArrayBuffer): string => {\n let bytes = new Uint8Array(arraybuffer),\n i,\n len = bytes.length,\n base64 = '';\n\n for (i = 0; i < len; i += 3) {\n base64 += chars[bytes[i] >> 2];\n base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];\n base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];\n base64 += chars[bytes[i + 2] & 63];\n }\n\n if (len % 3 === 2) {\n base64 = base64.substring(0, base64.length - 1) + '=';\n } else if (len % 3 === 1) {\n base64 = base64.substring(0, base64.length - 2) + '==';\n }\n\n return base64;\n};\n\nexport const decode = (base64: string): ArrayBuffer => {\n let bufferLength = base64.length * 0.75,\n len = base64.length,\n i,\n p = 0,\n encoded1,\n encoded2,\n encoded3,\n encoded4;\n\n if (base64[base64.length - 1] === '=') {\n bufferLength--;\n if (base64[base64.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n const arraybuffer = new ArrayBuffer(bufferLength),\n bytes = new Uint8Array(arraybuffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = lookup[base64.charCodeAt(i)];\n encoded2 = lookup[base64.charCodeAt(i + 1)];\n encoded3 = lookup[base64.charCodeAt(i + 2)];\n encoded4 = lookup[base64.charCodeAt(i + 3)];\n\n bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);\n bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);\n bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);\n }\n\n return arraybuffer;\n};\n","import {base64, byteLength} from './grapheme-break-trie';\nimport {createTrieFromBase64} from 'utrie';\n\nconst Other = 0;\nconst Prepend = 1;\nconst CR = 2;\nconst LF = 3;\nconst Control = 4;\nconst Extend = 5;\nconst Regional_Indicator = 6;\nconst SpacingMark = 7;\nconst L = 8;\nconst V = 9;\nconst T = 10;\nconst LV = 11;\nconst LVT = 12;\nconst ZWJ = 13;\nconst Extended_Pictographic = 14;\nconst RI = 15;\n\nexport const classes: {[key: string]: number} = {\n Other,\n Prepend,\n CR,\n LF,\n Control,\n Extend,\n Regional_Indicator,\n SpacingMark,\n L,\n V,\n T,\n LV,\n LVT,\n ZWJ,\n Extended_Pictographic,\n RI,\n};\n\nexport const toCodePoints = (str: string): number[] => {\n const codePoints = [];\n let i = 0;\n const length = str.length;\n while (i < length) {\n const value = str.charCodeAt(i++);\n if (value >= 0xd800 && value <= 0xdbff && i < length) {\n const extra = str.charCodeAt(i++);\n if ((extra & 0xfc00) === 0xdc00) {\n codePoints.push(((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);\n } else {\n codePoints.push(value);\n i--;\n }\n } else {\n codePoints.push(value);\n }\n }\n return codePoints;\n};\n\nexport const fromCodePoint = (...codePoints: number[]): string => {\n if (String.fromCodePoint) {\n return String.fromCodePoint(...codePoints);\n }\n\n const length = codePoints.length;\n if (!length) {\n return '';\n }\n\n const codeUnits = [];\n\n let index = -1;\n let result = '';\n while (++index < length) {\n let codePoint = codePoints[index];\n if (codePoint <= 0xffff) {\n codeUnits.push(codePoint);\n } else {\n codePoint -= 0x10000;\n codeUnits.push((codePoint >> 10) + 0xd800, (codePoint % 0x400) + 0xdc00);\n }\n if (index + 1 === length || codeUnits.length > 0x4000) {\n result += String.fromCharCode(...codeUnits);\n codeUnits.length = 0;\n }\n }\n return result;\n};\n\nexport const UnicodeTrie = createTrieFromBase64(base64, byteLength);\n\nexport const BREAK_NOT_ALLOWED = '×';\nexport const BREAK_ALLOWED = '÷';\n\nexport type BREAK_OPPORTUNITIES = typeof BREAK_NOT_ALLOWED | typeof BREAK_ALLOWED;\n\nexport const codePointToClass = (codePoint: number): number => UnicodeTrie.get(codePoint);\n\nconst _graphemeBreakAtIndex = (_codePoints: number[], classTypes: number[], index: number): BREAK_OPPORTUNITIES => {\n let prevIndex = index - 2;\n let prev = classTypes[prevIndex];\n const current = classTypes[index - 1];\n const next = classTypes[index];\n // GB3 Do not break between a CR and LF\n if (current === CR && next === LF) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB4 Otherwise, break before and after controls.\n if (current === CR || current === LF || current === Control) {\n return BREAK_ALLOWED;\n }\n\n // GB5\n if (next === CR || next === LF || next === Control) {\n return BREAK_ALLOWED;\n }\n\n // Do not break Hangul syllable sequences.\n // GB6\n if (current === L && [L, V, LV, LVT].indexOf(next) !== -1) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB7\n if ((current === LV || current === V) && (next === V || next === T)) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB8\n if ((current === LVT || current === T) && next === T) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB9 Do not break before extending characters or ZWJ.\n if (next === ZWJ || next === Extend) {\n return BREAK_NOT_ALLOWED;\n }\n // Do not break before SpacingMarks, or after Prepend characters.\n // GB9a\n if (next === SpacingMark) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB9a\n if (current === Prepend) {\n return BREAK_NOT_ALLOWED;\n }\n\n // GB11 Do not break within emoji modifier sequences or emoji zwj sequences.\n if (current === ZWJ && next === Extended_Pictographic) {\n while (prev === Extend) {\n prev = classTypes[--prevIndex];\n }\n if (prev === Extended_Pictographic) {\n return BREAK_NOT_ALLOWED;\n }\n }\n\n // GB12 Do not break within emoji flag sequences.\n // That is, do not break between regional indicator (RI) symbols\n // if there is an odd number of RI characters before the break point.\n if (current === RI && next === RI) {\n let countRI = 0;\n while (prev === RI) {\n countRI++;\n prev = classTypes[--prevIndex];\n }\n if (countRI % 2 === 0) {\n return BREAK_NOT_ALLOWED;\n }\n }\n\n return BREAK_ALLOWED;\n};\n\nexport const graphemeBreakAtIndex = (codePoints: number[], index: number): BREAK_OPPORTUNITIES => {\n // GB1 Break at the start and end of text, unless the text is empty.\n if (index === 0) {\n return BREAK_ALLOWED;\n }\n\n // GB2\n if (index >= codePoints.length) {\n return BREAK_ALLOWED;\n }\n\n const classTypes = codePoints.map(codePointToClass);\n return _graphemeBreakAtIndex(codePoints, classTypes, index);\n};\n\nexport const GraphemeBreaker = (str: string) => {\n const codePoints = toCodePoints(str);\n const length = codePoints.length;\n let index = 0;\n let lastEnd = 0;\n const classTypes = codePoints.map(codePointToClass);\n\n return {\n next: () => {\n if (index >= length) {\n return {done: true, value: null};\n }\n\n let graphemeBreak = BREAK_NOT_ALLOWED;\n while (\n index < length &&\n (graphemeBreak = _graphemeBreakAtIndex(codePoints, classTypes, ++index)) === BREAK_NOT_ALLOWED\n ) {}\n\n if (graphemeBreak !== BREAK_NOT_ALLOWED || index === length) {\n const value = fromCodePoint.apply(null, codePoints.slice(lastEnd, index));\n lastEnd = index;\n return {value, done: false};\n }\n\n return {done: true, value: null};\n while (index < length) {}\n\n return {done: true, value: null};\n },\n };\n};\n\nexport const splitGraphemes = (str: string): string[] => {\n const breaker = GraphemeBreaker(str);\n\n const graphemes = [];\n let bk;\n\n while (!(bk = breaker.next()).done) {\n if (bk.value) {\n graphemes.push(bk.value.slice());\n }\n }\n\n return graphemes;\n};\n","import {fromCodePoint, toCodePoints} from 'css-line-break';\n\nconst testRangeBounds = (document: Document) => {\n const TEST_HEIGHT = 123;\n\n if (document.createRange) {\n const range = document.createRange();\n if (range.getBoundingClientRect) {\n const testElement = document.createElement('boundtest');\n testElement.style.height = `${TEST_HEIGHT}px`;\n testElement.style.display = 'block';\n document.body.appendChild(testElement);\n\n range.selectNode(testElement);\n const rangeBounds = range.getBoundingClientRect();\n const rangeHeight = Math.round(rangeBounds.height);\n document.body.removeChild(testElement);\n if (rangeHeight === TEST_HEIGHT) {\n return true;\n }\n }\n }\n\n return false;\n};\n\nconst testIOSLineBreak = (document: Document) => {\n const testElement = document.createElement('boundtest');\n testElement.style.width = '50px';\n testElement.style.display = 'block';\n testElement.style.fontSize = '12px';\n testElement.style.letterSpacing = '0px';\n testElement.style.wordSpacing = '0px';\n document.body.appendChild(testElement);\n const range = document.createRange();\n\n testElement.innerHTML = typeof ''.repeat === 'function' ? '&#128104;'.repeat(10) : '';\n\n const node = testElement.firstChild as Text;\n\n const textList = toCodePoints(node.data).map((i) => fromCodePoint(i));\n let offset = 0;\n let prev: DOMRect = {} as DOMRect;\n\n // ios 13 does not handle range getBoundingClientRect line changes correctly #2177\n const supports = textList.every((text, i) => {\n range.setStart(node, offset);\n range.setEnd(node, offset + text.length);\n const rect = range.getBoundingClientRect();\n\n offset += text.length;\n const boundAhead = rect.x > prev.x || rect.y > prev.y;\n\n prev = rect;\n if (i === 0) {\n return true;\n }\n\n return boundAhead;\n });\n\n document.body.removeChild(testElement);\n return supports;\n};\n\nconst testCORS = (): boolean => typeof new Image().crossOrigin !== 'undefined';\n\nconst testResponseType = (): boolean => typeof new XMLHttpRequest().responseType === 'string';\n\nconst testSVG = (document: Document): boolean => {\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n return false;\n }\n\n img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>`;\n\n try {\n ctx.drawImage(img, 0, 0);\n canvas.toDataURL();\n } catch (e) {\n return false;\n }\n return true;\n};\n\nconst isGreenPixel = (data: Uint8ClampedArray): boolean =>\n data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;\n\nconst testForeignObject = (document: Document): Promise<boolean> => {\n const canvas = document.createElement('canvas');\n const size = 100;\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n return Promise.reject(false);\n }\n ctx.fillStyle = 'rgb(0, 255, 0)';\n ctx.fillRect(0, 0, size, size);\n\n const img = new Image();\n const greenImageSrc = canvas.toDataURL();\n img.src = greenImageSrc;\n const svg = createForeignObjectSVG(size, size, 0, 0, img);\n ctx.fillStyle = 'red';\n ctx.fillRect(0, 0, size, size);\n\n return loadSerializedSVG(svg)\n .then((img: HTMLImageElement) => {\n ctx.drawImage(img, 0, 0);\n const data = ctx.getImageData(0, 0, size, size).data;\n ctx.fillStyle = 'red';\n ctx.fillRect(0, 0, size, size);\n\n const node = document.createElement('div');\n node.style.backgroundImage = `url(${greenImageSrc})`;\n node.style.height = `${size}px`;\n // Firefox 55 does not render inline <img /> tags\n return isGreenPixel(data)\n ? loadSerializedSVG(createForeignObjectSVG(size, size, 0, 0, node))\n : Promise.reject(false);\n })\n .then((img: HTMLImageElement) => {\n ctx.drawImage(img, 0, 0);\n // Edge does not render background-images\n return isGreenPixel(ctx.getImageData(0, 0, size, size).data);\n })\n .catch(() => false);\n};\n\nexport const createForeignObjectSVG = (\n width: number,\n height: number,\n x: number,\n y: number,\n node: Node\n): SVGForeignObjectElement => {\n const xmlns = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(xmlns, 'svg');\n const foreignObject = document.createElementNS(xmlns, 'foreignObject');\n svg.setAttributeNS(null, 'width', width.toString());\n svg.setAttributeNS(null, 'height', height.toString());\n\n foreignObject.setAttributeNS(null, 'width', '100%');\n foreignObject.setAttributeNS(null, 'height', '100%');\n foreignObject.setAttributeNS(null, 'x', x.toString());\n foreignObject.setAttributeNS(null, 'y', y.toString());\n foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');\n svg.appendChild(foreignObject);\n\n foreignObject.appendChild(node);\n\n return svg;\n};\n\nexport const loadSerializedSVG = (svg: Node): Promise<HTMLImageElement> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = reject;\n\n img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;\n });\n};\n\nexport const FEATURES = {\n get SUPPORT_RANGE_BOUNDS(): boolean {\n 'use strict';\n const value = testRangeBounds(document);\n Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', {value});\n return value;\n },\n get SUPPORT_WORD_BREAKING(): boolean {\n 'use strict';\n const value = FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);\n Object.defineProperty(FEATURES, 'SUPPORT_WORD_BREAKING', {value});\n return value;\n },\n get SUPPORT_SVG_DRAWING(): boolean {\n 'use strict';\n const value = testSVG(document);\n Object.defineProperty(FEATURES, 'SUPPORT_SVG_DRAWING', {value});\n return value;\n },\n get SUPPORT_FOREIGNOBJECT_DRAWING(): Promise<boolean> {\n 'use strict';\n const value =\n typeof Array.from === 'function' && typeof window.fetch === 'function'\n ? testForeignObject(document)\n : Promise.resolve(false);\n Object.defineProperty(FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', {value});\n return value;\n },\n get SUPPORT_CORS_IMAGES(): boolean {\n 'use strict';\n const value = testCORS();\n Object.defineProperty(FEATURES, 'SUPPORT_CORS_IMAGES', {value});\n return value;\n },\n get SUPPORT_RESPONSE_TYPE(): boolean {\n 'use strict';\n const value = testResponseType();\n Object.defineProperty(FEATURES, 'SUPPORT_RESPONSE_TYPE', {value});\n return value;\n },\n get SUPPORT_CORS_XHR(): boolean {\n 'use strict';\n const value = 'withCredentials' in new XMLHttpRequest();\n Object.defineProperty(FEATURES, 'SUPPORT_CORS_XHR', {value});\n return value;\n },\n get SUPPORT_NATIVE_TEXT_SEGMENTATION(): boolean {\n 'use strict';\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const value = !!(typeof Intl !== 'undefined' && (Intl as any).Segmenter);\n Object.defineProperty(FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', {value});\n return value;\n }\n};\n","import {OVERFLOW_WRAP} from '../property-descriptors/overflow-wrap';\nimport {CSSParsedDeclaration} from '../index';\nimport {fromCodePoint, LineBreaker, toCodePoints} from 'css-line-break';\nimport {splitGraphemes} from 'text-segmentation';\nimport {Bounds, parseBounds} from './bounds';\nimport {FEATURES} from '../../core/features';\nimport {Context} from '../../core/context';\n\nexport class TextBounds {\n readonly text: string;\n readonly bounds: Bounds;\n\n constructor(text: string, bounds: Bounds) {\n this.text = text;\n this.bounds = bounds;\n }\n}\n\nexport const parseTextBounds = (\n context: Context,\n value: string,\n styles: CSSParsedDeclaration,\n node: Text\n): TextBounds[] => {\n const textList = breakText(value, styles);\n const textBounds: TextBounds[] = [];\n let offset = 0;\n textList.forEach((text) => {\n if (styles.textDecorationLine.length || text.trim().length > 0) {\n if (FEATURES.SUPPORT_RANGE_BOUNDS) {\n const clientRects = createRange(node, offset, text.length).getClientRects();\n if (clientRects.length > 1) {\n const subSegments = segmentGraphemes(text);\n let subOffset = 0;\n subSegments.forEach((subSegment) => {\n textBounds.push(\n new TextBounds(\n subSegment,\n Bounds.fromDOMRectList(\n context,\n createRange(node, subOffset + offset, subSegment.length).getClientRects()\n )\n )\n );\n subOffset += subSegment.length;\n });\n } else {\n textBounds.push(new TextBounds(text, Bounds.fromDOMRectList(context, clientRects)));\n }\n } else {\n const replacementNode = node.splitText(text.length);\n textBounds.push(new TextBounds(text, getWrapperBounds(context, node)));\n node = replacementNode;\n }\n } else if (!FEATURES.SUPPORT_RANGE_BOUNDS) {\n node = node.splitText(text.length);\n }\n offset += text.length;\n });\n\n return textBounds;\n};\n\nconst getWrapperBounds = (context: Context, node: Text): Bounds => {\n const ownerDocument = node.ownerDocument;\n if (ownerDocument) {\n const wrapper = ownerDocument.createElement('html2canvaswrapper');\n wrapper.appendChild(node.cloneNode(true));\n const parentNode = node.parentNode;\n if (parentNode) {\n parentNode.replaceChild(wrapper, node);\n const bounds = parseBounds(context, wrapper);\n if (wrapper.firstChild) {\n parentNode.replaceChild(wrapper.firstChild, wrapper);\n }\n return bounds;\n }\n }\n\n return Bounds.EMPTY;\n};\n\nconst createRange = (node: Text, offset: number, length: number): Range => {\n const ownerDocument = node.ownerDocument;\n if (!ownerDocument) {\n throw new Error('Node has no owner document');\n }\n const range = ownerDocument.createRange();\n range.setStart(node, offset);\n range.setEnd(node, offset + length);\n return range;\n};\n\nexport const segmentGraphemes = (value: string): string[] => {\n if (FEATURES.SUPPORT_NATIVE_TEXT_SEGMENTATION) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const segmenter = new (Intl as any).Segmenter(void 0, {granularity: 'grapheme'});\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Array.from(segmenter.segment(value)).map((segment: any) => segment.segment);\n }\n\n return splitGraphemes(value);\n};\n\nconst segmentWords = (value: string, styles: CSSParsedDeclaration): string[] => {\n if (FEATURES.SUPPORT_NATIVE_TEXT_SEGMENTATION) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const segmenter = new (Intl as any).Segmenter(void 0, {\n granularity: 'word'\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return Array.from(segmenter.segment(value)).map((segment: any) => segment.segment);\n }\n\n return breakWords(value, styles);\n};\n\nconst breakText = (value: string, styles: CSSParsedDeclaration): string[] => {\n return styles.letterSpacing !== 0 ? segmentGraphemes(value) : segmentWords(value, styles);\n};\n\n// https://drafts.csswg.org/css-text/#word-separator\nconst wordSeparators = [0x0020, 0x00a0, 0x1361, 0x10100, 0x10101, 0x1039, 0x1091];\n\nconst breakWords = (str: string, styles: CSSParsedDeclaration): string[] => {\n const breaker = LineBreaker(str, {\n lineBreak: styles.lineBreak,\n wordBreak: styles.overflowWrap === OVERFLOW_WRAP.BREAK_WORD ? 'break-word' : styles.wordBreak\n });\n\n const words = [];\n let bk;\n\n while (!(bk = breaker.next()).done) {\n if (bk.value) {\n const value = bk.value.slice();\n const codePoints = toCodePoints(value);\n let word = '';\n codePoints.forEach((codePoint) => {\n if (wordSeparators.indexOf(codePoint) === -1) {\n word += fromCodePoint(codePoint);\n } else {\n if (word.length) {\n words.push(word);\n }\n words.push(fromCodePoint(codePoint));\n word = '';\n }\n });\n\n if (word.length) {\n words.push(word);\n }\n }\n }\n\n return words;\n};\n","import {CSSParsedDeclaration} from '../css/index';\nimport {TEXT_TRANSFORM} from '../css/property-descriptors/text-transform';\nimport {parseTextBounds, TextBounds} from '../css/layout/text';\nimport {Context} from '../core/context';\n\nexport class TextContainer {\n text: string;\n textBounds: TextBounds[];\n\n constructor(context: Context, node: Text, styles: CSSParsedDeclaration) {\n this.text = transform(node.data, styles.textTransform);\n this.textBounds = parseTextBounds(context, this.text, styles, node);\n }\n}\n\nconst transform = (text: string, transform: TEXT_TRANSFORM) => {\n switch (transform) {\n case TEXT_TRANSFORM.LOWERCASE:\n return text.toLowerCase();\n case TEXT_TRANSFORM.CAPITALIZE:\n return text.replace(CAPITALIZE, capitalize);\n case TEXT_TRANSFORM.UPPERCASE:\n return text.toUpperCase();\n default:\n return text;\n }\n};\n\nconst CAPITALIZE = /(^|\\s|:|-|\\(|\\))([a-z])/g;\n\nconst capitalize = (m: string, p1: string, p2: string) => {\n if (m.length > 0) {\n return p1 + p2.toUpperCase();\n }\n\n return m;\n};\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\n\nexport class ImageElementContainer extends ElementContainer {\n src: string;\n intrinsicWidth: number;\n intrinsicHeight: number;\n\n constructor(context: Context, img: HTMLImageElement) {\n super(context, img);\n this.src = img.currentSrc || img.src;\n this.intrinsicWidth = img.naturalWidth;\n this.intrinsicHeight = img.naturalHeight;\n this.context.cache.addImage(this.src);\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\n\nexport class CanvasElementContainer extends ElementContainer {\n canvas: HTMLCanvasElement;\n intrinsicWidth: number;\n intrinsicHeight: number;\n\n constructor(context: Context, canvas: HTMLCanvasElement) {\n super(context, canvas);\n this.canvas = canvas;\n this.intrinsicWidth = canvas.width;\n this.intrinsicHeight = canvas.height;\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {parseBounds} from '../../css/layout/bounds';\nimport {Context} from '../../core/context';\n\nexport class SVGElementContainer extends ElementContainer {\n svg: string;\n intrinsicWidth: number;\n intrinsicHeight: number;\n\n constructor(context: Context, img: SVGSVGElement) {\n super(context, img);\n const s = new XMLSerializer();\n const bounds = parseBounds(context, img);\n img.setAttribute('width', `${bounds.width}px`);\n img.setAttribute('height', `${bounds.height}px`);\n\n this.svg = `data:image/svg+xml,${encodeURIComponent(s.serializeToString(img))}`;\n this.intrinsicWidth = img.width.baseVal.value;\n this.intrinsicHeight = img.height.baseVal.value;\n\n this.context.cache.addImage(this.svg);\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\nexport class LIElementContainer extends ElementContainer {\n readonly value: number;\n\n constructor(context: Context, element: HTMLLIElement) {\n super(context, element);\n this.value = element.value;\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\nexport class OLElementContainer extends ElementContainer {\n readonly start: number;\n readonly reversed: boolean;\n\n constructor(context: Context, element: HTMLOListElement) {\n super(context, element);\n this.start = element.start;\n this.reversed = typeof element.reversed === 'boolean' && element.reversed === true;\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {BORDER_STYLE} from '../../css/property-descriptors/border-style';\nimport {BACKGROUND_CLIP} from '../../css/property-descriptors/background-clip';\nimport {BACKGROUND_ORIGIN} from '../../css/property-descriptors/background-origin';\nimport {TokenType} from '../../css/syntax/tokenizer';\nimport {LengthPercentageTuple} from '../../css/types/length-percentage';\nimport {Bounds} from '../../css/layout/bounds';\nimport {Context} from '../../core/context';\n\nconst CHECKBOX_BORDER_RADIUS: LengthPercentageTuple = [\n {\n type: TokenType.DIMENSION_TOKEN,\n flags: 0,\n unit: 'px',\n number: 3\n }\n];\n\nconst RADIO_BORDER_RADIUS: LengthPercentageTuple = [\n {\n type: TokenType.PERCENTAGE_TOKEN,\n flags: 0,\n number: 50\n }\n];\n\nconst reformatInputBounds = (bounds: Bounds): Bounds => {\n if (bounds.width > bounds.height) {\n return new Bounds(bounds.left + (bounds.width - bounds.height) / 2, bounds.top, bounds.height, bounds.height);\n } else if (bounds.width < bounds.height) {\n return new Bounds(bounds.left, bounds.top + (bounds.height - bounds.width) / 2, bounds.width, bounds.width);\n }\n return bounds;\n};\n\nconst getInputValue = (node: HTMLInputElement): string => {\n const value = node.type === PASSWORD ? new Array(node.value.length + 1).join('\\u2022') : node.value;\n\n return value.length === 0 ? node.placeholder || '' : value;\n};\n\nexport const CHECKBOX = 'checkbox';\nexport const RADIO = 'radio';\nexport const PASSWORD = 'password';\nexport const INPUT_COLOR = 0x2a2a2aff;\n\nexport class InputElementContainer extends ElementContainer {\n readonly type: string;\n readonly checked: boolean;\n readonly value: string;\n\n constructor(context: Context, input: HTMLInputElement) {\n super(context, input);\n this.type = input.type.toLowerCase();\n this.checked = input.checked;\n this.value = getInputValue(input);\n\n if (this.type === CHECKBOX || this.type === RADIO) {\n this.styles.backgroundColor = 0xdededeff;\n this.styles.borderTopColor =\n this.styles.borderRightColor =\n this.styles.borderBottomColor =\n this.styles.borderLeftColor =\n 0xa5a5a5ff;\n this.styles.borderTopWidth =\n this.styles.borderRightWidth =\n this.styles.borderBottomWidth =\n this.styles.borderLeftWidth =\n 1;\n this.styles.borderTopStyle =\n this.styles.borderRightStyle =\n this.styles.borderBottomStyle =\n this.styles.borderLeftStyle =\n BORDER_STYLE.SOLID;\n this.styles.backgroundClip = [BACKGROUND_CLIP.BORDER_BOX];\n this.styles.backgroundOrigin = [BACKGROUND_ORIGIN.BORDER_BOX];\n this.bounds = reformatInputBounds(this.bounds);\n }\n\n switch (this.type) {\n case CHECKBOX:\n this.styles.borderTopRightRadius =\n this.styles.borderTopLeftRadius =\n this.styles.borderBottomRightRadius =\n this.styles.borderBottomLeftRadius =\n CHECKBOX_BORDER_RADIUS;\n break;\n case RADIO:\n this.styles.borderTopRightRadius =\n this.styles.borderTopLeftRadius =\n this.styles.borderBottomRightRadius =\n this.styles.borderBottomLeftRadius =\n RADIO_BORDER_RADIUS;\n break;\n }\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\nexport class SelectElementContainer extends ElementContainer {\n readonly value: string;\n constructor(context: Context, element: HTMLSelectElement) {\n super(context, element);\n const option = element.options[element.selectedIndex || 0];\n this.value = option ? option.text || '' : '';\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {Context} from '../../core/context';\nexport class TextareaElementContainer extends ElementContainer {\n readonly value: string;\n constructor(context: Context, element: HTMLTextAreaElement) {\n super(context, element);\n this.value = element.value;\n }\n}\n","import {ElementContainer} from '../element-container';\nimport {parseTree} from '../node-parser';\nimport {Color, parseColor, COLORS, isTransparent} from '../../css/types/color';\nimport {Context} from '../../core/context';\n\nexport class IFrameElementContainer extends ElementContainer {\n src: string;\n width: number;\n height: number;\n tree?: ElementContainer;\n backgroundColor: Color;\n\n constructor(context: Context, iframe: HTMLIFrameElement) {\n super(context, iframe);\n this.src = iframe.src;\n this.width = parseInt(iframe.width, 10) || 0;\n this.height = parseInt(iframe.height, 10) || 0;\n this.backgroundColor = this.styles.backgroundColor;\n try {\n if (\n iframe.contentWindow &&\n iframe.contentWindow.document &&\n iframe.contentWindow.document.documentElement\n ) {\n this.tree = parseTree(context, iframe.contentWindow.document.documentElement);\n\n // http://www.w3.org/TR/css3-background/#special-backgrounds\n const documentBackgroundColor = iframe.contentWindow.document.documentElement\n ? parseColor(\n context,\n getComputedStyle(iframe.contentWindow.document.documentElement).backgroundColor as string\n )\n : COLORS.TRANSPARENT;\n const bodyBackgroundColor = iframe.contentWindow.document.body\n ? parseColor(\n context,\n getComputedStyle(iframe.contentWindow.document.body).backgroundColor as string\n )\n : COLORS.TRANSPARENT;\n\n this.backgroundColor = isTransparent(documentBackgroundColor)\n ? isTransparent(bodyBackgroundColor)\n ? this.styles.backgroundColor\n : bodyBackgroundColor\n : documentBackgroundColor;\n }\n } catch (e) {}\n }\n}\n","import {CSSParsedDeclaration} from '../css';\nimport {ElementContainer, FLAGS} from './element-container';\nimport {TextContainer} from './text-container';\nimport {ImageElementContainer} from './replaced-elements/image-element-container';\nimport {CanvasElementContainer} from './replaced-elements/canvas-element-container';\nimport {SVGElementContainer} from './replaced-elements/svg-element-container';\nimport {LIElementContainer} from './elements/li-element-container';\nimport {OLElementContainer} from './elements/ol-element-container';\nimport {InputElementContainer} from './replaced-elements/input-element-container';\nimport {SelectElementContainer} from './elements/select-element-container';\nimport {TextareaElementContainer} from './elements/textarea-element-container';\nimport {IFrameElementContainer} from './replaced-elements/iframe-element-container';\nimport {Context} from '../core/context';\n\nconst LIST_OWNERS = ['OL', 'UL', 'MENU'];\n\nconst parseNodeTree = (context: Context, node: Node, parent: ElementContainer, root: ElementContainer) => {\n for (let childNode = node.firstChild, nextNode; childNode; childNode = nextNode) {\n nextNode = childNode.nextSibling;\n\n if (isTextNode(childNode) && childNode.data.trim().length > 0) {\n parent.textNodes.push(new TextContainer(context, childNode, parent.styles));\n } else if (isElementNode(childNode)) {\n if (isSlotElement(childNode) && childNode.assignedNodes) {\n childNode.assignedNodes().forEach((childNode) => parseNodeTree(context, childNode, parent, root));\n } else {\n const container = createContainer(context, childNode);\n if (container.styles.isVisible()) {\n if (createsRealStackingContext(childNode, container, root)) {\n container.flags |= FLAGS.CREATES_REAL_STACKING_CONTEXT;\n } else if (createsStackingContext(container.styles)) {\n container.flags |= FLAGS.CREATES_STACKING_CONTEXT;\n }\n\n if (LIST_OWNERS.indexOf(childNode.tagName) !== -1) {\n container.flags |= FLAGS.IS_LIST_OWNER;\n }\n\n parent.elements.push(container);\n childNode.slot;\n if (childNode.shadowRoot) {\n parseNodeTree(context, childNode.shadowRoot, container, root);\n } else if (\n !isTextareaElement(childNode) &&\n !isSVGElement(childNode) &&\n !isSelectElement(childNode)\n ) {\n parseNodeTree(context, childNode, container, root);\n }\n }\n }\n }\n }\n};\n\nconst createContainer = (context: Context, element: Element): ElementContainer => {\n if (isImageElement(element)) {\n return new ImageElementContainer(context, element);\n }\n\n if (isCanvasElement(element)) {\n return new CanvasElementContainer(context, element);\n }\n\n if (isSVGElement(element)) {\n return new SVGElementContainer(context, element);\n }\n\n if (isLIElement(element)) {\n return new LIElementContainer(context, element);\n }\n\n if (isOLElement(element)) {\n return new OLElementContainer(context, element);\n }\n\n if (isInputElement(element)) {\n return new InputElementContainer(context, element);\n }\n\n if (isSelectElement(element)) {\n return new SelectElementContainer(context, element);\n }\n\n if (isTextareaElement(element)) {\n return new TextareaElementContainer(context, element);\n }\n\n if (isIFrameElement(element)) {\n return new IFrameElementContainer(context, element);\n }\n\n return new ElementContainer(context, element);\n};\n\nexport const parseTree = (context: Context, element: HTMLElement): ElementContainer => {\n const container = createContainer(context, element);\n container.flags |= FLAGS.CREATES_REAL_STACKING_CONTEXT;\n parseNodeTree(context, element, container, container);\n return container;\n};\n\nconst createsRealStackingContext = (node: Element, container: ElementContainer, root: ElementContainer): boolean => {\n return (\n container.styles.isPositionedWithZIndex() ||\n container.styles.opacity < 1 ||\n container.styles.isTransformed() ||\n (isBodyElement(node) && root.styles.isTransparent())\n );\n};\n\nconst createsStackingContext = (styles: CSSParsedDeclaration): boolean => styles.isPositioned() || styles.isFloating();\n\nexport const isTextNode = (node: Node): node is Text => node.nodeType === Node.TEXT_NODE;\nexport const isElementNode = (node: Node): node is Element => node.nodeType === Node.ELEMENT_NODE;\nexport const isHTMLElementNode = (node: Node): node is HTMLElement =>\n isElementNode(node) && typeof (node as HTMLElement).style !== 'undefined' && !isSVGElementNode(node);\nexport const isSVGElementNode = (element: Element): element is SVGElement =>\n typeof (element as SVGElement).className === 'object';\nexport const isLIElement = (node: Element): node is HTMLLIElement => node.tagName === 'LI';\nexport const isOLElement = (node: Element): node is HTMLOListElement => node.tagName === 'OL';\nexport const isInputElement = (node: Element): node is HTMLInputElement => node.tagName === 'INPUT';\nexport const isHTMLElement = (node: Element): node is HTMLHtmlElement => node.tagName === 'HTML';\nexport const isSVGElement = (node: Element): node is SVGSVGElement => node.tagName === 'svg';\nexport const isBodyElement = (node: Element): node is HTMLBodyElement => node.tagName === 'BODY';\nexport const isCanvasElement = (node: Element): node is HTMLCanvasElement => node.tagName === 'CANVAS';\nexport const isVideoElement = (node: Element): node is HTMLVideoElement => node.tagName === 'VIDEO';\nexport const isImageElement = (node: Element): node is HTMLImageElement => node.tagName === 'IMG';\nexport const isIFrameElement = (node: Element): node is HTMLIFrameElement => node.tagName === 'IFRAME';\nexport const isStyleElement = (node: Element): node is HTMLStyleElement => node.tagName === 'STYLE';\nexport const isScriptElement = (node: Element): node is HTMLScriptElement => node.tagName === 'SCRIPT';\nexport const isTextareaElement = (node: Element): node is HTMLTextAreaElement => node.tagName === 'TEXTAREA';\nexport const isSelectElement = (node: Element): node is HTMLSelectElement => node.tagName === 'SELECT';\nexport const isSlotElement = (node: Element): node is HTMLSlotElement => node.tagName === 'SLOT';\n// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name\nexport const isCustomElement = (node: Element): node is HTMLElement => node.tagName.indexOf('-') > 0;\n","import {LIST_STYLE_TYPE} from '../../property-descriptors/list-style-type';\nimport {fromCodePoint} from 'css-line-break';\nimport {contains} from '../../../core/bitwise';\nimport {CSSParsedCounterDeclaration} from '../../index';\n\nexport class CounterState {\n private readonly counters: {[key: string]: number[]} = {};\n\n getCounterValue(name: string): number {\n const counter = this.counters[name];\n\n if (counter && counter.length) {\n return counter[counter.length - 1];\n }\n return 1;\n }\n\n getCounterValues(name: string): readonly number[] {\n const counter = this.counters[name];\n return counter ? counter : [];\n }\n\n pop(counters: string[]): void {\n counters.forEach((counter) => this.counters[counter].pop());\n }\n\n parse(style: CSSParsedCounterDeclaration): string[] {\n const counterIncrement = style.counterIncrement;\n const counterReset = style.counterReset;\n let canReset = true;\n\n if (counterIncrement !== null) {\n counterIncrement.forEach((entry) => {\n const counter = this.counters[entry.counter];\n if (counter && entry.increment !== 0) {\n canReset = false;\n if (!counter.length) {\n counter.push(1);\n }\n counter[Math.max(0, counter.length - 1)] += entry.increment;\n }\n });\n }\n\n const counterNames: string[] = [];\n if (canReset) {\n counterReset.forEach((entry) => {\n let counter = this.counters[entry.counter];\n counterNames.push(entry.counter);\n if (!counter) {\n counter = this.counters[entry.counter] = [];\n }\n counter.push(entry.reset);\n });\n }\n\n return counterNames;\n }\n}\n\ninterface CounterSymbols {\n integers: number[];\n values: string[];\n}\n\nconst ROMAN_UPPER: CounterSymbols = {\n integers: [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],\n values: ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']\n};\n\nconst ARMENIAN: CounterSymbols = {\n integers: [\n 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 90, 80, 70,\n 60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n ],\n values: [\n 'Ք',\n 'Փ',\n 'Ւ',\n 'Ց',\n 'Ր',\n 'Տ',\n 'Վ',\n 'Ս',\n 'Ռ',\n 'Ջ',\n 'Պ',\n 'Չ',\n 'Ո',\n 'Շ',\n 'Ն',\n 'Յ',\n 'Մ',\n 'Ճ',\n 'Ղ',\n 'Ձ',\n 'Հ',\n 'Կ',\n 'Ծ',\n 'Խ',\n 'Լ',\n 'Ի',\n 'Ժ',\n 'Թ',\n 'Ը',\n 'Է',\n 'Զ',\n 'Ե',\n 'Դ',\n 'Գ',\n 'Բ',\n 'Ա'\n ]\n};\n\nconst HEBREW: CounterSymbols = {\n integers: [\n 10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 400, 300, 200, 100, 90, 80, 70, 60, 50, 40, 30, 20,\n 19, 18, 17, 16, 15, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n ],\n values: [\n 'י׳',\n 'ט׳',\n 'ח׳',\n 'ז׳',\n 'ו׳',\n 'ה׳',\n 'ד׳',\n 'ג׳',\n 'ב׳',\n 'א׳',\n 'ת',\n 'ש',\n 'ר',\n 'ק',\n 'צ',\n 'פ',\n 'ע',\n 'ס',\n 'נ',\n 'מ',\n 'ל',\n 'כ',\n 'יט',\n 'יח',\n 'יז',\n 'טז',\n 'טו',\n 'י',\n 'ט',\n 'ח',\n 'ז',\n 'ו',\n 'ה',\n 'ד',\n 'ג',\n 'ב',\n 'א'\n ]\n};\n\nconst GEORGIAN: CounterSymbols = {\n integers: [\n 10000, 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, 900, 800, 700, 600, 500, 400, 300, 200, 100, 90,\n 80, 70, 60, 50, 40, 30, 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n ],\n values: [\n 'ჵ',\n 'ჰ',\n 'ჯ',\n 'ჴ',\n 'ხ',\n 'ჭ',\n 'წ',\n 'ძ',\n 'ც',\n 'ჩ',\n 'შ',\n 'ყ',\n 'ღ',\n 'ქ',\n 'ფ',\n 'ჳ',\n 'ტ',\n 'ს',\n 'რ',\n 'ჟ',\n 'პ',\n 'ო',\n 'ჲ',\n 'ნ',\n 'მ',\n 'ლ',\n 'კ',\n 'ი',\n 'თ',\n 'ჱ',\n 'ზ',\n 'ვ',\n 'ე',\n 'დ',\n 'გ',\n 'ბ',\n 'ა'\n ]\n};\n\nconst createAdditiveCounter = (\n value: number,\n min: number,\n max: number,\n symbols: CounterSymbols,\n fallback: LIST_STYLE_TYPE,\n suffix: string\n) => {\n if (value < min || value > max) {\n return createCounterText(value, fallback, suffix.length > 0);\n }\n\n return (\n symbols.integers.reduce((string, integer, index) => {\n while (value >= integer) {\n value -= integer;\n string += symbols.values[index];\n }\n return string;\n }, '') + suffix\n );\n};\n\nconst createCounterStyleWithSymbolResolver = (\n value: number,\n codePointRangeLength: number,\n isNumeric: boolean,\n resolver: (codePoint: number) => string\n): string => {\n let string = '';\n\n do {\n if (!isNumeric) {\n value--;\n }\n string = resolver(value) + string;\n value /= codePointRangeLength;\n } while (value * codePointRangeLength >= codePointRangeLength);\n\n return string;\n};\n\nconst createCounterStyleFromRange = (\n value: number,\n codePointRangeStart: number,\n codePointRangeEnd: number,\n isNumeric: boolean,\n suffix: string\n): string => {\n const codePointRangeLength = codePointRangeEnd - codePointRangeStart + 1;\n\n return (\n (value < 0 ? '-' : '') +\n (createCounterStyleWithSymbolResolver(Math.abs(value), codePointRangeLength, isNumeric, (codePoint) =>\n fromCodePoint(Math.floor(codePoint % codePointRangeLength) + codePointRangeStart)\n ) +\n suffix)\n );\n};\n\nconst createCounterStyleFromSymbols = (value: number, symbols: string, suffix = '. '): string => {\n const codePointRangeLength = symbols.length;\n return (\n createCounterStyleWithSymbolResolver(\n Math.abs(value),\n codePointRangeLength,\n false,\n (codePoint) => symbols[Math.floor(codePoint % codePointRangeLength)]\n ) + suffix\n );\n};\n\nconst CJK_ZEROS = 1 << 0;\nconst CJK_TEN_COEFFICIENTS = 1 << 1;\nconst CJK_TEN_HIGH_COEFFICIENTS = 1 << 2;\nconst CJK_HUNDRED_COEFFICIENTS = 1 << 3;\n\nconst createCJKCounter = (\n value: number,\n numbers: string,\n multipliers: string,\n negativeSign: string,\n suffix: string,\n flags: number\n): string => {\n if (value < -9999 || value > 9999) {\n return createCounterText(value, LIST_STYLE_TYPE.CJK_DECIMAL, suffix.length > 0);\n }\n let tmp = Math.abs(value);\n let string = suffix;\n\n if (tmp === 0) {\n return numbers[0] + string;\n }\n\n for (let digit = 0; tmp > 0 && digit <= 4; digit++) {\n const coefficient = tmp % 10;\n\n if (coefficient === 0 && contains(flags, CJK_ZEROS) && string !== '') {\n string = numbers[coefficient] + string;\n } else if (\n coefficient > 1 ||\n (coefficient === 1 && digit === 0) ||\n (coefficient === 1 && digit === 1 && contains(flags, CJK_TEN_COEFFICIENTS)) ||\n (coefficient === 1 && digit === 1 && contains(flags, CJK_TEN_HIGH_COEFFICIENTS) && value > 100) ||\n (coefficient === 1 && digit > 1 && contains(flags, CJK_HUNDRED_COEFFICIENTS))\n ) {\n string = numbers[coefficient] + (digit > 0 ? multipliers[digit - 1] : '') + string;\n } else if (coefficient === 1 && digit > 0) {\n string = multipliers[digit - 1] + string;\n }\n tmp = Math.floor(tmp / 10);\n }\n\n return (value < 0 ? negativeSign : '') + string;\n};\n\nconst CHINESE_INFORMAL_MULTIPLIERS = '十百千萬';\nconst CHINESE_FORMAL_MULTIPLIERS = '拾佰仟萬';\nconst JAPANESE_NEGATIVE = 'マイナス';\nconst KOREAN_NEGATIVE = '마이너스';\n\nexport const createCounterText = (value: number, type: LIST_STYLE_TYPE, appendSuffix: boolean): string => {\n const defaultSuffix = appendSuffix ? '. ' : '';\n const cjkSuffix = appendSuffix ? '、' : '';\n const koreanSuffix = appendSuffix ? ', ' : '';\n const spaceSuffix = appendSuffix ? ' ' : '';\n switch (type) {\n case LIST_STYLE_TYPE.DISC:\n return '•' + spaceSuffix;\n case LIST_STYLE_TYPE.CIRCLE:\n return '◦' + spaceSuffix;\n case LIST_STYLE_TYPE.SQUARE:\n return '◾' + spaceSuffix;\n case LIST_STYLE_TYPE.DECIMAL_LEADING_ZERO:\n const string = createCounterStyleFromRange(value, 48, 57, true, defaultSuffix);\n return string.length < 4 ? `0${string}` : string;\n case LIST_STYLE_TYPE.CJK_DECIMAL:\n return createCounterStyleFromSymbols(value, '〇一二三四五六七八九', cjkSuffix);\n case LIST_STYLE_TYPE.LOWER_ROMAN:\n return createAdditiveCounter(\n value,\n 1,\n 3999,\n ROMAN_UPPER,\n LIST_STYLE_TYPE.DECIMAL,\n defaultSuffix\n ).toLowerCase();\n case LIST_STYLE_TYPE.UPPER_ROMAN:\n return createAdditiveCounter(value, 1, 3999, ROMAN_UPPER, LIST_STYLE_TYPE.DECIMAL, defaultSuffix);\n case LIST_STYLE_TYPE.LOWER_GREEK:\n return createCounterStyleFromRange(value, 945, 969, false, defaultSuffix);\n case LIST_STYLE_TYPE.LOWER_ALPHA:\n return createCounterStyleFromRange(value, 97, 122, false, defaultSuffix);\n case LIST_STYLE_TYPE.UPPER_ALPHA:\n return createCounterStyleFromRange(value, 65, 90, false, defaultSuffix);\n case LIST_STYLE_TYPE.ARABIC_INDIC:\n return createCounterStyleFromRange(value, 1632, 1641, true, defaultSuffix);\n case LIST_STYLE_TYPE.ARMENIAN:\n case LIST_STYLE_TYPE.UPPER_ARMENIAN:\n return createAdditiveCounter(value, 1, 9999, ARMENIAN, LIST_STYLE_TYPE.DECIMAL, defaultSuffix);\n case LIST_STYLE_TYPE.LOWER_ARMENIAN:\n return createAdditiveCounter(\n value,\n 1,\n 9999,\n ARMENIAN,\n LIST_STYLE_TYPE.DECIMAL,\n defaultSuffix\n ).toLowerCase();\n case LIST_STYLE_TYPE.BENGALI:\n return createCounterStyleFromRange(value, 2534, 2543, true, defaultSuffix);\n case LIST_STYLE_TYPE.CAMBODIAN:\n case LIST_STYLE_TYPE.KHMER:\n return createCounterStyleFromRange(value, 6112, 6121, true, defaultSuffix);\n case LIST_STYLE_TYPE.CJK_EARTHLY_BRANCH:\n return createCounterStyleFromSymbols(value, '子丑寅卯辰巳午未申酉戌亥', cjkSuffix);\n case LIST_STYLE_TYPE.CJK_HEAVENLY_STEM:\n return createCounterStyleFromSymbols(value, '甲乙丙丁戊己庚辛壬癸', cjkSuffix);\n case LIST_STYLE_TYPE.CJK_IDEOGRAPHIC:\n case LIST_STYLE_TYPE.TRAD_CHINESE_INFORMAL:\n return createCJKCounter(\n value,\n '零一二三四五六七八九',\n CHINESE_INFORMAL_MULTIPLIERS,\n '負',\n cjkSuffix,\n CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.TRAD_CHINESE_FORMAL:\n return createCJKCounter(\n value,\n '零壹貳參肆伍陸柒捌玖',\n CHINESE_FORMAL_MULTIPLIERS,\n '負',\n cjkSuffix,\n CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.SIMP_CHINESE_INFORMAL:\n return createCJKCounter(\n value,\n '零一二三四五六七八九',\n CHINESE_INFORMAL_MULTIPLIERS,\n '负',\n cjkSuffix,\n CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.SIMP_CHINESE_FORMAL:\n return createCJKCounter(\n value,\n '零壹贰叁肆伍陆柒捌玖',\n CHINESE_FORMAL_MULTIPLIERS,\n '负',\n cjkSuffix,\n CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS | CJK_HUNDRED_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.JAPANESE_INFORMAL:\n return createCJKCounter(value, '〇一二三四五六七八九', '十百千万', JAPANESE_NEGATIVE, cjkSuffix, 0);\n case LIST_STYLE_TYPE.JAPANESE_FORMAL:\n return createCJKCounter(\n value,\n '零壱弐参四伍六七八九',\n '拾百千万',\n JAPANESE_NEGATIVE,\n cjkSuffix,\n CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.KOREAN_HANGUL_FORMAL:\n return createCJKCounter(\n value,\n '영일이삼사오육칠팔구',\n '십백천만',\n KOREAN_NEGATIVE,\n koreanSuffix,\n CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.KOREAN_HANJA_INFORMAL:\n return createCJKCounter(value, '零一二三四五六七八九', '十百千萬', KOREAN_NEGATIVE, koreanSuffix, 0);\n case LIST_STYLE_TYPE.KOREAN_HANJA_FORMAL:\n return createCJKCounter(\n value,\n '零壹貳參四五六七八九',\n '拾百千',\n KOREAN_NEGATIVE,\n koreanSuffix,\n CJK_ZEROS | CJK_TEN_COEFFICIENTS | CJK_TEN_HIGH_COEFFICIENTS\n );\n case LIST_STYLE_TYPE.DEVANAGARI:\n return createCounterStyleFromRange(value, 0x966, 0x96f, true, defaultSuffix);\n case LIST_STYLE_TYPE.GEORGIAN:\n return createAdditiveCounter(value, 1, 19999, GEORGIAN, LIST_STYLE_TYPE.DECIMAL, defaultSuffix);\n case LIST_STYLE_TYPE.GUJARATI:\n return createCounterStyleFromRange(value, 0xae6, 0xaef, true, defaultSuffix);\n case LIST_STYLE_TYPE.GURMUKHI:\n return createCounterStyleFromRange(value, 0xa66, 0xa6f, true, defaultSuffix);\n case LIST_STYLE_TYPE.HEBREW:\n return createAdditiveCounter(value, 1, 10999, HEBREW, LIST_STYLE_TYPE.DECIMAL, defaultSuffix);\n case LIST_STYLE_TYPE.HIRAGANA:\n return createCounterStyleFromSymbols(\n value,\n 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをん'\n );\n case LIST_STYLE_TYPE.HIRAGANA_IROHA:\n return createCounterStyleFromSymbols(\n value,\n 'いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす'\n );\n case LIST_STYLE_TYPE.KANNADA:\n return createCounterStyleFromRange(value, 0xce6, 0xcef, true, defaultSuffix);\n case LIST_STYLE_TYPE.KATAKANA:\n return createCounterStyleFromSymbols(\n value,\n 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヰヱヲン',\n cjkSuffix\n );\n case LIST_STYLE_TYPE.KATAKANA_IROHA:\n return createCounterStyleFromSymbols(\n value,\n 'イロハニホヘトチリヌルヲワカヨタレソツネナラムウヰノオクヤマケフコエテアサキユメミシヱヒモセス',\n cjkSuffix\n );\n case LIST_STYLE_TYPE.LAO:\n return createCounterStyleFromRange(value, 0xed0, 0xed9, true, defaultSuffix);\n case LIST_STYLE_TYPE.MONGOLIAN:\n return createCounterStyleFromRange(value, 0x1810, 0x1819, true, defaultSuffix);\n case LIST_STYLE_TYPE.MYANMAR:\n return createCounterStyleFromRange(value, 0x1040, 0x1049, true, defaultSuffix);\n case LIST_STYLE_TYPE.ORIYA:\n return createCounterStyleFromRange(value, 0xb66, 0xb6f, true, defaultSuffix);\n case LIST_STYLE_TYPE.PERSIAN:\n return createCounterStyleFromRange(value, 0x6f0, 0x6f9, true, defaultSuffix);\n case LIST_STYLE_TYPE.TAMIL:\n return createCounterStyleFromRange(value, 0xbe6, 0xbef, true, defaultSuffix);\n case LIST_STYLE_TYPE.TELUGU:\n return createCounterStyleFromRange(value, 0xc66, 0xc6f, true, defaultSuffix);\n case LIST_STYLE_TYPE.THAI:\n return createCounterStyleFromRange(value, 0xe50, 0xe59, true, defaultSuffix);\n case LIST_STYLE_TYPE.TIBETAN:\n return createCounterStyleFromRange(value, 0xf20, 0xf29, true, defaultSuffix);\n case LIST_STYLE_TYPE.DECIMAL:\n default:\n return createCounterStyleFromRange(value, 48, 57, true, defaultSuffix);\n }\n};\n","import {Bounds} from '../css/layout/bounds';\nimport {\n isBodyElement,\n isCanvasElement,\n isCustomElement,\n isElementNode,\n isHTMLElementNode,\n isIFrameElement,\n isImageElement,\n isScriptElement,\n isSelectElement,\n isSlotElement,\n isStyleElement,\n isSVGElementNode,\n isTextareaElement,\n isTextNode,\n isVideoElement\n} from './node-parser';\nimport {isIdentToken, nonFunctionArgSeparator} from '../css/syntax/parser';\nimport {TokenType} from '../css/syntax/tokenizer';\nimport {CounterState, createCounterText} from '../css/types/functions/counter';\nimport {LIST_STYLE_TYPE, listStyleType} from '../css/property-descriptors/list-style-type';\nimport {CSSParsedCounterDeclaration, CSSParsedPseudoDeclaration} from '../css/index';\nimport {getQuote} from '../css/property-descriptors/quotes';\nimport {Context} from '../core/context';\nimport {DebuggerType, isDebugging} from '../core/debugger';\n\nexport interface CloneOptions {\n ignoreElements?: (element: Element) => boolean;\n onclone?: (document: Document, element: HTMLElement) => void;\n allowTaint?: boolean;\n}\n\nexport interface WindowOptions {\n scrollX: number;\n scrollY: number;\n windowWidth: number;\n windowHeight: number;\n}\n\nexport type CloneConfigurations = CloneOptions & {\n inlineImages: boolean;\n copyStyles: boolean;\n};\n\nconst IGNORE_ATTRIBUTE = 'data-html2canvas-ignore';\n\nexport class DocumentCloner {\n private readonly scrolledElements: [Element, number, number][];\n private readonly referenceElement: HTMLElement;\n clonedReferenceElement?: HTMLElement;\n private readonly documentElement: HTMLElement;\n private readonly counters: CounterState;\n private quoteDepth: number;\n\n constructor(\n private readonly context: Context,\n element: HTMLElement,\n private readonly options: CloneConfigurations\n ) {\n this.scrolledElements = [];\n this.referenceElement = element;\n this.counters = new CounterState();\n this.quoteDepth = 0;\n if (!element.ownerDocument) {\n throw new Error('Cloned element does not have an owner document');\n }\n\n this.documentElement = this.cloneNode(element.ownerDocument.documentElement, false) as HTMLElement;\n }\n\n toIFrame(ownerDocument: Document, windowSize: Bounds): Promise<HTMLIFrameElement> {\n const iframe: HTMLIFrameElement = createIFrameContainer(ownerDocument, windowSize);\n\n if (!iframe.contentWindow) {\n return Promise.reject(`Unable to find iframe window`);\n }\n\n const scrollX = (ownerDocument.defaultView as Window).pageXOffset;\n const scrollY = (ownerDocument.defaultView as Window).pageYOffset;\n\n const cloneWindow = iframe.contentWindow;\n const documentClone: Document = cloneWindow.document;\n\n /* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle\n if window url is about:blank, we can assign the url to current by writing onto the document\n */\n\n const iframeLoad = iframeLoader(iframe).then(async () => {\n this.scrolledElements.forEach(restoreNodeScroll);\n if (cloneWindow) {\n cloneWindow.scrollTo(windowSize.left, windowSize.top);\n if (\n /(iPad|iPhone|iPod)/g.test(navigator.userAgent) &&\n (cloneWindow.scrollY !== windowSize.top || cloneWindow.scrollX !== windowSize.left)\n ) {\n this.context.logger.warn('Unable to restore scroll position for cloned document');\n this.context.windowBounds = this.context.windowBounds.add(\n cloneWindow.scrollX - windowSize.left,\n cloneWindow.scrollY - windowSize.top,\n 0,\n 0\n );\n }\n }\n\n const onclone = this.options.onclone;\n\n const referenceElement = this.clonedReferenceElement;\n\n if (typeof referenceElement === 'undefined') {\n return Promise.reject(`Error finding the ${this.referenceElement.nodeName} in the cloned document`);\n }\n\n if (documentClone.fonts && documentClone.fonts.ready) {\n await documentClone.fonts.ready;\n }\n\n if (/(AppleWebKit)/g.test(navigator.userAgent)) {\n await imagesReady(documentClone);\n }\n\n if (typeof onclone === 'function') {\n return Promise.resolve()\n .then(() => onclone(documentClone, referenceElement))\n .then(() => iframe);\n }\n\n return iframe;\n });\n\n documentClone.open();\n documentClone.write(`${serializeDoctype(document.doctype)}<html></html>`);\n // Chrome scrolls the parent document for some reason after the write to the cloned window???\n restoreOwnerScroll(this.referenceElement.ownerDocument, scrollX, scrollY);\n documentClone.replaceChild(documentClone.adoptNode(this.documentElement), documentClone.documentElement);\n documentClone.close();\n\n return iframeLoad;\n }\n\n createElementClone<T extends HTMLElement | SVGElement>(node: T): HTMLElement | SVGElement {\n if (isDebugging(node, DebuggerType.CLONE)) {\n debugger;\n }\n if (isCanvasElement(node)) {\n return this.createCanvasClone(node);\n }\n if (isVideoElement(node)) {\n return this.createVideoClone(node);\n }\n if (isStyleElement(node)) {\n return this.createStyleClone(node);\n }\n\n const clone = node.cloneNode(false) as T;\n if (isImageElement(clone)) {\n if (isImageElement(node) && node.currentSrc && node.currentSrc !== node.src) {\n clone.src = node.currentSrc;\n clone.srcset = '';\n }\n\n if (clone.loading === 'lazy') {\n clone.loading = 'eager';\n }\n }\n\n if (isCustomElement(clone)) {\n return this.createCustomElementClone(clone);\n }\n\n return clone;\n }\n\n createCustomElementClone(node: HTMLElement): HTMLElement {\n const clone = document.createElement('html2canvascustomelement');\n copyCSSStyles(node.style, clone);\n\n return clone;\n }\n\n createStyleClone(node: HTMLStyleElement): HTMLStyleElement {\n try {\n const sheet = node.sheet as CSSStyleSheet | undefined;\n if (sheet && sheet.cssRules) {\n const css: string = [].slice.call(sheet.cssRules, 0).reduce((css: string, rule: CSSRule) => {\n if (rule && typeof rule.cssText === 'string') {\n return css + rule.cssText;\n }\n return css;\n }, '');\n const style = node.cloneNode(false) as HTMLStyleElement;\n style.textContent = css;\n return style;\n }\n } catch (e) {\n // accessing node.sheet.cssRules throws a DOMException\n this.context.logger.error('Unable to access cssRules property', e);\n if (e.name !== 'SecurityError') {\n throw e;\n }\n }\n return node.cloneNode(false) as HTMLStyleElement;\n }\n\n createCanvasClone(canvas: HTMLCanvasElement): HTMLImageElement | HTMLCanvasElement {\n if (this.options.inlineImages && canvas.ownerDocument) {\n const img = canvas.ownerDocument.createElement('img');\n try {\n img.src = canvas.toDataURL();\n return img;\n } catch (e) {\n this.context.logger.info(`Unable to inline canvas contents, canvas is tainted`, canvas);\n }\n }\n\n const clonedCanvas = canvas.cloneNode(false) as HTMLCanvasElement;\n\n try {\n clonedCanvas.width = canvas.width;\n clonedCanvas.height = canvas.height;\n const ctx = canvas.getContext('2d');\n const clonedCtx = clonedCanvas.getContext('2d');\n if (clonedCtx) {\n if (!this.options.allowTaint && ctx) {\n clonedCtx.putImageData(ctx.getImageData(0, 0, canvas.width, canvas.height), 0, 0);\n } else {\n const gl = canvas.getContext('webgl2') ?? canvas.getContext('webgl');\n if (gl) {\n const attribs = gl.getContextAttributes();\n if (attribs?.preserveDrawingBuffer === false) {\n this.context.logger.warn(\n 'Unable to clone WebGL context as it has preserveDrawingBuffer=false',\n canvas\n );\n }\n }\n\n clonedCtx.drawImage(canvas, 0, 0);\n }\n }\n return clonedCanvas;\n } catch (e) {\n this.context.logger.info(`Unable to clone canvas as it is tainted`, canvas);\n }\n\n return clonedCanvas;\n }\n\n createVideoClone(video: HTMLVideoElement): HTMLCanvasElement {\n const canvas = video.ownerDocument.createElement('canvas');\n\n canvas.width = video.offsetWidth;\n canvas.height = video.offsetHeight;\n const ctx = canvas.getContext('2d');\n\n try {\n if (ctx) {\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height);\n if (!this.options.allowTaint) {\n ctx.getImageData(0, 0, canvas.width, canvas.height);\n }\n }\n return canvas;\n } catch (e) {\n this.context.logger.info(`Unable to clone video as it is tainted`, video);\n }\n\n const blankCanvas = video.ownerDocument.createElement('canvas');\n\n blankCanvas.width = video.offsetWidth;\n blankCanvas.height = video.offsetHeight;\n return blankCanvas;\n }\n\n appendChildNode(clone: HTMLElement | SVGElement, child: Node, copyStyles: boolean): void {\n if (\n !isElementNode(child) ||\n (!isScriptElement(child) &&\n !child.hasAttribute(IGNORE_ATTRIBUTE) &&\n (typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child)))\n ) {\n if (!this.options.copyStyles || !isElementNode(child) || !isStyleElement(child)) {\n clone.appendChild(this.cloneNode(child, copyStyles));\n }\n }\n }\n\n cloneChildNodes(node: Element, clone: HTMLElement | SVGElement, copyStyles: boolean): void {\n for (\n let child = node.shadowRoot ? node.shadowRoot.firstChild : node.firstChild;\n child;\n child = child.nextSibling\n ) {\n if (isElementNode(child) && isSlotElement(child) && typeof child.assignedNodes === 'function') {\n const assignedNodes = child.assignedNodes() as ChildNode[];\n if (assignedNodes.length) {\n assignedNodes.forEach((assignedNode) => this.appendChildNode(clone, assignedNode, copyStyles));\n }\n } else {\n this.appendChildNode(clone, child, copyStyles);\n }\n }\n }\n\n cloneNode(node: Node, copyStyles: boolean): Node {\n if (isTextNode(node)) {\n return document.createTextNode(node.data);\n }\n\n if (!node.ownerDocument) {\n return node.cloneNode(false);\n }\n\n const window = node.ownerDocument.defaultView;\n\n if (window && isElementNode(node) && (isHTMLElementNode(node) || isSVGElementNode(node))) {\n const clone = this.createElementClone(node);\n clone.style.transitionProperty = 'none';\n\n const style = window.getComputedStyle(node);\n const styleBefore = window.getComputedStyle(node, ':before');\n const styleAfter = window.getComputedStyle(node, ':after');\n\n if (this.referenceElement === node && isHTMLElementNode(clone)) {\n this.clonedReferenceElement = clone;\n }\n if (isBodyElement(clone)) {\n createPseudoHideStyles(clone);\n }\n\n const counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));\n const before = this.resolvePseudoContent(node, clone, styleBefore, PseudoElementType.BEFORE);\n\n if (isCustomElement(node)) {\n copyStyles = true;\n }\n\n if (!isVideoElement(node)) {\n this.cloneChildNodes(node, clone, copyStyles);\n }\n\n if (before) {\n clone.insertBefore(before, clone.firstChild);\n }\n\n const after = this.resolvePseudoContent(node, clone, styleAfter, PseudoElementType.AFTER);\n if (after) {\n clone.appendChild(after);\n }\n\n this.counters.pop(counters);\n\n if (\n (style && (this.options.copyStyles || isSVGElementNode(node)) && !isIFrameElement(node)) ||\n copyStyles\n ) {\n copyCSSStyles(style, clone);\n }\n\n if (node.scrollTop !== 0 || node.scrollLeft !== 0) {\n this.scrolledElements.push([clone, node.scrollLeft, node.scrollTop]);\n }\n\n if (\n (isTextareaElement(node) || isSelectElement(node)) &&\n (isTextareaElement(clone) || isSelectElement(clone))\n ) {\n clone.value = node.value;\n }\n\n return clone;\n }\n\n return node.cloneNode(false);\n }\n\n resolvePseudoContent(\n node: Element,\n clone: Element,\n style: CSSStyleDeclaration,\n pseudoElt: PseudoElementType\n ): HTMLElement | void {\n if (!style) {\n return;\n }\n\n const value = style.content;\n const document = clone.ownerDocument;\n if (!document || !value || value === 'none' || value === '-moz-alt-content' || style.display === 'none') {\n return;\n }\n\n this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));\n const declaration = new CSSParsedPseudoDeclaration(this.context, style);\n\n const anonymousReplacedElement = document.createElement('html2canvaspseudoelement');\n copyCSSStyles(style, anonymousReplacedElement);\n\n declaration.content.forEach((token) => {\n if (token.type === TokenType.STRING_TOKEN) {\n anonymousReplacedElement.appendChild(document.createTextNode(token.value));\n } else if (token.type === TokenType.URL_TOKEN) {\n const img = document.createElement('img');\n img.src = token.value;\n img.style.opacity = '1';\n anonymousReplacedElement.appendChild(img);\n } else if (token.type === TokenType.FUNCTION) {\n if (token.name === 'attr') {\n const attr = token.values.filter(isIdentToken);\n if (attr.length) {\n anonymousReplacedElement.appendChild(\n document.createTextNode(node.getAttribute(attr[0].value) || '')\n );\n }\n } else if (token.name === 'counter') {\n const [counter, counterStyle] = token.values.filter(nonFunctionArgSeparator);\n if (counter && isIdentToken(counter)) {\n const counterState = this.counters.getCounterValue(counter.value);\n const counterType =\n counterStyle && isIdentToken(counterStyle)\n ? listStyleType.parse(this.context, counterStyle.value)\n : LIST_STYLE_TYPE.DECIMAL;\n\n anonymousReplacedElement.appendChild(\n document.createTextNode(createCounterText(counterState, counterType, false))\n );\n }\n } else if (token.name === 'counters') {\n const [counter, delim, counterStyle] = token.values.filter(nonFunctionArgSeparator);\n if (counter && isIdentToken(counter)) {\n const counterStates = this.counters.getCounterValues(counter.value);\n const counterType =\n counterStyle && isIdentToken(counterStyle)\n ? listStyleType.parse(this.context, counterStyle.value)\n : LIST_STYLE_TYPE.DECIMAL;\n const separator = delim && delim.type === TokenType.STRING_TOKEN ? delim.value : '';\n const text = counterStates\n .map((value) => createCounterText(value, counterType, false))\n .join(separator);\n\n anonymousReplacedElement.appendChild(document.createTextNode(text));\n }\n } else {\n // console.log('FUNCTION_TOKEN', token);\n }\n } else if (token.type === TokenType.IDENT_TOKEN) {\n switch (token.value) {\n case 'open-quote':\n anonymousReplacedElement.appendChild(\n document.createTextNode(getQuote(declaration.quotes, this.quoteDepth++, true))\n );\n break;\n case 'close-quote':\n anonymousReplacedElement.appendChild(\n document.createTextNode(getQuote(declaration.quotes, --this.quoteDepth, false))\n );\n break;\n default:\n // safari doesn't parse string tokens correctly because of lack of quotes\n anonymousReplacedElement.appendChild(document.createTextNode(token.value));\n }\n }\n });\n\n anonymousReplacedElement.className = `${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE} ${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}`;\n const newClassName =\n pseudoElt === PseudoElementType.BEFORE\n ? ` ${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}`\n : ` ${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}`;\n\n if (isSVGElementNode(clone)) {\n clone.className.baseValue += newClassName;\n } else {\n clone.className += newClassName;\n }\n\n return anonymousReplacedElement;\n }\n\n static destroy(container: HTMLIFrameElement): boolean {\n if (container.parentNode) {\n container.parentNode.removeChild(container);\n return true;\n }\n return false;\n }\n}\n\nenum PseudoElementType {\n BEFORE,\n AFTER\n}\n\nconst createIFrameContainer = (ownerDocument: Document, bounds: Bounds): HTMLIFrameElement => {\n const cloneIframeContainer = ownerDocument.createElement('iframe');\n\n cloneIframeContainer.className = 'html2canvas-container';\n cloneIframeContainer.style.visibility = 'hidden';\n cloneIframeContainer.style.position = 'fixed';\n cloneIframeContainer.style.left = '-10000px';\n cloneIframeContainer.style.top = '0px';\n cloneIframeContainer.style.border = '0';\n cloneIframeContainer.width = bounds.width.toString();\n cloneIframeContainer.height = bounds.height.toString();\n cloneIframeContainer.scrolling = 'no'; // ios won't scroll without it\n cloneIframeContainer.setAttribute(IGNORE_ATTRIBUTE, 'true');\n ownerDocument.body.appendChild(cloneIframeContainer);\n\n return cloneIframeContainer;\n};\n\nconst imageReady = (img: HTMLImageElement): Promise<Event | void | string> => {\n return new Promise((resolve) => {\n if (img.complete) {\n resolve();\n return;\n }\n if (!img.src) {\n resolve();\n return;\n }\n img.onload = resolve;\n img.onerror = resolve;\n });\n};\n\nconst imagesReady = (document: HTMLDocument): Promise<unknown[]> => {\n return Promise.all([].slice.call(document.images, 0).map(imageReady));\n};\n\nconst iframeLoader = (iframe: HTMLIFrameElement): Promise<HTMLIFrameElement> => {\n return new Promise((resolve, reject) => {\n const cloneWindow = iframe.contentWindow;\n\n if (!cloneWindow) {\n return reject(`No window assigned for iframe`);\n }\n\n const documentClone = cloneWindow.document;\n\n cloneWindow.onload = iframe.onload = () => {\n cloneWindow.onload = iframe.onload = null;\n const interval = setInterval(() => {\n if (documentClone.body.childNodes.length > 0 && documentClone.readyState === 'complete') {\n clearInterval(interval);\n resolve(iframe);\n }\n }, 50);\n };\n });\n};\n\nconst ignoredStyleProperties = [\n 'all', // #2476\n 'd', // #2483\n 'content' // Safari shows pseudoelements if content is set\n];\n\nexport const copyCSSStyles = <T extends HTMLElement | SVGElement>(style: CSSStyleDeclaration, target: T): T => {\n // Edge does not provide value for cssText\n for (let i = style.length - 1; i >= 0; i--) {\n const property = style.item(i);\n if (ignoredStyleProperties.indexOf(property) === -1) {\n target.style.setProperty(property, style.getPropertyValue(property));\n }\n }\n return target;\n};\n\nconst serializeDoctype = (doctype?: DocumentType | null): string => {\n let str = '';\n if (doctype) {\n str += '<!DOCTYPE ';\n if (doctype.name) {\n str += doctype.name;\n }\n\n if (doctype.internalSubset) {\n str += doctype.internalSubset;\n }\n\n if (doctype.publicId) {\n str += `\"${doctype.publicId}\"`;\n }\n\n if (doctype.systemId) {\n str += `\"${doctype.systemId}\"`;\n }\n\n str += '>';\n }\n\n return str;\n};\n\nconst restoreOwnerScroll = (ownerDocument: Document | null, x: number, y: number) => {\n if (\n ownerDocument &&\n ownerDocument.defaultView &&\n (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)\n ) {\n ownerDocument.defaultView.scrollTo(x, y);\n }\n};\n\nconst restoreNodeScroll = ([element, x, y]: [HTMLElement, number, number]) => {\n element.scrollLeft = x;\n element.scrollTop = y;\n};\n\nconst PSEUDO_BEFORE = ':before';\nconst PSEUDO_AFTER = ':after';\nconst PSEUDO_HIDE_ELEMENT_CLASS_BEFORE = '___html2canvas___pseudoelement_before';\nconst PSEUDO_HIDE_ELEMENT_CLASS_AFTER = '___html2canvas___pseudoelement_after';\n\nconst PSEUDO_HIDE_ELEMENT_STYLE = `{\n content: \"\" !important;\n display: none !important;\n}`;\n\nconst createPseudoHideStyles = (body: HTMLElement) => {\n createStyles(\n body,\n `.${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}${PSEUDO_BEFORE}${PSEUDO_HIDE_ELEMENT_STYLE}\n .${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}${PSEUDO_AFTER}${PSEUDO_HIDE_ELEMENT_STYLE}`\n );\n};\n\nconst createStyles = (body: HTMLElement, styles: string) => {\n const document = body.ownerDocument;\n if (document) {\n const style = document.createElement('style');\n style.textContent = styles;\n body.appendChild(style);\n }\n};\n","import {FEATURES} from './features';\nimport {Context} from './context';\n\nexport class CacheStorage {\n private static _link?: HTMLAnchorElement;\n private static _origin = 'about:blank';\n\n static getOrigin(url: string): string {\n const link = CacheStorage._link;\n if (!link) {\n return 'about:blank';\n }\n\n link.href = url;\n link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/\n return link.protocol + link.hostname + link.port;\n }\n\n static isSameOrigin(src: string): boolean {\n return CacheStorage.getOrigin(src) === CacheStorage._origin;\n }\n\n static setContext(window: Window): void {\n CacheStorage._link = window.document.createElement('a');\n CacheStorage._origin = CacheStorage.getOrigin(window.location.href);\n }\n}\n\nexport interface ResourceOptions {\n imageTimeout: number;\n useCORS: boolean;\n allowTaint: boolean;\n proxy?: string;\n}\n\nexport class Cache {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _cache: {[key: string]: Promise<any>} = {};\n\n constructor(private readonly context: Context, private readonly _options: ResourceOptions) {}\n\n addImage(src: string): Promise<void> {\n const result = Promise.resolve();\n if (this.has(src)) {\n return result;\n }\n\n if (isBlobImage(src) || isRenderable(src)) {\n (this._cache[src] = this.loadImage(src)).catch(() => {\n // prevent unhandled rejection\n });\n return result;\n }\n\n return result;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n match(src: string): Promise<any> {\n return this._cache[src];\n }\n\n private async loadImage(key: string) {\n const isSameOrigin = CacheStorage.isSameOrigin(key);\n const useCORS =\n !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;\n const useProxy =\n !isInlineImage(key) &&\n !isSameOrigin &&\n !isBlobImage(key) &&\n typeof this._options.proxy === 'string' &&\n FEATURES.SUPPORT_CORS_XHR &&\n !useCORS;\n if (\n !isSameOrigin &&\n this._options.allowTaint === false &&\n !isInlineImage(key) &&\n !isBlobImage(key) &&\n !useProxy &&\n !useCORS\n ) {\n return;\n }\n\n let src = key;\n if (useProxy) {\n src = await this.proxy(src);\n }\n\n this.context.logger.debug(`Added image ${key.substring(0, 256)}`);\n\n return await new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = reject;\n //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous\n if (isInlineBase64Image(src) || useCORS) {\n img.crossOrigin = 'anonymous';\n }\n img.src = src;\n if (img.complete === true) {\n // Inline XML images may fail to parse, throwing an Error later on\n setTimeout(() => resolve(img), 500);\n }\n if (this._options.imageTimeout > 0) {\n setTimeout(\n () => reject(`Timed out (${this._options.imageTimeout}ms) loading image`),\n this._options.imageTimeout\n );\n }\n });\n }\n\n private has(key: string): boolean {\n return typeof this._cache[key] !== 'undefined';\n }\n\n keys(): Promise<string[]> {\n return Promise.resolve(Object.keys(this._cache));\n }\n\n private proxy(src: string): Promise<string> {\n const proxy = this._options.proxy;\n\n if (!proxy) {\n throw new Error('No proxy defined');\n }\n\n const key = src.substring(0, 256);\n\n return new Promise((resolve, reject) => {\n const responseType = FEATURES.SUPPORT_RESPONSE_TYPE ? 'blob' : 'text';\n const xhr = new XMLHttpRequest();\n xhr.onload = () => {\n if (xhr.status === 200) {\n if (responseType === 'text') {\n resolve(xhr.response);\n } else {\n const reader = new FileReader();\n reader.addEventListener('load', () => resolve(reader.result as string), false);\n reader.addEventListener('error', (e) => reject(e), false);\n reader.readAsDataURL(xhr.response);\n }\n } else {\n reject(`Failed to proxy resource ${key} with status code ${xhr.status}`);\n }\n };\n\n xhr.onerror = reject;\n const queryString = proxy.indexOf('?') > -1 ? '&' : '?';\n xhr.open('GET', `${proxy}${queryString}url=${encodeURIComponent(src)}&responseType=${responseType}`);\n\n if (responseType !== 'text' && xhr instanceof XMLHttpRequest) {\n xhr.responseType = responseType;\n }\n\n if (this._options.imageTimeout) {\n const timeout = this._options.imageTimeout;\n xhr.timeout = timeout;\n xhr.ontimeout = () => reject(`Timed out (${timeout}ms) proxying ${key}`);\n }\n\n xhr.send();\n });\n }\n}\n\nconst INLINE_SVG = /^data:image\\/svg\\+xml/i;\nconst INLINE_BASE64 = /^data:image\\/.*;base64,/i;\nconst INLINE_IMG = /^data:image\\/.*/i;\n\nconst isRenderable = (src: string): boolean => FEATURES.SUPPORT_SVG_DRAWING || !isSVG(src);\nconst isInlineImage = (src: string): boolean => INLINE_IMG.test(src);\nconst isInlineBase64Image = (src: string): boolean => INLINE_BASE64.test(src);\nconst isBlobImage = (src: string): boolean => src.substr(0, 4) === 'blob';\n\nconst isSVG = (src: string): boolean => src.substr(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);\n","import {IPath, Path, PathType} from './path';\n\nexport class Vector implements IPath {\n type: PathType;\n x: number;\n y: number;\n\n constructor(x: number, y: number) {\n this.type = PathType.VECTOR;\n this.x = x;\n this.y = y;\n }\n\n add(deltaX: number, deltaY: number): Vector {\n return new Vector(this.x + deltaX, this.y + deltaY);\n }\n}\n\nexport const isVector = (path: Path): path is Vector => path.type === PathType.VECTOR;\n","import {Vector} from './vector';\nimport {IPath, PathType, Path} from './path';\n\nconst lerp = (a: Vector, b: Vector, t: number): Vector => {\n return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);\n};\n\nexport class BezierCurve implements IPath {\n type: PathType;\n start: Vector;\n startControl: Vector;\n endControl: Vector;\n end: Vector;\n\n constructor(start: Vector, startControl: Vector, endControl: Vector, end: Vector) {\n this.type = PathType.BEZIER_CURVE;\n this.start = start;\n this.startControl = startControl;\n this.endControl = endControl;\n this.end = end;\n }\n\n subdivide(t: number, firstHalf: boolean): BezierCurve {\n const ab = lerp(this.start, this.startControl, t);\n const bc = lerp(this.startControl, this.endControl, t);\n const cd = lerp(this.endControl, this.end, t);\n const abbc = lerp(ab, bc, t);\n const bccd = lerp(bc, cd, t);\n const dest = lerp(abbc, bccd, t);\n return firstHalf ? new BezierCurve(this.start, ab, abbc, dest) : new BezierCurve(dest, bccd, cd, this.end);\n }\n\n add(deltaX: number, deltaY: number): BezierCurve {\n return new BezierCurve(\n this.start.add(deltaX, deltaY),\n this.startControl.add(deltaX, deltaY),\n this.endControl.add(deltaX, deltaY),\n this.end.add(deltaX, deltaY)\n );\n }\n\n reverse(): BezierCurve {\n return new BezierCurve(this.end, this.endControl, this.startControl, this.start);\n }\n}\n\nexport const isBezierCurve = (path: Path): path is BezierCurve => path.type === PathType.BEZIER_CURVE;\n","import {ElementContainer} from '../dom/element-container';\nimport {getAbsoluteValue, getAbsoluteValueForTuple} from '../css/types/length-percentage';\nimport {Vector} from './vector';\nimport {BezierCurve} from './bezier-curve';\nimport {Path} from './path';\n\nexport class BoundCurves {\n readonly topLeftBorderDoubleOuterBox: Path;\n readonly topRightBorderDoubleOuterBox: Path;\n readonly bottomRightBorderDoubleOuterBox: Path;\n readonly bottomLeftBorderDoubleOuterBox: Path;\n readonly topLeftBorderDoubleInnerBox: Path;\n readonly topRightBorderDoubleInnerBox: Path;\n readonly bottomRightBorderDoubleInnerBox: Path;\n readonly bottomLeftBorderDoubleInnerBox: Path;\n readonly topLeftBorderStroke: Path;\n readonly topRightBorderStroke: Path;\n readonly bottomRightBorderStroke: Path;\n readonly bottomLeftBorderStroke: Path;\n readonly topLeftBorderBox: Path;\n readonly topRightBorderBox: Path;\n readonly bottomRightBorderBox: Path;\n readonly bottomLeftBorderBox: Path;\n readonly topLeftPaddingBox: Path;\n readonly topRightPaddingBox: Path;\n readonly bottomRightPaddingBox: Path;\n readonly bottomLeftPaddingBox: Path;\n readonly topLeftContentBox: Path;\n readonly topRightContentBox: Path;\n readonly bottomRightContentBox: Path;\n readonly bottomLeftContentBox: Path;\n\n constructor(element: ElementContainer) {\n const styles = element.styles;\n const bounds = element.bounds;\n\n let [tlh, tlv] = getAbsoluteValueForTuple(styles.borderTopLeftRadius, bounds.width, bounds.height);\n let [trh, trv] = getAbsoluteValueForTuple(styles.borderTopRightRadius, bounds.width, bounds.height);\n let [brh, brv] = getAbsoluteValueForTuple(styles.borderBottomRightRadius, bounds.width, bounds.height);\n let [blh, blv] = getAbsoluteValueForTuple(styles.borderBottomLeftRadius, bounds.width, bounds.height);\n\n const factors = [];\n factors.push((tlh + trh) / bounds.width);\n factors.push((blh + brh) / bounds.width);\n factors.push((tlv + blv) / bounds.height);\n factors.push((trv + brv) / bounds.height);\n const maxFactor = Math.max(...factors);\n\n if (maxFactor > 1) {\n tlh /= maxFactor;\n tlv /= maxFactor;\n trh /= maxFactor;\n trv /= maxFactor;\n brh /= maxFactor;\n brv /= maxFactor;\n blh /= maxFactor;\n blv /= maxFactor;\n }\n\n const topWidth = bounds.width - trh;\n const rightHeight = bounds.height - brv;\n const bottomWidth = bounds.width - brh;\n const leftHeight = bounds.height - blv;\n\n const borderTopWidth = styles.borderTopWidth;\n const borderRightWidth = styles.borderRightWidth;\n const borderBottomWidth = styles.borderBottomWidth;\n const borderLeftWidth = styles.borderLeftWidth;\n\n const paddingTop = getAbsoluteValue(styles.paddingTop, element.bounds.width);\n const paddingRight = getAbsoluteValue(styles.paddingRight, element.bounds.width);\n const paddingBottom = getAbsoluteValue(styles.paddingBottom, element.bounds.width);\n const paddingLeft = getAbsoluteValue(styles.paddingLeft, element.bounds.width);\n\n this.topLeftBorderDoubleOuterBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth / 3,\n bounds.top + borderTopWidth / 3,\n tlh - borderLeftWidth / 3,\n tlv - borderTopWidth / 3,\n CORNER.TOP_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth / 3, bounds.top + borderTopWidth / 3);\n this.topRightBorderDoubleOuterBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + topWidth,\n bounds.top + borderTopWidth / 3,\n trh - borderRightWidth / 3,\n trv - borderTopWidth / 3,\n CORNER.TOP_RIGHT\n )\n : new Vector(bounds.left + bounds.width - borderRightWidth / 3, bounds.top + borderTopWidth / 3);\n this.bottomRightBorderDoubleOuterBox =\n brh > 0 || brv > 0\n ? getCurvePoints(\n bounds.left + bottomWidth,\n bounds.top + rightHeight,\n brh - borderRightWidth / 3,\n brv - borderBottomWidth / 3,\n CORNER.BOTTOM_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - borderRightWidth / 3,\n bounds.top + bounds.height - borderBottomWidth / 3\n );\n this.bottomLeftBorderDoubleOuterBox =\n blh > 0 || blv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth / 3,\n bounds.top + leftHeight,\n blh - borderLeftWidth / 3,\n blv - borderBottomWidth / 3,\n CORNER.BOTTOM_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth / 3, bounds.top + bounds.height - borderBottomWidth / 3);\n this.topLeftBorderDoubleInnerBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + (borderLeftWidth * 2) / 3,\n bounds.top + (borderTopWidth * 2) / 3,\n tlh - (borderLeftWidth * 2) / 3,\n tlv - (borderTopWidth * 2) / 3,\n CORNER.TOP_LEFT\n )\n : new Vector(bounds.left + (borderLeftWidth * 2) / 3, bounds.top + (borderTopWidth * 2) / 3);\n this.topRightBorderDoubleInnerBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + topWidth,\n bounds.top + (borderTopWidth * 2) / 3,\n trh - (borderRightWidth * 2) / 3,\n trv - (borderTopWidth * 2) / 3,\n CORNER.TOP_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - (borderRightWidth * 2) / 3,\n bounds.top + (borderTopWidth * 2) / 3\n );\n this.bottomRightBorderDoubleInnerBox =\n brh > 0 || brv > 0\n ? getCurvePoints(\n bounds.left + bottomWidth,\n bounds.top + rightHeight,\n brh - (borderRightWidth * 2) / 3,\n brv - (borderBottomWidth * 2) / 3,\n CORNER.BOTTOM_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - (borderRightWidth * 2) / 3,\n bounds.top + bounds.height - (borderBottomWidth * 2) / 3\n );\n this.bottomLeftBorderDoubleInnerBox =\n blh > 0 || blv > 0\n ? getCurvePoints(\n bounds.left + (borderLeftWidth * 2) / 3,\n bounds.top + leftHeight,\n blh - (borderLeftWidth * 2) / 3,\n blv - (borderBottomWidth * 2) / 3,\n CORNER.BOTTOM_LEFT\n )\n : new Vector(\n bounds.left + (borderLeftWidth * 2) / 3,\n bounds.top + bounds.height - (borderBottomWidth * 2) / 3\n );\n this.topLeftBorderStroke =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth / 2,\n bounds.top + borderTopWidth / 2,\n tlh - borderLeftWidth / 2,\n tlv - borderTopWidth / 2,\n CORNER.TOP_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth / 2, bounds.top + borderTopWidth / 2);\n this.topRightBorderStroke =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + topWidth,\n bounds.top + borderTopWidth / 2,\n trh - borderRightWidth / 2,\n trv - borderTopWidth / 2,\n CORNER.TOP_RIGHT\n )\n : new Vector(bounds.left + bounds.width - borderRightWidth / 2, bounds.top + borderTopWidth / 2);\n this.bottomRightBorderStroke =\n brh > 0 || brv > 0\n ? getCurvePoints(\n bounds.left + bottomWidth,\n bounds.top + rightHeight,\n brh - borderRightWidth / 2,\n brv - borderBottomWidth / 2,\n CORNER.BOTTOM_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - borderRightWidth / 2,\n bounds.top + bounds.height - borderBottomWidth / 2\n );\n this.bottomLeftBorderStroke =\n blh > 0 || blv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth / 2,\n bounds.top + leftHeight,\n blh - borderLeftWidth / 2,\n blv - borderBottomWidth / 2,\n CORNER.BOTTOM_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth / 2, bounds.top + bounds.height - borderBottomWidth / 2);\n this.topLeftBorderBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(bounds.left, bounds.top, tlh, tlv, CORNER.TOP_LEFT)\n : new Vector(bounds.left, bounds.top);\n this.topRightBorderBox =\n trh > 0 || trv > 0\n ? getCurvePoints(bounds.left + topWidth, bounds.top, trh, trv, CORNER.TOP_RIGHT)\n : new Vector(bounds.left + bounds.width, bounds.top);\n this.bottomRightBorderBox =\n brh > 0 || brv > 0\n ? getCurvePoints(bounds.left + bottomWidth, bounds.top + rightHeight, brh, brv, CORNER.BOTTOM_RIGHT)\n : new Vector(bounds.left + bounds.width, bounds.top + bounds.height);\n this.bottomLeftBorderBox =\n blh > 0 || blv > 0\n ? getCurvePoints(bounds.left, bounds.top + leftHeight, blh, blv, CORNER.BOTTOM_LEFT)\n : new Vector(bounds.left, bounds.top + bounds.height);\n this.topLeftPaddingBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth,\n bounds.top + borderTopWidth,\n Math.max(0, tlh - borderLeftWidth),\n Math.max(0, tlv - borderTopWidth),\n CORNER.TOP_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth, bounds.top + borderTopWidth);\n this.topRightPaddingBox =\n trh > 0 || trv > 0\n ? getCurvePoints(\n bounds.left + Math.min(topWidth, bounds.width - borderRightWidth),\n bounds.top + borderTopWidth,\n topWidth > bounds.width + borderRightWidth ? 0 : Math.max(0, trh - borderRightWidth),\n Math.max(0, trv - borderTopWidth),\n CORNER.TOP_RIGHT\n )\n : new Vector(bounds.left + bounds.width - borderRightWidth, bounds.top + borderTopWidth);\n this.bottomRightPaddingBox =\n brh > 0 || brv > 0\n ? getCurvePoints(\n bounds.left + Math.min(bottomWidth, bounds.width - borderLeftWidth),\n bounds.top + Math.min(rightHeight, bounds.height - borderBottomWidth),\n Math.max(0, brh - borderRightWidth),\n Math.max(0, brv - borderBottomWidth),\n CORNER.BOTTOM_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - borderRightWidth,\n bounds.top + bounds.height - borderBottomWidth\n );\n this.bottomLeftPaddingBox =\n blh > 0 || blv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth,\n bounds.top + Math.min(leftHeight, bounds.height - borderBottomWidth),\n Math.max(0, blh - borderLeftWidth),\n Math.max(0, blv - borderBottomWidth),\n CORNER.BOTTOM_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth, bounds.top + bounds.height - borderBottomWidth);\n this.topLeftContentBox =\n tlh > 0 || tlv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth + paddingLeft,\n bounds.top + borderTopWidth + paddingTop,\n Math.max(0, tlh - (borderLeftWidth + paddingLeft)),\n Math.max(0, tlv - (borderTopWidth + paddingTop)),\n CORNER.TOP_LEFT\n )\n : new Vector(bounds.left + borderLeftWidth + paddingLeft, bounds.top + borderTopWidth + paddingTop);\n this.topRightContentBox =\n trh > 0 || trv > 0\n ? getCurvePoints(\n bounds.left + Math.min(topWidth, bounds.width + borderLeftWidth + paddingLeft),\n bounds.top + borderTopWidth + paddingTop,\n topWidth > bounds.width + borderLeftWidth + paddingLeft ? 0 : trh - borderLeftWidth + paddingLeft,\n trv - (borderTopWidth + paddingTop),\n CORNER.TOP_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - (borderRightWidth + paddingRight),\n bounds.top + borderTopWidth + paddingTop\n );\n this.bottomRightContentBox =\n brh > 0 || brv > 0\n ? getCurvePoints(\n bounds.left + Math.min(bottomWidth, bounds.width - (borderLeftWidth + paddingLeft)),\n bounds.top + Math.min(rightHeight, bounds.height + borderTopWidth + paddingTop),\n Math.max(0, brh - (borderRightWidth + paddingRight)),\n brv - (borderBottomWidth + paddingBottom),\n CORNER.BOTTOM_RIGHT\n )\n : new Vector(\n bounds.left + bounds.width - (borderRightWidth + paddingRight),\n bounds.top + bounds.height - (borderBottomWidth + paddingBottom)\n );\n this.bottomLeftContentBox =\n blh > 0 || blv > 0\n ? getCurvePoints(\n bounds.left + borderLeftWidth + paddingLeft,\n bounds.top + leftHeight,\n Math.max(0, blh - (borderLeftWidth + paddingLeft)),\n blv - (borderBottomWidth + paddingBottom),\n CORNER.BOTTOM_LEFT\n )\n : new Vector(\n bounds.left + borderLeftWidth + paddingLeft,\n bounds.top + bounds.height - (borderBottomWidth + paddingBottom)\n );\n }\n}\n\nenum CORNER {\n TOP_LEFT = 0,\n TOP_RIGHT = 1,\n BOTTOM_RIGHT = 2,\n BOTTOM_LEFT = 3\n}\n\nconst getCurvePoints = (x: number, y: number, r1: number, r2: number, position: CORNER): BezierCurve => {\n const kappa = 4 * ((Math.sqrt(2) - 1) / 3);\n const ox = r1 * kappa; // control point offset horizontal\n const oy = r2 * kappa; // control point offset vertical\n const xm = x + r1; // x-middle\n const ym = y + r2; // y-middle\n\n switch (position) {\n case CORNER.TOP_LEFT:\n return new BezierCurve(\n new Vector(x, ym),\n new Vector(x, ym - oy),\n new Vector(xm - ox, y),\n new Vector(xm, y)\n );\n case CORNER.TOP_RIGHT:\n return new BezierCurve(\n new Vector(x, y),\n new Vector(x + ox, y),\n new Vector(xm, ym - oy),\n new Vector(xm, ym)\n );\n case CORNER.BOTTOM_RIGHT:\n return new BezierCurve(\n new Vector(xm, y),\n new Vector(xm, y + oy),\n new Vector(x + ox, ym),\n new Vector(x, ym)\n );\n case CORNER.BOTTOM_LEFT:\n default:\n return new BezierCurve(\n new Vector(xm, ym),\n new Vector(xm - ox, ym),\n new Vector(x, y + oy),\n new Vector(x, y)\n );\n }\n};\n\nexport const calculateBorderBoxPath = (curves: BoundCurves): Path[] => {\n return [curves.topLeftBorderBox, curves.topRightBorderBox, curves.bottomRightBorderBox, curves.bottomLeftBorderBox];\n};\n\nexport const calculateContentBoxPath = (curves: BoundCurves): Path[] => {\n return [\n curves.topLeftContentBox,\n curves.topRightContentBox,\n curves.bottomRightContentBox,\n curves.bottomLeftContentBox\n ];\n};\n\nexport const calculatePaddingBoxPath = (curves: BoundCurves): Path[] => {\n return [\n curves.topLeftPaddingBox,\n curves.topRightPaddingBox,\n curves.bottomRightPaddingBox,\n curves.bottomLeftPaddingBox\n ];\n};\n","import {Matrix} from '../css/property-descriptors/transform';\nimport {Path} from './path';\n\nexport const enum EffectType {\n TRANSFORM = 0,\n CLIP = 1,\n OPACITY = 2\n}\n\nexport const enum EffectTarget {\n BACKGROUND_BORDERS = 1 << 1,\n CONTENT = 1 << 2\n}\n\nexport interface IElementEffect {\n readonly type: EffectType;\n readonly target: number;\n}\n\nexport class TransformEffect implements IElementEffect {\n readonly type: EffectType = EffectType.TRANSFORM;\n readonly target: number = EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT;\n\n constructor(readonly offsetX: number, readonly offsetY: number, readonly matrix: Matrix) {}\n}\n\nexport class ClipEffect implements IElementEffect {\n readonly type: EffectType = EffectType.CLIP;\n\n constructor(readonly path: Path[], readonly target: EffectTarget) {}\n}\n\nexport class OpacityEffect implements IElementEffect {\n readonly type: EffectType = EffectType.OPACITY;\n readonly target: number = EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT;\n\n constructor(readonly opacity: number) {}\n}\n\nexport const isTransformEffect = (effect: IElementEffect): effect is TransformEffect =>\n effect.type === EffectType.TRANSFORM;\nexport const isClipEffect = (effect: IElementEffect): effect is ClipEffect => effect.type === EffectType.CLIP;\nexport const isOpacityEffect = (effect: IElementEffect): effect is OpacityEffect => effect.type === EffectType.OPACITY;\n","import {BezierCurve} from './bezier-curve';\nimport {Vector} from './vector';\nexport const enum PathType {\n VECTOR = 0,\n BEZIER_CURVE = 1\n}\n\nexport interface IPath {\n type: PathType;\n add(deltaX: number, deltaY: number): IPath;\n}\n\nexport const equalPath = (a: Path[], b: Path[]): boolean => {\n if (a.length === b.length) {\n return a.some((v, i) => v === b[i]);\n }\n\n return false;\n};\n\nexport const transformPath = (path: Path[], deltaX: number, deltaY: number, deltaW: number, deltaH: number): Path[] => {\n return path.map((point, index) => {\n switch (index) {\n case 0:\n return point.add(deltaX, deltaY);\n case 1:\n return point.add(deltaX + deltaW, deltaY);\n case 2:\n return point.add(deltaX + deltaW, deltaY + deltaH);\n case 3:\n return point.add(deltaX, deltaY + deltaH);\n }\n return point;\n });\n};\n\nexport type Path = Vector | BezierCurve;\n","import {ElementContainer, FLAGS} from '../dom/element-container';\nimport {contains} from '../core/bitwise';\nimport {BoundCurves, calculateBorderBoxPath, calculatePaddingBoxPath} from './bound-curves';\nimport {ClipEffect, EffectTarget, IElementEffect, isClipEffect, OpacityEffect, TransformEffect} from './effects';\nimport {OVERFLOW} from '../css/property-descriptors/overflow';\nimport {equalPath} from './path';\nimport {DISPLAY} from '../css/property-descriptors/display';\nimport {OLElementContainer} from '../dom/elements/ol-element-container';\nimport {LIElementContainer} from '../dom/elements/li-element-container';\nimport {createCounterText} from '../css/types/functions/counter';\nimport {POSITION} from '../css/property-descriptors/position';\n\nexport class StackingContext {\n element: ElementPaint;\n negativeZIndex: StackingContext[];\n zeroOrAutoZIndexOrTransformedOrOpacity: StackingContext[];\n positiveZIndex: StackingContext[];\n nonPositionedFloats: StackingContext[];\n nonPositionedInlineLevel: StackingContext[];\n inlineLevel: ElementPaint[];\n nonInlineLevel: ElementPaint[];\n\n constructor(container: ElementPaint) {\n this.element = container;\n this.inlineLevel = [];\n this.nonInlineLevel = [];\n this.negativeZIndex = [];\n this.zeroOrAutoZIndexOrTransformedOrOpacity = [];\n this.positiveZIndex = [];\n this.nonPositionedFloats = [];\n this.nonPositionedInlineLevel = [];\n }\n}\n\nexport class ElementPaint {\n readonly effects: IElementEffect[] = [];\n readonly curves: BoundCurves;\n listValue?: string;\n\n constructor(readonly container: ElementContainer, readonly parent: ElementPaint | null) {\n this.curves = new BoundCurves(this.container);\n if (this.container.styles.opacity < 1) {\n this.effects.push(new OpacityEffect(this.container.styles.opacity));\n }\n\n if (this.container.styles.transform !== null) {\n const offsetX = this.container.bounds.left + this.container.styles.transformOrigin[0].number;\n const offsetY = this.container.bounds.top + this.container.styles.transformOrigin[1].number;\n const matrix = this.container.styles.transform;\n this.effects.push(new TransformEffect(offsetX, offsetY, matrix));\n }\n\n if (this.container.styles.overflowX !== OVERFLOW.VISIBLE) {\n const borderBox = calculateBorderBoxPath(this.curves);\n const paddingBox = calculatePaddingBoxPath(this.curves);\n\n if (equalPath(borderBox, paddingBox)) {\n this.effects.push(new ClipEffect(borderBox, EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT));\n } else {\n this.effects.push(new ClipEffect(borderBox, EffectTarget.BACKGROUND_BORDERS));\n this.effects.push(new ClipEffect(paddingBox, EffectTarget.CONTENT));\n }\n }\n }\n\n getEffects(target: EffectTarget): IElementEffect[] {\n let inFlow = [POSITION.ABSOLUTE, POSITION.FIXED].indexOf(this.container.styles.position) === -1;\n let parent = this.parent;\n const effects = this.effects.slice(0);\n while (parent) {\n const croplessEffects = parent.effects.filter((effect) => !isClipEffect(effect));\n if (inFlow || parent.container.styles.position !== POSITION.STATIC || !parent.parent) {\n effects.unshift(...croplessEffects);\n inFlow = [POSITION.ABSOLUTE, POSITION.FIXED].indexOf(parent.container.styles.position) === -1;\n if (parent.container.styles.overflowX !== OVERFLOW.VISIBLE) {\n const borderBox = calculateBorderBoxPath(parent.curves);\n const paddingBox = calculatePaddingBoxPath(parent.curves);\n if (!equalPath(borderBox, paddingBox)) {\n effects.unshift(\n new ClipEffect(paddingBox, EffectTarget.BACKGROUND_BORDERS | EffectTarget.CONTENT)\n );\n }\n }\n } else {\n effects.unshift(...croplessEffects);\n }\n\n parent = parent.parent;\n }\n\n return effects.filter((effect) => contains(effect.target, target));\n }\n}\n\nconst parseStackTree = (\n parent: ElementPaint,\n stackingContext: StackingContext,\n realStackingContext: StackingContext,\n listItems: ElementPaint[]\n) => {\n parent.container.elements.forEach((child) => {\n const treatAsRealStackingContext = contains(child.flags, FLAGS.CREATES_REAL_STACKING_CONTEXT);\n const createsStackingContext = contains(child.flags, FLAGS.CREATES_STACKING_CONTEXT);\n const paintContainer = new ElementPaint(child, parent);\n if (contains(child.styles.display, DISPLAY.LIST_ITEM)) {\n listItems.push(paintContainer);\n }\n\n const listOwnerItems = contains(child.flags, FLAGS.IS_LIST_OWNER) ? [] : listItems;\n\n if (treatAsRealStackingContext || createsStackingContext) {\n const parentStack =\n treatAsRealStackingContext || child.styles.isPositioned() ? realStackingContext : stackingContext;\n\n const stack = new StackingContext(paintContainer);\n\n if (child.styles.isPositioned() || child.styles.opacity < 1 || child.styles.isTransformed()) {\n const order = child.styles.zIndex.order;\n if (order < 0) {\n let index = 0;\n\n parentStack.negativeZIndex.some((current, i) => {\n if (order > current.element.container.styles.zIndex.order) {\n index = i;\n return false;\n } else if (index > 0) {\n return true;\n }\n\n return false;\n });\n parentStack.negativeZIndex.splice(index, 0, stack);\n } else if (order > 0) {\n let index = 0;\n parentStack.positiveZIndex.some((current, i) => {\n if (order >= current.element.container.styles.zIndex.order) {\n index = i + 1;\n return false;\n } else if (index > 0) {\n return true;\n }\n\n return false;\n });\n parentStack.positiveZIndex.splice(index, 0, stack);\n } else {\n parentStack.zeroOrAutoZIndexOrTransformedOrOpacity.push(stack);\n }\n } else {\n if (child.styles.isFloating()) {\n parentStack.nonPositionedFloats.push(stack);\n } else {\n parentStack.nonPositionedInlineLevel.push(stack);\n }\n }\n\n parseStackTree(\n paintContainer,\n stack,\n treatAsRealStackingContext ? stack : realStackingContext,\n listOwnerItems\n );\n } else {\n if (child.styles.isInlineLevel()) {\n stackingContext.inlineLevel.push(paintContainer);\n } else {\n stackingContext.nonInlineLevel.push(paintContainer);\n }\n\n parseStackTree(paintContainer, stackingContext, realStackingContext, listOwnerItems);\n }\n\n if (contains(child.flags, FLAGS.IS_LIST_OWNER)) {\n processListItems(child, listOwnerItems);\n }\n });\n};\n\nconst processListItems = (owner: ElementContainer, elements: ElementPaint[]) => {\n let numbering = owner instanceof OLElementContainer ? owner.start : 1;\n const reversed = owner instanceof OLElementContainer ? owner.reversed : false;\n for (let i = 0; i < elements.length; i++) {\n const item = elements[i];\n if (\n item.container instanceof LIElementContainer &&\n typeof item.container.value === 'number' &&\n item.container.value !== 0\n ) {\n numbering = item.container.value;\n }\n\n item.listValue = createCounterText(numbering, item.container.styles.listStyleType, true);\n\n numbering += reversed ? -1 : 1;\n }\n};\n\nexport const parseStackingContexts = (container: ElementContainer): StackingContext => {\n const paintContainer = new ElementPaint(container, null);\n const root = new StackingContext(paintContainer);\n const listItems: ElementPaint[] = [];\n parseStackTree(paintContainer, root, root, listItems);\n processListItems(paintContainer.container, listItems);\n return root;\n};\n","import {Path} from './path';\nimport {BoundCurves} from './bound-curves';\nimport {isBezierCurve} from './bezier-curve';\n\nexport const parsePathForBorder = (curves: BoundCurves, borderSide: number): Path[] => {\n switch (borderSide) {\n case 0:\n return createPathFromCurves(\n curves.topLeftBorderBox,\n curves.topLeftPaddingBox,\n curves.topRightBorderBox,\n curves.topRightPaddingBox\n );\n case 1:\n return createPathFromCurves(\n curves.topRightBorderBox,\n curves.topRightPaddingBox,\n curves.bottomRightBorderBox,\n curves.bottomRightPaddingBox\n );\n case 2:\n return createPathFromCurves(\n curves.bottomRightBorderBox,\n curves.bottomRightPaddingBox,\n curves.bottomLeftBorderBox,\n curves.bottomLeftPaddingBox\n );\n case 3:\n default:\n return createPathFromCurves(\n curves.bottomLeftBorderBox,\n curves.bottomLeftPaddingBox,\n curves.topLeftBorderBox,\n curves.topLeftPaddingBox\n );\n }\n};\n\nexport const parsePathForBorderDoubleOuter = (curves: BoundCurves, borderSide: number): Path[] => {\n switch (borderSide) {\n case 0:\n return createPathFromCurves(\n curves.topLeftBorderBox,\n curves.topLeftBorderDoubleOuterBox,\n curves.topRightBorderBox,\n curves.topRightBorderDoubleOuterBox\n );\n case 1:\n return createPathFromCurves(\n curves.topRightBorderBox,\n curves.topRightBorderDoubleOuterBox,\n curves.bottomRightBorderBox,\n curves.bottomRightBorderDoubleOuterBox\n );\n case 2:\n return createPathFromCurves(\n curves.bottomRightBorderBox,\n curves.bottomRightBorderDoubleOuterBox,\n curves.bottomLeftBorderBox,\n curves.bottomLeftBorderDoubleOuterBox\n );\n case 3:\n default:\n return createPathFromCurves(\n curves.bottomLeftBorderBox,\n curves.bottomLeftBorderDoubleOuterBox,\n curves.topLeftBorderBox,\n curves.topLeftBorderDoubleOuterBox\n );\n }\n};\n\nexport const parsePathForBorderDoubleInner = (curves: BoundCurves, borderSide: number): Path[] => {\n switch (borderSide) {\n case 0:\n return createPathFromCurves(\n curves.topLeftBorderDoubleInnerBox,\n curves.topLeftPaddingBox,\n curves.topRightBorderDoubleInnerBox,\n curves.topRightPaddingBox\n );\n case 1:\n return createPathFromCurves(\n curves.topRightBorderDoubleInnerBox,\n curves.topRightPaddingBox,\n curves.bottomRightBorderDoubleInnerBox,\n curves.bottomRightPaddingBox\n );\n case 2:\n return createPathFromCurves(\n curves.bottomRightBorderDoubleInnerBox,\n curves.bottomRightPaddingBox,\n curves.bottomLeftBorderDoubleInnerBox,\n curves.bottomLeftPaddingBox\n );\n case 3:\n default:\n return createPathFromCurves(\n curves.bottomLeftBorderDoubleInnerBox,\n curves.bottomLeftPaddingBox,\n curves.topLeftBorderDoubleInnerBox,\n curves.topLeftPaddingBox\n );\n }\n};\n\nexport const parsePathForBorderStroke = (curves: BoundCurves, borderSide: number): Path[] => {\n switch (borderSide) {\n case 0:\n return createStrokePathFromCurves(curves.topLeftBorderStroke, curves.topRightBorderStroke);\n case 1:\n return createStrokePathFromCurves(curves.topRightBorderStroke, curves.bottomRightBorderStroke);\n case 2:\n return createStrokePathFromCurves(curves.bottomRightBorderStroke, curves.bottomLeftBorderStroke);\n case 3:\n default:\n return createStrokePathFromCurves(curves.bottomLeftBorderStroke, curves.topLeftBorderStroke);\n }\n};\n\nconst createStrokePathFromCurves = (outer1: Path, outer2: Path): Path[] => {\n const path = [];\n if (isBezierCurve(outer1)) {\n path.push(outer1.subdivide(0.5, false));\n } else {\n path.push(outer1);\n }\n\n if (isBezierCurve(outer2)) {\n path.push(outer2.subdivide(0.5, true));\n } else {\n path.push(outer2);\n }\n\n return path;\n};\n\nconst createPathFromCurves = (outer1: Path, inner1: Path, outer2: Path, inner2: Path): Path[] => {\n const path = [];\n if (isBezierCurve(outer1)) {\n path.push(outer1.subdivide(0.5, false));\n } else {\n path.push(outer1);\n }\n\n if (isBezierCurve(outer2)) {\n path.push(outer2.subdivide(0.5, true));\n } else {\n path.push(outer2);\n }\n\n if (isBezierCurve(inner2)) {\n path.push(inner2.subdivide(0.5, true).reverse());\n } else {\n path.push(inner2);\n }\n\n if (isBezierCurve(inner1)) {\n path.push(inner1.subdivide(0.5, false).reverse());\n } else {\n path.push(inner1);\n }\n\n return path;\n};\n","import {getAbsoluteValue} from '../css/types/length-percentage';\nimport {Bounds} from '../css/layout/bounds';\nimport {ElementContainer} from '../dom/element-container';\n\nexport const paddingBox = (element: ElementContainer): Bounds => {\n const bounds = element.bounds;\n const styles = element.styles;\n return bounds.add(\n styles.borderLeftWidth,\n styles.borderTopWidth,\n -(styles.borderRightWidth + styles.borderLeftWidth),\n -(styles.borderTopWidth + styles.borderBottomWidth)\n );\n};\n\nexport const contentBox = (element: ElementContainer): Bounds => {\n const styles = element.styles;\n const bounds = element.bounds;\n\n const paddingLeft = getAbsoluteValue(styles.paddingLeft, bounds.width);\n const paddingRight = getAbsoluteValue(styles.paddingRight, bounds.width);\n const paddingTop = getAbsoluteValue(styles.paddingTop, bounds.width);\n const paddingBottom = getAbsoluteValue(styles.paddingBottom, bounds.width);\n\n return bounds.add(\n paddingLeft + styles.borderLeftWidth,\n paddingTop + styles.borderTopWidth,\n -(styles.borderRightWidth + styles.borderLeftWidth + paddingLeft + paddingRight),\n -(styles.borderTopWidth + styles.borderBottomWidth + paddingTop + paddingBottom)\n );\n};\n","import {Bounds} from '../css/layout/bounds';\nimport {BACKGROUND_ORIGIN} from '../css/property-descriptors/background-origin';\nimport {ElementContainer} from '../dom/element-container';\nimport {BACKGROUND_SIZE, BackgroundSizeInfo} from '../css/property-descriptors/background-size';\nimport {Vector} from './vector';\nimport {BACKGROUND_REPEAT} from '../css/property-descriptors/background-repeat';\nimport {getAbsoluteValue, getAbsoluteValueForTuple, isLengthPercentage} from '../css/types/length-percentage';\nimport {CSSValue, isIdentToken} from '../css/syntax/parser';\nimport {contentBox, paddingBox} from './box-sizing';\nimport {Path} from './path';\nimport {BACKGROUND_CLIP} from '../css/property-descriptors/background-clip';\n\nexport const calculateBackgroundPositioningArea = (\n backgroundOrigin: BACKGROUND_ORIGIN,\n element: ElementContainer\n): Bounds => {\n if (backgroundOrigin === BACKGROUND_ORIGIN.BORDER_BOX) {\n return element.bounds;\n }\n\n if (backgroundOrigin === BACKGROUND_ORIGIN.CONTENT_BOX) {\n return contentBox(element);\n }\n\n return paddingBox(element);\n};\n\nexport const calculateBackgroundPaintingArea = (backgroundClip: BACKGROUND_CLIP, element: ElementContainer): Bounds => {\n if (backgroundClip === BACKGROUND_CLIP.BORDER_BOX) {\n return element.bounds;\n }\n\n if (backgroundClip === BACKGROUND_CLIP.CONTENT_BOX) {\n return contentBox(element);\n }\n\n return paddingBox(element);\n};\n\nexport const calculateBackgroundRendering = (\n container: ElementContainer,\n index: number,\n intrinsicSize: [number | null, number | null, number | null]\n): [Path[], number, number, number, number] => {\n const backgroundPositioningArea = calculateBackgroundPositioningArea(\n getBackgroundValueForIndex(container.styles.backgroundOrigin, index),\n container\n );\n\n const backgroundPaintingArea = calculateBackgroundPaintingArea(\n getBackgroundValueForIndex(container.styles.backgroundClip, index),\n container\n );\n\n const backgroundImageSize = calculateBackgroundSize(\n getBackgroundValueForIndex(container.styles.backgroundSize, index),\n intrinsicSize,\n backgroundPositioningArea\n );\n\n const [sizeWidth, sizeHeight] = backgroundImageSize;\n\n const position = getAbsoluteValueForTuple(\n getBackgroundValueForIndex(container.styles.backgroundPosition, index),\n backgroundPositioningArea.width - sizeWidth,\n backgroundPositioningArea.height - sizeHeight\n );\n\n const path = calculateBackgroundRepeatPath(\n getBackgroundValueForIndex(container.styles.backgroundRepeat, index),\n position,\n backgroundImageSize,\n backgroundPositioningArea,\n backgroundPaintingArea\n );\n\n const offsetX = Math.round(backgroundPositioningArea.left + position[0]);\n const offsetY = Math.round(backgroundPositioningArea.top + position[1]);\n\n return [path, offsetX, offsetY, sizeWidth, sizeHeight];\n};\n\nexport const isAuto = (token: CSSValue): boolean => isIdentToken(token) && token.value === BACKGROUND_SIZE.AUTO;\n\nconst hasIntrinsicValue = (value: number | null): value is number => typeof value === 'number';\n\nexport const calculateBackgroundSize = (\n size: BackgroundSizeInfo[],\n [intrinsicWidth, intrinsicHeight, intrinsicProportion]: [number | null, number | null, number | null],\n bounds: Bounds\n): [number, number] => {\n const [first, second] = size;\n\n if (!first) {\n return [0, 0];\n }\n\n if (isLengthPercentage(first) && second && isLengthPercentage(second)) {\n return [getAbsoluteValue(first, bounds.width), getAbsoluteValue(second, bounds.height)];\n }\n\n const hasIntrinsicProportion = hasIntrinsicValue(intrinsicProportion);\n\n if (isIdentToken(first) && (first.value === BACKGROUND_SIZE.CONTAIN || first.value === BACKGROUND_SIZE.COVER)) {\n if (hasIntrinsicValue(intrinsicProportion)) {\n const targetRatio = bounds.width / bounds.height;\n\n return targetRatio < intrinsicProportion !== (first.value === BACKGROUND_SIZE.COVER)\n ? [bounds.width, bounds.width / intrinsicProportion]\n : [bounds.height * intrinsicProportion, bounds.height];\n }\n\n return [bounds.width, bounds.height];\n }\n\n const hasIntrinsicWidth = hasIntrinsicValue(intrinsicWidth);\n const hasIntrinsicHeight = hasIntrinsicValue(intrinsicHeight);\n const hasIntrinsicDimensions = hasIntrinsicWidth || hasIntrinsicHeight;\n\n // If the background-size is auto or auto auto:\n if (isAuto(first) && (!second || isAuto(second))) {\n // If the image has both horizontal and vertical intrinsic dimensions, it's rendered at that size.\n if (hasIntrinsicWidth && hasIntrinsicHeight) {\n return [intrinsicWidth as number, intrinsicHeight as number];\n }\n\n // If the image has no intrinsic dimensions and has no intrinsic proportions,\n // it's rendered at the size of the background positioning area.\n\n if (!hasIntrinsicProportion && !hasIntrinsicDimensions) {\n return [bounds.width, bounds.height];\n }\n\n // TODO If the image has no intrinsic dimensions but has intrinsic proportions, it's rendered as if contain had been specified instead.\n\n // If the image has only one intrinsic dimension and has intrinsic proportions, it's rendered at the size corresponding to that one dimension.\n // The other dimension is computed using the specified dimension and the intrinsic proportions.\n if (hasIntrinsicDimensions && hasIntrinsicProportion) {\n const width = hasIntrinsicWidth\n ? (intrinsicWidth as number)\n : (intrinsicHeight as number) * (intrinsicProportion as number);\n const height = hasIntrinsicHeight\n ? (intrinsicHeight as number)\n : (intrinsicWidth as number) / (intrinsicProportion as number);\n return [width, height];\n }\n\n // If the image has only one intrinsic dimension but has no intrinsic proportions,\n // it's rendered using the specified dimension and the other dimension of the background positioning area.\n const width = hasIntrinsicWidth ? (intrinsicWidth as number) : bounds.width;\n const height = hasIntrinsicHeight ? (intrinsicHeight as number) : bounds.height;\n return [width, height];\n }\n\n // If the image has intrinsic proportions, it's stretched to the specified dimension.\n // The unspecified dimension is computed using the specified dimension and the intrinsic proportions.\n if (hasIntrinsicProportion) {\n let width = 0;\n let height = 0;\n if (isLengthPercentage(first)) {\n width = getAbsoluteValue(first, bounds.width);\n } else if (isLengthPercentage(second)) {\n height = getAbsoluteValue(second, bounds.height);\n }\n\n if (isAuto(first)) {\n width = height * (intrinsicProportion as number);\n } else if (!second || isAuto(second)) {\n height = width / (intrinsicProportion as number);\n }\n\n return [width, height];\n }\n\n // If the image has no intrinsic proportions, it's stretched to the specified dimension.\n // The unspecified dimension is computed using the image's corresponding intrinsic dimension,\n // if there is one. If there is no such intrinsic dimension,\n // it becomes the corresponding dimension of the background positioning area.\n\n let width = null;\n let height = null;\n\n if (isLengthPercentage(first)) {\n width = getAbsoluteValue(first, bounds.width);\n } else if (second && isLengthPercentage(second)) {\n height = getAbsoluteValue(second, bounds.height);\n }\n\n if (width !== null && (!second || isAuto(second))) {\n height =\n hasIntrinsicWidth && hasIntrinsicHeight\n ? (width / (intrinsicWidth as number)) * (intrinsicHeight as number)\n : bounds.height;\n }\n\n if (height !== null && isAuto(first)) {\n width =\n hasIntrinsicWidth && hasIntrinsicHeight\n ? (height / (intrinsicHeight as number)) * (intrinsicWidth as number)\n : bounds.width;\n }\n\n if (width !== null && height !== null) {\n return [width, height];\n }\n\n throw new Error(`Unable to calculate background-size for element`);\n};\n\nexport const getBackgroundValueForIndex = <T>(values: T[], index: number): T => {\n const value = values[index];\n if (typeof value === 'undefined') {\n return values[0];\n }\n\n return value;\n};\n\nexport const calculateBackgroundRepeatPath = (\n repeat: BACKGROUND_REPEAT,\n [x, y]: [number, number],\n [width, height]: [number, number],\n backgroundPositioningArea: Bounds,\n backgroundPaintingArea: Bounds\n): [Vector, Vector, Vector, Vector] => {\n switch (repeat) {\n case BACKGROUND_REPEAT.REPEAT_X:\n return [\n new Vector(Math.round(backgroundPositioningArea.left), Math.round(backgroundPositioningArea.top + y)),\n new Vector(\n Math.round(backgroundPositioningArea.left + backgroundPositioningArea.width),\n Math.round(backgroundPositioningArea.top + y)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + backgroundPositioningArea.width),\n Math.round(height + backgroundPositioningArea.top + y)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left),\n Math.round(height + backgroundPositioningArea.top + y)\n )\n ];\n case BACKGROUND_REPEAT.REPEAT_Y:\n return [\n new Vector(Math.round(backgroundPositioningArea.left + x), Math.round(backgroundPositioningArea.top)),\n new Vector(\n Math.round(backgroundPositioningArea.left + x + width),\n Math.round(backgroundPositioningArea.top)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + x + width),\n Math.round(backgroundPositioningArea.height + backgroundPositioningArea.top)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + x),\n Math.round(backgroundPositioningArea.height + backgroundPositioningArea.top)\n )\n ];\n case BACKGROUND_REPEAT.NO_REPEAT:\n return [\n new Vector(\n Math.round(backgroundPositioningArea.left + x),\n Math.round(backgroundPositioningArea.top + y)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + x + width),\n Math.round(backgroundPositioningArea.top + y)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + x + width),\n Math.round(backgroundPositioningArea.top + y + height)\n ),\n new Vector(\n Math.round(backgroundPositioningArea.left + x),\n Math.round(backgroundPositioningArea.top + y + height)\n )\n ];\n default:\n return [\n new Vector(Math.round(backgroundPaintingArea.left), Math.round(backgroundPaintingArea.top)),\n new Vector(\n Math.round(backgroundPaintingArea.left + backgroundPaintingArea.width),\n Math.round(backgroundPaintingArea.top)\n ),\n new Vector(\n Math.round(backgroundPaintingArea.left + backgroundPaintingArea.width),\n Math.round(backgroundPaintingArea.height + backgroundPaintingArea.top)\n ),\n new Vector(\n Math.round(backgroundPaintingArea.left),\n Math.round(backgroundPaintingArea.height + backgroundPaintingArea.top)\n )\n ];\n }\n};\n","export const SMALL_IMAGE = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';\n","import {SMALL_IMAGE} from '../core/util';\nexport interface FontMetric {\n baseline: number;\n middle: number;\n}\n\nconst SAMPLE_TEXT = 'Hidden Text';\n\nexport class FontMetrics {\n private readonly _data: {[key: string]: FontMetric};\n private readonly _document: Document;\n\n constructor(document: Document) {\n this._data = {};\n this._document = document;\n }\n\n private parseMetrics(fontFamily: string, fontSize: string): FontMetric {\n const container = this._document.createElement('div');\n const img = this._document.createElement('img');\n const span = this._document.createElement('span');\n\n const body = this._document.body as HTMLBodyElement;\n\n container.style.visibility = 'hidden';\n container.style.fontFamily = fontFamily;\n container.style.fontSize = fontSize;\n container.style.margin = '0';\n container.style.padding = '0';\n container.style.whiteSpace = 'nowrap';\n\n body.appendChild(container);\n\n img.src = SMALL_IMAGE;\n img.width = 1;\n img.height = 1;\n\n img.style.margin = '0';\n img.style.padding = '0';\n img.style.verticalAlign = 'baseline';\n\n span.style.fontFamily = fontFamily;\n span.style.fontSize = fontSize;\n span.style.margin = '0';\n span.style.padding = '0';\n\n span.appendChild(this._document.createTextNode(SAMPLE_TEXT));\n container.appendChild(span);\n container.appendChild(img);\n const baseline = img.offsetTop - span.offsetTop + 2;\n\n container.removeChild(span);\n container.appendChild(this._document.createTextNode(SAMPLE_TEXT));\n\n container.style.lineHeight = 'normal';\n img.style.verticalAlign = 'super';\n\n const middle = img.offsetTop - container.offsetTop + 2;\n\n body.removeChild(container);\n\n return {baseline, middle};\n }\n getMetrics(fontFamily: string, fontSize: string): FontMetric {\n const key = `${fontFamily} ${fontSize}`;\n if (typeof this._data[key] === 'undefined') {\n this._data[key] = this.parseMetrics(fontFamily, fontSize);\n }\n\n return this._data[key];\n }\n}\n","import {Context} from '../core/context';\nimport {RenderConfigurations} from './canvas/canvas-renderer';\n\nexport class Renderer {\n constructor(protected readonly context: Context, protected readonly options: RenderConfigurations) {}\n}\n","import {ElementPaint, parseStackingContexts, StackingContext} from '../stacking-context';\nimport {asString, Color, isTransparent} from '../../css/types/color';\nimport {ElementContainer, FLAGS} from '../../dom/element-container';\nimport {BORDER_STYLE} from '../../css/property-descriptors/border-style';\nimport {CSSParsedDeclaration} from '../../css';\nimport {TextContainer} from '../../dom/text-container';\nimport {Path, transformPath} from '../path';\nimport {BACKGROUND_CLIP} from '../../css/property-descriptors/background-clip';\nimport {BoundCurves, calculateBorderBoxPath, calculateContentBoxPath, calculatePaddingBoxPath} from '../bound-curves';\nimport {BezierCurve, isBezierCurve} from '../bezier-curve';\nimport {Vector} from '../vector';\nimport {CSSImageType, CSSURLImage, isLinearGradient, isRadialGradient} from '../../css/types/image';\nimport {\n parsePathForBorder,\n parsePathForBorderDoubleInner,\n parsePathForBorderDoubleOuter,\n parsePathForBorderStroke\n} from '../border';\nimport {calculateBackgroundRendering, getBackgroundValueForIndex} from '../background';\nimport {isDimensionToken} from '../../css/syntax/parser';\nimport {segmentGraphemes, TextBounds} from '../../css/layout/text';\nimport {ImageElementContainer} from '../../dom/replaced-elements/image-element-container';\nimport {contentBox} from '../box-sizing';\nimport {CanvasElementContainer} from '../../dom/replaced-elements/canvas-element-container';\nimport {SVGElementContainer} from '../../dom/replaced-elements/svg-element-container';\nimport {ReplacedElementContainer} from '../../dom/replaced-elements';\nimport {EffectTarget, IElementEffect, isClipEffect, isOpacityEffect, isTransformEffect} from '../effects';\nimport {contains} from '../../core/bitwise';\nimport {calculateGradientDirection, calculateRadius, processColorStops} from '../../css/types/functions/gradient';\nimport {FIFTY_PERCENT, getAbsoluteValue} from '../../css/types/length-percentage';\nimport {TEXT_DECORATION_LINE} from '../../css/property-descriptors/text-decoration-line';\nimport {FontMetrics} from '../font-metrics';\nimport {DISPLAY} from '../../css/property-descriptors/display';\nimport {Bounds} from '../../css/layout/bounds';\nimport {LIST_STYLE_TYPE} from '../../css/property-descriptors/list-style-type';\nimport {computeLineHeight} from '../../css/property-descriptors/line-height';\nimport {CHECKBOX, INPUT_COLOR, InputElementContainer, RADIO} from '../../dom/replaced-elements/input-element-container';\nimport {TEXT_ALIGN} from '../../css/property-descriptors/text-align';\nimport {TextareaElementContainer} from '../../dom/elements/textarea-element-container';\nimport {SelectElementContainer} from '../../dom/elements/select-element-container';\nimport {IFrameElementContainer} from '../../dom/replaced-elements/iframe-element-container';\nimport {TextShadow} from '../../css/property-descriptors/text-shadow';\nimport {PAINT_ORDER_LAYER} from '../../css/property-descriptors/paint-order';\nimport {Renderer} from '../renderer';\nimport {Context} from '../../core/context';\nimport {DIRECTION} from '../../css/property-descriptors/direction';\n\nexport type RenderConfigurations = RenderOptions & {\n backgroundColor: Color | null;\n};\n\nexport interface RenderOptions {\n scale: number;\n canvas?: HTMLCanvasElement;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nconst MASK_OFFSET = 10000;\n\nexport class CanvasRenderer extends Renderer {\n canvas: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n private readonly _activeEffects: IElementEffect[] = [];\n private readonly fontMetrics: FontMetrics;\n\n constructor(context: Context, options: RenderConfigurations) {\n super(context, options);\n this.canvas = options.canvas ? options.canvas : document.createElement('canvas');\n this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D;\n if (!options.canvas) {\n this.canvas.width = Math.floor(options.width * options.scale);\n this.canvas.height = Math.floor(options.height * options.scale);\n this.canvas.style.width = `${options.width}px`;\n this.canvas.style.height = `${options.height}px`;\n }\n this.fontMetrics = new FontMetrics(document);\n this.ctx.scale(this.options.scale, this.options.scale);\n this.ctx.translate(-options.x, -options.y);\n this.ctx.textBaseline = 'bottom';\n this._activeEffects = [];\n this.context.logger.debug(\n `Canvas renderer initialized (${options.width}x${options.height}) with scale ${options.scale}`\n );\n }\n\n applyEffects(effects: IElementEffect[]): void {\n while (this._activeEffects.length) {\n this.popEffect();\n }\n\n effects.forEach((effect) => this.applyEffect(effect));\n }\n\n applyEffect(effect: IElementEffect): void {\n this.ctx.save();\n if (isOpacityEffect(effect)) {\n this.ctx.globalAlpha = effect.opacity;\n }\n\n if (isTransformEffect(effect)) {\n this.ctx.translate(effect.offsetX, effect.offsetY);\n this.ctx.transform(\n effect.matrix[0],\n effect.matrix[1],\n effect.matrix[2],\n effect.matrix[3],\n effect.matrix[4],\n effect.matrix[5]\n );\n this.ctx.translate(-effect.offsetX, -effect.offsetY);\n }\n\n if (isClipEffect(effect)) {\n this.path(effect.path);\n this.ctx.clip();\n }\n\n this._activeEffects.push(effect);\n }\n\n popEffect(): void {\n this._activeEffects.pop();\n this.ctx.restore();\n }\n\n async renderStack(stack: StackingContext): Promise<void> {\n const styles = stack.element.container.styles;\n if (styles.isVisible()) {\n await this.renderStackContent(stack);\n }\n }\n\n async renderNode(paint: ElementPaint): Promise<void> {\n if (contains(paint.container.flags, FLAGS.DEBUG_RENDER)) {\n debugger;\n }\n\n if (paint.container.styles.isVisible()) {\n await this.renderNodeBackgroundAndBorders(paint);\n await this.renderNodeContent(paint);\n }\n }\n\n renderTextWithLetterSpacing(text: TextBounds, letterSpacing: number, baseline: number): void {\n if (letterSpacing === 0) {\n this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + baseline);\n } else {\n const letters = segmentGraphemes(text.text);\n letters.reduce((left, letter) => {\n this.ctx.fillText(letter, left, text.bounds.top + baseline);\n\n return left + this.ctx.measureText(letter).width;\n }, text.bounds.left);\n }\n }\n\n private createFontStyle(styles: CSSParsedDeclaration): string[] {\n const fontVariant = styles.fontVariant\n .filter((variant) => variant === 'normal' || variant === 'small-caps')\n .join('');\n const fontFamily = fixIOSSystemFonts(styles.fontFamily).join(', ');\n const fontSize = isDimensionToken(styles.fontSize)\n ? `${styles.fontSize.number}${styles.fontSize.unit}`\n : `${styles.fontSize.number}px`;\n\n return [\n [styles.fontStyle, fontVariant, styles.fontWeight, fontSize, fontFamily].join(' '),\n fontFamily,\n fontSize\n ];\n }\n\n async renderTextNode(text: TextContainer, styles: CSSParsedDeclaration): Promise<void> {\n const [font, fontFamily, fontSize] = this.createFontStyle(styles);\n\n this.ctx.font = font;\n\n this.ctx.direction = styles.direction === DIRECTION.RTL ? 'rtl' : 'ltr';\n this.ctx.textAlign = 'left';\n this.ctx.textBaseline = 'alphabetic';\n const {baseline, middle} = this.fontMetrics.getMetrics(fontFamily, fontSize);\n const paintOrder = styles.paintOrder;\n\n text.textBounds.forEach((text) => {\n paintOrder.forEach((paintOrderLayer) => {\n switch (paintOrderLayer) {\n case PAINT_ORDER_LAYER.FILL:\n this.ctx.fillStyle = asString(styles.color);\n this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline);\n const textShadows: TextShadow = styles.textShadow;\n\n if (textShadows.length && text.text.trim().length) {\n textShadows\n .slice(0)\n .reverse()\n .forEach((textShadow) => {\n this.ctx.shadowColor = asString(textShadow.color);\n this.ctx.shadowOffsetX = textShadow.offsetX.number * this.options.scale;\n this.ctx.shadowOffsetY = textShadow.offsetY.number * this.options.scale;\n this.ctx.shadowBlur = textShadow.blur.number;\n\n this.renderTextWithLetterSpacing(text, styles.letterSpacing, baseline);\n });\n\n this.ctx.shadowColor = '';\n this.ctx.shadowOffsetX = 0;\n this.ctx.shadowOffsetY = 0;\n this.ctx.shadowBlur = 0;\n }\n\n if (styles.textDecorationLine.length) {\n this.ctx.fillStyle = asString(styles.textDecorationColor || styles.color);\n styles.textDecorationLine.forEach((textDecorationLine) => {\n switch (textDecorationLine) {\n case TEXT_DECORATION_LINE.UNDERLINE:\n // Draws a line at the baseline of the font\n // TODO As some browsers display the line as more than 1px if the font-size is big,\n // need to take that into account both in position and size\n this.ctx.fillRect(\n text.bounds.left,\n Math.round(text.bounds.top + baseline),\n text.bounds.width,\n 1\n );\n\n break;\n case TEXT_DECORATION_LINE.OVERLINE:\n this.ctx.fillRect(\n text.bounds.left,\n Math.round(text.bounds.top),\n text.bounds.width,\n 1\n );\n break;\n case TEXT_DECORATION_LINE.LINE_THROUGH:\n // TODO try and find exact position for line-through\n this.ctx.fillRect(\n text.bounds.left,\n Math.ceil(text.bounds.top + middle),\n text.bounds.width,\n 1\n );\n break;\n }\n });\n }\n break;\n case PAINT_ORDER_LAYER.STROKE:\n if (styles.webkitTextStrokeWidth && text.text.trim().length) {\n this.ctx.strokeStyle = asString(styles.webkitTextStrokeColor);\n this.ctx.lineWidth = styles.webkitTextStrokeWidth;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.ctx.lineJoin = !!(window as any).chrome ? 'miter' : 'round';\n this.ctx.strokeText(text.text, text.bounds.left, text.bounds.top + baseline);\n }\n this.ctx.strokeStyle = '';\n this.ctx.lineWidth = 0;\n this.ctx.lineJoin = 'miter';\n break;\n }\n });\n });\n }\n\n renderReplacedElement(\n container: ReplacedElementContainer,\n curves: BoundCurves,\n image: HTMLImageElement | HTMLCanvasElement\n ): void {\n if (image && container.intrinsicWidth > 0 && container.intrinsicHeight > 0) {\n const box = contentBox(container);\n const path = calculatePaddingBoxPath(curves);\n this.path(path);\n this.ctx.save();\n this.ctx.clip();\n this.ctx.drawImage(\n image,\n 0,\n 0,\n container.intrinsicWidth,\n container.intrinsicHeight,\n box.left,\n box.top,\n box.width,\n box.height\n );\n this.ctx.restore();\n }\n }\n\n async renderNodeContent(paint: ElementPaint): Promise<void> {\n this.applyEffects(paint.getEffects(EffectTarget.CONTENT));\n const container = paint.container;\n const curves = paint.curves;\n const styles = container.styles;\n for (const child of container.textNodes) {\n await this.renderTextNode(child, styles);\n }\n\n if (container instanceof ImageElementContainer) {\n try {\n const image = await this.context.cache.match(container.src);\n this.renderReplacedElement(container, curves, image);\n } catch (e) {\n this.context.logger.error(`Error loading image ${container.src}`);\n }\n }\n\n if (container instanceof CanvasElementContainer) {\n this.renderReplacedElement(container, curves, container.canvas);\n }\n\n if (container instanceof SVGElementContainer) {\n try {\n const image = await this.context.cache.match(container.svg);\n this.renderReplacedElement(container, curves, image);\n } catch (e) {\n this.context.logger.error(`Error loading svg ${container.svg.substring(0, 255)}`);\n }\n }\n\n if (container instanceof IFrameElementContainer && container.tree) {\n const iframeRenderer = new CanvasRenderer(this.context, {\n scale: this.options.scale,\n backgroundColor: container.backgroundColor,\n x: 0,\n y: 0,\n width: container.width,\n height: container.height\n });\n\n const canvas = await iframeRenderer.render(container.tree);\n if (container.width && container.height) {\n this.ctx.drawImage(\n canvas,\n 0,\n 0,\n container.width,\n container.height,\n container.bounds.left,\n container.bounds.top,\n container.bounds.width,\n container.bounds.height\n );\n }\n }\n\n if (container instanceof InputElementContainer) {\n const size = Math.min(container.bounds.width, container.bounds.height);\n\n if (container.type === CHECKBOX) {\n if (container.checked) {\n this.ctx.save();\n this.path([\n new Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79),\n new Vector(container.bounds.left + size * 0.16, container.bounds.top + size * 0.5549),\n new Vector(container.bounds.left + size * 0.27347, container.bounds.top + size * 0.44071),\n new Vector(container.bounds.left + size * 0.39694, container.bounds.top + size * 0.5649),\n new Vector(container.bounds.left + size * 0.72983, container.bounds.top + size * 0.23),\n new Vector(container.bounds.left + size * 0.84, container.bounds.top + size * 0.34085),\n new Vector(container.bounds.left + size * 0.39363, container.bounds.top + size * 0.79)\n ]);\n\n this.ctx.fillStyle = asString(INPUT_COLOR);\n this.ctx.fill();\n this.ctx.restore();\n }\n } else if (container.type === RADIO) {\n if (container.checked) {\n this.ctx.save();\n this.ctx.beginPath();\n this.ctx.arc(\n container.bounds.left + size / 2,\n container.bounds.top + size / 2,\n size / 4,\n 0,\n Math.PI * 2,\n true\n );\n this.ctx.fillStyle = asString(INPUT_COLOR);\n this.ctx.fill();\n this.ctx.restore();\n }\n }\n }\n\n if (isTextInputElement(container) && container.value.length) {\n const [fontFamily, fontSize] = this.createFontStyle(styles);\n const {baseline} = this.fontMetrics.getMetrics(fontFamily, fontSize);\n\n this.ctx.font = fontFamily;\n this.ctx.fillStyle = asString(styles.color);\n\n this.ctx.textBaseline = 'alphabetic';\n this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);\n\n const bounds = contentBox(container);\n\n let x = 0;\n\n switch (container.styles.textAlign) {\n case TEXT_ALIGN.CENTER:\n x += bounds.width / 2;\n break;\n case TEXT_ALIGN.RIGHT:\n x += bounds.width;\n break;\n }\n\n const textBounds = bounds.add(x, 0, 0, -bounds.height / 2 + 1);\n\n this.ctx.save();\n this.path([\n new Vector(bounds.left, bounds.top),\n new Vector(bounds.left + bounds.width, bounds.top),\n new Vector(bounds.left + bounds.width, bounds.top + bounds.height),\n new Vector(bounds.left, bounds.top + bounds.height)\n ]);\n\n this.ctx.clip();\n this.renderTextWithLetterSpacing(\n new TextBounds(container.value, textBounds),\n styles.letterSpacing,\n baseline\n );\n this.ctx.restore();\n this.ctx.textBaseline = 'alphabetic';\n this.ctx.textAlign = 'left';\n }\n\n if (contains(container.styles.display, DISPLAY.LIST_ITEM)) {\n if (container.styles.listStyleImage !== null) {\n const img = container.styles.listStyleImage;\n if (img.type === CSSImageType.URL) {\n let image;\n const url = (img as CSSURLImage).url;\n try {\n image = await this.context.cache.match(url);\n this.ctx.drawImage(image, container.bounds.left - (image.width + 10), container.bounds.top);\n } catch (e) {\n this.context.logger.error(`Error loading list-style-image ${url}`);\n }\n }\n } else if (paint.listValue && container.styles.listStyleType !== LIST_STYLE_TYPE.NONE) {\n const [fontFamily] = this.createFontStyle(styles);\n\n this.ctx.font = fontFamily;\n this.ctx.fillStyle = asString(styles.color);\n\n this.ctx.textBaseline = 'middle';\n this.ctx.textAlign = 'right';\n const bounds = new Bounds(\n container.bounds.left,\n container.bounds.top + getAbsoluteValue(container.styles.paddingTop, container.bounds.width),\n container.bounds.width,\n computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 1\n );\n\n this.renderTextWithLetterSpacing(\n new TextBounds(paint.listValue, bounds),\n styles.letterSpacing,\n computeLineHeight(styles.lineHeight, styles.fontSize.number) / 2 + 2\n );\n this.ctx.textBaseline = 'bottom';\n this.ctx.textAlign = 'left';\n }\n }\n }\n\n async renderStackContent(stack: StackingContext): Promise<void> {\n if (contains(stack.element.container.flags, FLAGS.DEBUG_RENDER)) {\n debugger;\n }\n // https://www.w3.org/TR/css-position-3/#painting-order\n // 1. the background and borders of the element forming the stacking context.\n await this.renderNodeBackgroundAndBorders(stack.element);\n // 2. the child stacking contexts with negative stack levels (most negative first).\n for (const child of stack.negativeZIndex) {\n await this.renderStack(child);\n }\n // 3. For all its in-flow, non-positioned, block-level descendants in tree order:\n await this.renderNodeContent(stack.element);\n\n for (const child of stack.nonInlineLevel) {\n await this.renderNode(child);\n }\n // 4. All non-positioned floating descendants, in tree order. For each one of these,\n // treat the element as if it created a new stacking context, but any positioned descendants and descendants\n // which actually create a new stacking context should be considered part of the parent stacking context,\n // not this new one.\n for (const child of stack.nonPositionedFloats) {\n await this.renderStack(child);\n }\n // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.\n for (const child of stack.nonPositionedInlineLevel) {\n await this.renderStack(child);\n }\n for (const child of stack.inlineLevel) {\n await this.renderNode(child);\n }\n // 6. All positioned, opacity or transform descendants, in tree order that fall into the following categories:\n // All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order.\n // For those with 'z-index: auto', treat the element as if it created a new stacking context,\n // but any positioned descendants and descendants which actually create a new stacking context should be\n // considered part of the parent stacking context, not this new one. For those with 'z-index: 0',\n // treat the stacking context generated atomically.\n //\n // All opacity descendants with opacity less than 1\n //\n // All transform descendants with transform other than none\n for (const child of stack.zeroOrAutoZIndexOrTransformedOrOpacity) {\n await this.renderStack(child);\n }\n // 7. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index\n // order (smallest first) then tree order.\n for (const child of stack.positiveZIndex) {\n await this.renderStack(child);\n }\n }\n\n mask(paths: Path[]): void {\n this.ctx.beginPath();\n this.ctx.moveTo(0, 0);\n this.ctx.lineTo(this.canvas.width, 0);\n this.ctx.lineTo(this.canvas.width, this.canvas.height);\n this.ctx.lineTo(0, this.canvas.height);\n this.ctx.lineTo(0, 0);\n this.formatPath(paths.slice(0).reverse());\n this.ctx.closePath();\n }\n\n path(paths: Path[]): void {\n this.ctx.beginPath();\n this.formatPath(paths);\n this.ctx.closePath();\n }\n\n formatPath(paths: Path[]): void {\n paths.forEach((point, index) => {\n const start: Vector = isBezierCurve(point) ? point.start : point;\n if (index === 0) {\n this.ctx.moveTo(start.x, start.y);\n } else {\n this.ctx.lineTo(start.x, start.y);\n }\n\n if (isBezierCurve(point)) {\n this.ctx.bezierCurveTo(\n point.startControl.x,\n point.startControl.y,\n point.endControl.x,\n point.endControl.y,\n point.end.x,\n point.end.y\n );\n }\n });\n }\n\n renderRepeat(path: Path[], pattern: CanvasPattern | CanvasGradient, offsetX: number, offsetY: number): void {\n this.path(path);\n this.ctx.fillStyle = pattern;\n this.ctx.translate(offsetX, offsetY);\n this.ctx.fill();\n this.ctx.translate(-offsetX, -offsetY);\n }\n\n resizeImage(image: HTMLImageElement, width: number, height: number): HTMLCanvasElement | HTMLImageElement {\n if (image.width === width && image.height === height) {\n return image;\n }\n\n const ownerDocument = this.canvas.ownerDocument ?? document;\n const canvas = ownerDocument.createElement('canvas');\n canvas.width = Math.max(1, width);\n canvas.height = Math.max(1, height);\n const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;\n ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height);\n return canvas;\n }\n\n async renderBackgroundImage(container: ElementContainer): Promise<void> {\n let index = container.styles.backgroundImage.length - 1;\n for (const backgroundImage of container.styles.backgroundImage.slice(0).reverse()) {\n if (backgroundImage.type === CSSImageType.URL) {\n let image;\n const url = (backgroundImage as CSSURLImage).url;\n try {\n image = await this.context.cache.match(url);\n } catch (e) {\n this.context.logger.error(`Error loading background-image ${url}`);\n }\n\n if (image) {\n const [path, x, y, width, height] = calculateBackgroundRendering(container, index, [\n image.width,\n image.height,\n image.width / image.height\n ]);\n const pattern = this.ctx.createPattern(\n this.resizeImage(image, width, height),\n 'repeat'\n ) as CanvasPattern;\n this.renderRepeat(path, pattern, x, y);\n }\n } else if (isLinearGradient(backgroundImage)) {\n const [path, x, y, width, height] = calculateBackgroundRendering(container, index, [null, null, null]);\n const [lineLength, x0, x1, y0, y1] = calculateGradientDirection(backgroundImage.angle, width, height);\n\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;\n const gradient = ctx.createLinearGradient(x0, y0, x1, y1);\n\n processColorStops(backgroundImage.stops, lineLength).forEach((colorStop) =>\n gradient.addColorStop(colorStop.stop, asString(colorStop.color))\n );\n\n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, width, height);\n if (width > 0 && height > 0) {\n const pattern = this.ctx.createPattern(canvas, 'repeat') as CanvasPattern;\n this.renderRepeat(path, pattern, x, y);\n }\n } else if (isRadialGradient(backgroundImage)) {\n const [path, left, top, width, height] = calculateBackgroundRendering(container, index, [\n null,\n null,\n null\n ]);\n const position = backgroundImage.position.length === 0 ? [FIFTY_PERCENT] : backgroundImage.position;\n const x = getAbsoluteValue(position[0], width);\n const y = getAbsoluteValue(position[position.length - 1], height);\n\n const [rx, ry] = calculateRadius(backgroundImage, x, y, width, height);\n if (rx > 0 && ry > 0) {\n const radialGradient = this.ctx.createRadialGradient(left + x, top + y, 0, left + x, top + y, rx);\n\n processColorStops(backgroundImage.stops, rx * 2).forEach((colorStop) =>\n radialGradient.addColorStop(colorStop.stop, asString(colorStop.color))\n );\n\n this.path(path);\n this.ctx.fillStyle = radialGradient;\n if (rx !== ry) {\n // transforms for elliptical radial gradient\n const midX = container.bounds.left + 0.5 * container.bounds.width;\n const midY = container.bounds.top + 0.5 * container.bounds.height;\n const f = ry / rx;\n const invF = 1 / f;\n\n this.ctx.save();\n this.ctx.translate(midX, midY);\n this.ctx.transform(1, 0, 0, f, 0, 0);\n this.ctx.translate(-midX, -midY);\n\n this.ctx.fillRect(left, invF * (top - midY) + midY, width, height * invF);\n this.ctx.restore();\n } else {\n this.ctx.fill();\n }\n }\n }\n index--;\n }\n }\n\n async renderSolidBorder(color: Color, side: number, curvePoints: BoundCurves): Promise<void> {\n this.path(parsePathForBorder(curvePoints, side));\n this.ctx.fillStyle = asString(color);\n this.ctx.fill();\n }\n\n async renderDoubleBorder(color: Color, width: number, side: number, curvePoints: BoundCurves): Promise<void> {\n if (width < 3) {\n await this.renderSolidBorder(color, side, curvePoints);\n return;\n }\n\n const outerPaths = parsePathForBorderDoubleOuter(curvePoints, side);\n this.path(outerPaths);\n this.ctx.fillStyle = asString(color);\n this.ctx.fill();\n const innerPaths = parsePathForBorderDoubleInner(curvePoints, side);\n this.path(innerPaths);\n this.ctx.fill();\n }\n\n async renderNodeBackgroundAndBorders(paint: ElementPaint): Promise<void> {\n this.applyEffects(paint.getEffects(EffectTarget.BACKGROUND_BORDERS));\n const styles = paint.container.styles;\n const hasBackground = !isTransparent(styles.backgroundColor) || styles.backgroundImage.length;\n\n const borders = [\n {style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth},\n {style: styles.borderRightStyle, color: styles.borderRightColor, width: styles.borderRightWidth},\n {style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth},\n {style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth}\n ];\n\n const backgroundPaintingArea = calculateBackgroundCurvedPaintingArea(\n getBackgroundValueForIndex(styles.backgroundClip, 0),\n paint.curves\n );\n\n if (hasBackground || styles.boxShadow.length) {\n this.ctx.save();\n this.path(backgroundPaintingArea);\n this.ctx.clip();\n\n if (!isTransparent(styles.backgroundColor)) {\n this.ctx.fillStyle = asString(styles.backgroundColor);\n this.ctx.fill();\n }\n\n await this.renderBackgroundImage(paint.container);\n\n this.ctx.restore();\n\n styles.boxShadow\n .slice(0)\n .reverse()\n .forEach((shadow) => {\n this.ctx.save();\n const borderBoxArea = calculateBorderBoxPath(paint.curves);\n const maskOffset = shadow.inset ? 0 : MASK_OFFSET;\n const shadowPaintingArea = transformPath(\n borderBoxArea,\n -maskOffset + (shadow.inset ? 1 : -1) * shadow.spread.number,\n (shadow.inset ? 1 : -1) * shadow.spread.number,\n shadow.spread.number * (shadow.inset ? -2 : 2),\n shadow.spread.number * (shadow.inset ? -2 : 2)\n );\n\n if (shadow.inset) {\n this.path(borderBoxArea);\n this.ctx.clip();\n this.mask(shadowPaintingArea);\n } else {\n this.mask(borderBoxArea);\n this.ctx.clip();\n this.path(shadowPaintingArea);\n }\n\n this.ctx.shadowOffsetX = shadow.offsetX.number + maskOffset;\n this.ctx.shadowOffsetY = shadow.offsetY.number;\n this.ctx.shadowColor = asString(shadow.color);\n this.ctx.shadowBlur = shadow.blur.number;\n this.ctx.fillStyle = shadow.inset ? asString(shadow.color) : 'rgba(0,0,0,1)';\n\n this.ctx.fill();\n this.ctx.restore();\n });\n }\n\n let side = 0;\n for (const border of borders) {\n if (border.style !== BORDER_STYLE.NONE && !isTransparent(border.color) && border.width > 0) {\n if (border.style === BORDER_STYLE.DASHED) {\n await this.renderDashedDottedBorder(\n border.color,\n border.width,\n side,\n paint.curves,\n BORDER_STYLE.DASHED\n );\n } else if (border.style === BORDER_STYLE.DOTTED) {\n await this.renderDashedDottedBorder(\n border.color,\n border.width,\n side,\n paint.curves,\n BORDER_STYLE.DOTTED\n );\n } else if (border.style === BORDER_STYLE.DOUBLE) {\n await this.renderDoubleBorder(border.color, border.width, side, paint.curves);\n } else {\n await this.renderSolidBorder(border.color, side, paint.curves);\n }\n }\n side++;\n }\n }\n\n async renderDashedDottedBorder(\n color: Color,\n width: number,\n side: number,\n curvePoints: BoundCurves,\n style: BORDER_STYLE\n ): Promise<void> {\n this.ctx.save();\n\n const strokePaths = parsePathForBorderStroke(curvePoints, side);\n const boxPaths = parsePathForBorder(curvePoints, side);\n\n if (style === BORDER_STYLE.DASHED) {\n this.path(boxPaths);\n this.ctx.clip();\n }\n\n let startX, startY, endX, endY;\n if (isBezierCurve(boxPaths[0])) {\n startX = (boxPaths[0] as BezierCurve).start.x;\n startY = (boxPaths[0] as BezierCurve).start.y;\n } else {\n startX = (boxPaths[0] as Vector).x;\n startY = (boxPaths[0] as Vector).y;\n }\n if (isBezierCurve(boxPaths[1])) {\n endX = (boxPaths[1] as BezierCurve).end.x;\n endY = (boxPaths[1] as BezierCurve).end.y;\n } else {\n endX = (boxPaths[1] as Vector).x;\n endY = (boxPaths[1] as Vector).y;\n }\n\n let length;\n if (side === 0 || side === 2) {\n length = Math.abs(startX - endX);\n } else {\n length = Math.abs(startY - endY);\n }\n\n this.ctx.beginPath();\n if (style === BORDER_STYLE.DOTTED) {\n this.formatPath(strokePaths);\n } else {\n this.formatPath(boxPaths.slice(0, 2));\n }\n\n let dashLength = width < 3 ? width * 3 : width * 2;\n let spaceLength = width < 3 ? width * 2 : width;\n if (style === BORDER_STYLE.DOTTED) {\n dashLength = width;\n spaceLength = width;\n }\n\n let useLineDash = true;\n if (length <= dashLength * 2) {\n useLineDash = false;\n } else if (length <= dashLength * 2 + spaceLength) {\n const multiplier = length / (2 * dashLength + spaceLength);\n dashLength *= multiplier;\n spaceLength *= multiplier;\n } else {\n const numberOfDashes = Math.floor((length + spaceLength) / (dashLength + spaceLength));\n const minSpace = (length - numberOfDashes * dashLength) / (numberOfDashes - 1);\n const maxSpace = (length - (numberOfDashes + 1) * dashLength) / numberOfDashes;\n spaceLength =\n maxSpace <= 0 || Math.abs(spaceLength - minSpace) < Math.abs(spaceLength - maxSpace)\n ? minSpace\n : maxSpace;\n }\n\n if (useLineDash) {\n if (style === BORDER_STYLE.DOTTED) {\n this.ctx.setLineDash([0, dashLength + spaceLength]);\n } else {\n this.ctx.setLineDash([dashLength, spaceLength]);\n }\n }\n\n if (style === BORDER_STYLE.DOTTED) {\n this.ctx.lineCap = 'round';\n this.ctx.lineWidth = width;\n } else {\n this.ctx.lineWidth = width * 2 + 1.1;\n }\n this.ctx.strokeStyle = asString(color);\n this.ctx.stroke();\n this.ctx.setLineDash([]);\n\n // dashed round edge gap\n if (style === BORDER_STYLE.DASHED) {\n if (isBezierCurve(boxPaths[0])) {\n const path1 = boxPaths[3] as BezierCurve;\n const path2 = boxPaths[0] as BezierCurve;\n this.ctx.beginPath();\n this.formatPath([new Vector(path1.end.x, path1.end.y), new Vector(path2.start.x, path2.start.y)]);\n this.ctx.stroke();\n }\n if (isBezierCurve(boxPaths[1])) {\n const path1 = boxPaths[1] as BezierCurve;\n const path2 = boxPaths[2] as BezierCurve;\n this.ctx.beginPath();\n this.formatPath([new Vector(path1.end.x, path1.end.y), new Vector(path2.start.x, path2.start.y)]);\n this.ctx.stroke();\n }\n }\n\n this.ctx.restore();\n }\n\n async render(element: ElementContainer): Promise<HTMLCanvasElement> {\n if (this.options.backgroundColor) {\n this.ctx.fillStyle = asString(this.options.backgroundColor);\n this.ctx.fillRect(this.options.x, this.options.y, this.options.width, this.options.height);\n }\n\n const stack = parseStackingContexts(element);\n\n await this.renderStack(stack);\n this.applyEffects([]);\n return this.canvas;\n }\n}\n\nconst isTextInputElement = (\n container: ElementContainer\n): container is InputElementContainer | TextareaElementContainer | SelectElementContainer => {\n if (container instanceof TextareaElementContainer) {\n return true;\n } else if (container instanceof SelectElementContainer) {\n return true;\n } else if (container instanceof InputElementContainer && container.type !== RADIO && container.type !== CHECKBOX) {\n return true;\n }\n return false;\n};\n\nconst calculateBackgroundCurvedPaintingArea = (clip: BACKGROUND_CLIP, curves: BoundCurves): Path[] => {\n switch (clip) {\n case BACKGROUND_CLIP.BORDER_BOX:\n return calculateBorderBoxPath(curves);\n case BACKGROUND_CLIP.CONTENT_BOX:\n return calculateContentBoxPath(curves);\n case BACKGROUND_CLIP.PADDING_BOX:\n default:\n return calculatePaddingBoxPath(curves);\n }\n};\n\nconst canvasTextAlign = (textAlign: TEXT_ALIGN): CanvasTextAlign => {\n switch (textAlign) {\n case TEXT_ALIGN.CENTER:\n return 'center';\n case TEXT_ALIGN.RIGHT:\n return 'right';\n case TEXT_ALIGN.LEFT:\n default:\n return 'left';\n }\n};\n\n// see https://github.com/niklasvh/html2canvas/pull/2645\nconst iOSBrokenFonts = ['-apple-system', 'system-ui'];\n\nconst fixIOSSystemFonts = (fontFamilies: string[]): string[] => {\n return /iPhone OS 15_(0|1)/.test(window.navigator.userAgent)\n ? fontFamilies.filter((fontFamily) => iOSBrokenFonts.indexOf(fontFamily) === -1)\n : fontFamilies;\n};\n","import {RenderConfigurations} from './canvas-renderer';\nimport {createForeignObjectSVG} from '../../core/features';\nimport {asString} from '../../css/types/color';\nimport {Renderer} from '../renderer';\nimport {Context} from '../../core/context';\n\nexport class ForeignObjectRenderer extends Renderer {\n canvas: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n options: RenderConfigurations;\n\n constructor(context: Context, options: RenderConfigurations) {\n super(context, options);\n this.canvas = options.canvas ? options.canvas : document.createElement('canvas');\n this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D;\n this.options = options;\n this.canvas.width = Math.floor(options.width * options.scale);\n this.canvas.height = Math.floor(options.height * options.scale);\n this.canvas.style.width = `${options.width}px`;\n this.canvas.style.height = `${options.height}px`;\n\n this.ctx.scale(this.options.scale, this.options.scale);\n this.ctx.translate(-options.x, -options.y);\n this.context.logger.debug(\n `EXPERIMENTAL ForeignObject renderer initialized (${options.width}x${options.height} at ${options.x},${options.y}) with scale ${options.scale}`\n );\n }\n\n async render(element: HTMLElement): Promise<HTMLCanvasElement> {\n const svg = createForeignObjectSVG(\n this.options.width * this.options.scale,\n this.options.height * this.options.scale,\n this.options.scale,\n this.options.scale,\n element\n );\n\n const img = await loadSerializedSVG(svg);\n\n if (this.options.backgroundColor) {\n this.ctx.fillStyle = asString(this.options.backgroundColor);\n this.ctx.fillRect(0, 0, this.options.width * this.options.scale, this.options.height * this.options.scale);\n }\n\n this.ctx.drawImage(img, -this.options.x * this.options.scale, -this.options.y * this.options.scale);\n\n return this.canvas;\n }\n}\n\nexport const loadSerializedSVG = (svg: Node): Promise<HTMLImageElement> =>\n new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n resolve(img);\n };\n img.onerror = reject;\n\n img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;\n });\n","export interface LoggerOptions {\n id: string;\n enabled: boolean;\n}\n\nexport class Logger {\n static instances: {[key: string]: Logger} = {};\n\n private readonly id: string;\n private readonly enabled: boolean;\n private readonly start: number;\n\n constructor({id, enabled}: LoggerOptions) {\n this.id = id;\n this.enabled = enabled;\n this.start = Date.now();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n debug(...args: unknown[]): void {\n if (this.enabled) {\n // eslint-disable-next-line no-console\n if (typeof window !== 'undefined' && window.console && typeof console.debug === 'function') {\n // eslint-disable-next-line no-console\n console.debug(this.id, `${this.getTime()}ms`, ...args);\n } else {\n this.info(...args);\n }\n }\n }\n\n getTime(): number {\n return Date.now() - this.start;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n info(...args: unknown[]): void {\n if (this.enabled) {\n // eslint-disable-next-line no-console\n if (typeof window !== 'undefined' && window.console && typeof console.info === 'function') {\n // eslint-disable-next-line no-console\n console.info(this.id, `${this.getTime()}ms`, ...args);\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n warn(...args: unknown[]): void {\n if (this.enabled) {\n // eslint-disable-next-line no-console\n if (typeof window !== 'undefined' && window.console && typeof console.warn === 'function') {\n // eslint-disable-next-line no-console\n console.warn(this.id, `${this.getTime()}ms`, ...args);\n } else {\n this.info(...args);\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error(...args: unknown[]): void {\n if (this.enabled) {\n // eslint-disable-next-line no-console\n if (typeof window !== 'undefined' && window.console && typeof console.error === 'function') {\n // eslint-disable-next-line no-console\n console.error(this.id, `${this.getTime()}ms`, ...args);\n } else {\n this.info(...args);\n }\n }\n }\n}\n","import {Logger} from './logger';\nimport {Cache, ResourceOptions} from './cache-storage';\nimport {Bounds} from '../css/layout/bounds';\n\nexport type ContextOptions = {\n logging: boolean;\n cache?: Cache;\n} & ResourceOptions;\n\nexport class Context {\n private readonly instanceName = `#${Context.instanceCount++}`;\n readonly logger: Logger;\n readonly cache: Cache;\n\n private static instanceCount = 1;\n\n constructor(options: ContextOptions, public windowBounds: Bounds) {\n this.logger = new Logger({id: this.instanceName, enabled: options.logging});\n this.cache = options.cache ?? new Cache(this, options);\n }\n}\n","import {Bounds, parseBounds, parseDocumentSize} from './css/layout/bounds';\nimport {COLORS, isTransparent, parseColor} from './css/types/color';\nimport {CloneConfigurations, CloneOptions, DocumentCloner, WindowOptions} from './dom/document-cloner';\nimport {isBodyElement, isHTMLElement, parseTree} from './dom/node-parser';\nimport {CacheStorage} from './core/cache-storage';\nimport {CanvasRenderer, RenderConfigurations, RenderOptions} from './render/canvas/canvas-renderer';\nimport {ForeignObjectRenderer} from './render/canvas/foreignobject-renderer';\nimport {Context, ContextOptions} from './core/context';\n\nexport type Options = CloneOptions &\n WindowOptions &\n RenderOptions &\n ContextOptions & {\n backgroundColor: string | null;\n foreignObjectRendering: boolean;\n removeContainer?: boolean;\n };\n\nconst html2canvas = (element: HTMLElement, options: Partial<Options> = {}): Promise<HTMLCanvasElement> => {\n return renderElement(element, options);\n};\n\nexport default html2canvas;\n\nif (typeof window !== 'undefined') {\n CacheStorage.setContext(window);\n}\n\nconst renderElement = async (element: HTMLElement, opts: Partial<Options>): Promise<HTMLCanvasElement> => {\n if (!element || typeof element !== 'object') {\n return Promise.reject('Invalid element provided as first argument');\n }\n const ownerDocument = element.ownerDocument;\n\n if (!ownerDocument) {\n throw new Error(`Element is not attached to a Document`);\n }\n\n const defaultView = ownerDocument.defaultView;\n\n if (!defaultView) {\n throw new Error(`Document is not attached to a Window`);\n }\n\n const resourceOptions = {\n allowTaint: opts.allowTaint ?? false,\n imageTimeout: opts.imageTimeout ?? 15000,\n proxy: opts.proxy,\n useCORS: opts.useCORS ?? false\n };\n\n const contextOptions = {\n logging: opts.logging ?? true,\n cache: opts.cache,\n ...resourceOptions\n };\n\n const windowOptions = {\n windowWidth: opts.windowWidth ?? defaultView.innerWidth,\n windowHeight: opts.windowHeight ?? defaultView.innerHeight,\n scrollX: opts.scrollX ?? defaultView.pageXOffset,\n scrollY: opts.scrollY ?? defaultView.pageYOffset\n };\n\n const windowBounds = new Bounds(\n windowOptions.scrollX,\n windowOptions.scrollY,\n windowOptions.windowWidth,\n windowOptions.windowHeight\n );\n\n const context = new Context(contextOptions, windowBounds);\n\n const foreignObjectRendering = opts.foreignObjectRendering ?? false;\n\n const cloneOptions: CloneConfigurations = {\n allowTaint: opts.allowTaint ?? false,\n onclone: opts.onclone,\n ignoreElements: opts.ignoreElements,\n inlineImages: foreignObjectRendering,\n copyStyles: foreignObjectRendering\n };\n\n context.logger.debug(\n `Starting document clone with size ${windowBounds.width}x${\n windowBounds.height\n } scrolled to ${-windowBounds.left},${-windowBounds.top}`\n );\n\n const documentCloner = new DocumentCloner(context, element, cloneOptions);\n const clonedElement = documentCloner.clonedReferenceElement;\n if (!clonedElement) {\n return Promise.reject(`Unable to find element in cloned iframe`);\n }\n\n const container = await documentCloner.toIFrame(ownerDocument, windowBounds);\n\n const {width, height, left, top} =\n isBodyElement(clonedElement) || isHTMLElement(clonedElement)\n ? parseDocumentSize(clonedElement.ownerDocument)\n : parseBounds(context, clonedElement);\n\n const backgroundColor = parseBackgroundColor(context, clonedElement, opts.backgroundColor);\n\n const renderOptions: RenderConfigurations = {\n canvas: opts.canvas,\n backgroundColor,\n scale: opts.scale ?? defaultView.devicePixelRatio ?? 1,\n x: (opts.x ?? 0) + left,\n y: (opts.y ?? 0) + top,\n width: opts.width ?? Math.ceil(width),\n height: opts.height ?? Math.ceil(height)\n };\n\n let canvas;\n\n if (foreignObjectRendering) {\n context.logger.debug(`Document cloned, using foreign object rendering`);\n const renderer = new ForeignObjectRenderer(context, renderOptions);\n canvas = await renderer.render(clonedElement);\n } else {\n context.logger.debug(\n `Document cloned, element located at ${left},${top} with size ${width}x${height} using computed rendering`\n );\n\n context.logger.debug(`Starting DOM parsing`);\n const root = parseTree(context, clonedElement);\n\n if (backgroundColor === root.styles.backgroundColor) {\n root.styles.backgroundColor = COLORS.TRANSPARENT;\n }\n\n context.logger.debug(\n `Starting renderer for element at ${renderOptions.x},${renderOptions.y} with size ${renderOptions.width}x${renderOptions.height}`\n );\n\n const renderer = new CanvasRenderer(context, renderOptions);\n canvas = await renderer.render(root);\n }\n\n if (opts.removeContainer ?? true) {\n if (!DocumentCloner.destroy(container)) {\n context.logger.error(`Cannot detach cloned iframe as it is not in the DOM anymore`);\n }\n }\n\n context.logger.debug(`Finished rendering`);\n return canvas;\n};\n\nconst parseBackgroundColor = (context: Context, element: HTMLElement, backgroundColorOverride?: string | null) => {\n const ownerDocument = element.ownerDocument;\n // http://www.w3.org/TR/css3-background/#special-backgrounds\n const documentBackgroundColor = ownerDocument.documentElement\n ? parseColor(context, getComputedStyle(ownerDocument.documentElement).backgroundColor as string)\n : COLORS.TRANSPARENT;\n const bodyBackgroundColor = ownerDocument.body\n ? parseColor(context, getComputedStyle(ownerDocument.body).backgroundColor as string)\n : COLORS.TRANSPARENT;\n\n const defaultBackgroundColor =\n typeof backgroundColorOverride === 'string'\n ? parseColor(context, backgroundColorOverride)\n : backgroundColorOverride === null\n ? COLORS.TRANSPARENT\n : 0xffffffff;\n\n return element === ownerDocument.documentElement\n ? isTransparent(documentBackgroundColor)\n ? isTransparent(bodyBackgroundColor)\n ? defaultBackgroundColor\n : bodyBackgroundColor\n : documentBackgroundColor\n : defaultBackgroundColor;\n};\n","import type { SitepingConfig, SitepingInstance } from \"@siteping/core\";\nimport { launch } from \"./launcher.js\";\n\nexport type {\n AnchorData,\n AnnotationPayload,\n AnnotationResponse,\n FeedbackPayload,\n FeedbackResponse,\n FeedbackStatus,\n FeedbackType,\n RectData,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEvents,\n SitepingStore,\n} from \"@siteping/core\";\n\nexport type { Identity } from \"./identity.js\";\n\n/**\n * Initialize the Siteping feedback widget.\n *\n * @example\n * ```ts\n * import { initSiteping } from '@siteping/widget'\n *\n * const { destroy } = initSiteping({\n * endpoint: '/api/siteping',\n * projectName: 'my-project',\n * })\n * ```\n */\nexport function initSiteping(config: SitepingConfig): SitepingInstance {\n return launch(config);\n}\n","// License: MIT\n// Author: Anton Medvedev <anton@medv.io>\n// Source: https://github.com/antonmedv/finder\nlet config;\nlet rootDocument;\nlet start;\nexport function finder(input, options) {\n start = new Date();\n if (input.nodeType !== Node.ELEMENT_NODE) {\n throw new Error(`Can't generate CSS selector for non-element node type.`);\n }\n if ('html' === input.tagName.toLowerCase()) {\n return 'html';\n }\n const defaults = {\n root: document.body,\n idName: (name) => true,\n className: (name) => true,\n tagName: (name) => true,\n attr: (name, value) => false,\n seedMinLength: 1,\n optimizedMinLength: 2,\n threshold: 1000,\n maxNumberOfTries: 10000,\n timeoutMs: undefined,\n };\n config = { ...defaults, ...options };\n rootDocument = findRootDocument(config.root, defaults);\n let path = bottomUpSearch(input, 'all', () => bottomUpSearch(input, 'two', () => bottomUpSearch(input, 'one', () => bottomUpSearch(input, 'none'))));\n if (path) {\n const optimized = sort(optimize(path, input));\n if (optimized.length > 0) {\n path = optimized[0];\n }\n return selector(path);\n }\n else {\n throw new Error(`Selector was not found.`);\n }\n}\nfunction findRootDocument(rootNode, defaults) {\n if (rootNode.nodeType === Node.DOCUMENT_NODE) {\n return rootNode;\n }\n if (rootNode === defaults.root) {\n return rootNode.ownerDocument;\n }\n return rootNode;\n}\nfunction bottomUpSearch(input, limit, fallback) {\n let path = null;\n let stack = [];\n let current = input;\n let i = 0;\n while (current) {\n const elapsedTime = new Date().getTime() - start.getTime();\n if (config.timeoutMs !== undefined && elapsedTime > config.timeoutMs) {\n throw new Error(`Timeout: Can't find a unique selector after ${elapsedTime}ms`);\n }\n let level = maybe(id(current)) ||\n maybe(...attr(current)) ||\n maybe(...classNames(current)) ||\n maybe(tagName(current)) || [any()];\n const nth = index(current);\n if (limit == 'all') {\n if (nth) {\n level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));\n }\n }\n else if (limit == 'two') {\n level = level.slice(0, 1);\n if (nth) {\n level = level.concat(level.filter(dispensableNth).map((node) => nthChild(node, nth)));\n }\n }\n else if (limit == 'one') {\n const [node] = (level = level.slice(0, 1));\n if (nth && dispensableNth(node)) {\n level = [nthChild(node, nth)];\n }\n }\n else if (limit == 'none') {\n level = [any()];\n if (nth) {\n level = [nthChild(level[0], nth)];\n }\n }\n for (let node of level) {\n node.level = i;\n }\n stack.push(level);\n if (stack.length >= config.seedMinLength) {\n path = findUniquePath(stack, fallback);\n if (path) {\n break;\n }\n }\n current = current.parentElement;\n i++;\n }\n if (!path) {\n path = findUniquePath(stack, fallback);\n }\n if (!path && fallback) {\n return fallback();\n }\n return path;\n}\nfunction findUniquePath(stack, fallback) {\n const paths = sort(combinations(stack));\n if (paths.length > config.threshold) {\n return fallback ? fallback() : null;\n }\n for (let candidate of paths) {\n if (unique(candidate)) {\n return candidate;\n }\n }\n return null;\n}\nfunction selector(path) {\n let node = path[0];\n let query = node.name;\n for (let i = 1; i < path.length; i++) {\n const level = path[i].level || 0;\n if (node.level === level - 1) {\n query = `${path[i].name} > ${query}`;\n }\n else {\n query = `${path[i].name} ${query}`;\n }\n node = path[i];\n }\n return query;\n}\nfunction penalty(path) {\n return path.map((node) => node.penalty).reduce((acc, i) => acc + i, 0);\n}\nfunction unique(path) {\n const css = selector(path);\n switch (rootDocument.querySelectorAll(css).length) {\n case 0:\n throw new Error(`Can't select any node with this selector: ${css}`);\n case 1:\n return true;\n default:\n return false;\n }\n}\nfunction id(input) {\n const elementId = input.getAttribute('id');\n if (elementId && config.idName(elementId)) {\n return {\n name: '#' + CSS.escape(elementId),\n penalty: 0,\n };\n }\n return null;\n}\nfunction attr(input) {\n const attrs = Array.from(input.attributes).filter((attr) => config.attr(attr.name, attr.value));\n return attrs.map((attr) => ({\n name: `[${CSS.escape(attr.name)}=\"${CSS.escape(attr.value)}\"]`,\n penalty: 0.5,\n }));\n}\nfunction classNames(input) {\n const names = Array.from(input.classList).filter(config.className);\n return names.map((name) => ({\n name: '.' + CSS.escape(name),\n penalty: 1,\n }));\n}\nfunction tagName(input) {\n const name = input.tagName.toLowerCase();\n if (config.tagName(name)) {\n return {\n name,\n penalty: 2,\n };\n }\n return null;\n}\nfunction any() {\n return {\n name: '*',\n penalty: 3,\n };\n}\nfunction index(input) {\n const parent = input.parentNode;\n if (!parent) {\n return null;\n }\n let child = parent.firstChild;\n if (!child) {\n return null;\n }\n let i = 0;\n while (child) {\n if (child.nodeType === Node.ELEMENT_NODE) {\n i++;\n }\n if (child === input) {\n break;\n }\n child = child.nextSibling;\n }\n return i;\n}\nfunction nthChild(node, i) {\n return {\n name: node.name + `:nth-child(${i})`,\n penalty: node.penalty + 1,\n };\n}\nfunction dispensableNth(node) {\n return node.name !== 'html' && !node.name.startsWith('#');\n}\nfunction maybe(...level) {\n const list = level.filter(notEmpty);\n if (list.length > 0) {\n return list;\n }\n return null;\n}\nfunction notEmpty(value) {\n return value !== null && value !== undefined;\n}\nfunction* combinations(stack, path = []) {\n if (stack.length > 0) {\n for (let node of stack[0]) {\n yield* combinations(stack.slice(1, stack.length), path.concat(node));\n }\n }\n else {\n yield path;\n }\n}\nfunction sort(paths) {\n return [...paths].sort((a, b) => penalty(a) - penalty(b));\n}\nfunction* optimize(path, input, scope = {\n counter: 0,\n visited: new Map(),\n}) {\n if (path.length > 2 && path.length > config.optimizedMinLength) {\n for (let i = 1; i < path.length - 1; i++) {\n if (scope.counter > config.maxNumberOfTries) {\n return; // Okay At least I tried!\n }\n scope.counter += 1;\n const newPath = [...path];\n newPath.splice(i, 1);\n const newPathKey = selector(newPath);\n if (scope.visited.has(newPathKey)) {\n return;\n }\n if (unique(newPath) && same(newPath, input)) {\n yield newPath;\n scope.visited.set(newPathKey, true);\n yield* optimize(newPath, input, scope);\n }\n }\n }\n}\nfunction same(path, input) {\n return rootDocument.querySelector(selector(path)) === input;\n}\n","/**\n * Element fingerprinting for robust DOM re-anchoring.\n *\n * Captures structural properties (child count, sibling index, stable attributes)\n * that survive CSS class changes and minor DOM reshuffling.\n * Inspired by Similo (academic state-of-the-art, 98.8% accuracy).\n */\n\nconst STABLE_ATTRS = [\"role\", \"aria-label\", \"type\", \"name\", \"href\", \"src\", \"data-testid\", \"data-id\"] as const;\n\n/** Simple 32-bit hash (djb2). */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * Generate a compact structural fingerprint for a DOM element.\n *\n * Format: `\"childCount:siblingIdx:attrHash\"`\n * - `childCount` — number of direct child elements\n * - `siblingIdx` — position among same-tag siblings (0-based)\n * - `attrHash` — djb2 hash of stable attributes (role, aria-label, type, etc.)\n *\n * Tag name is NOT included — it's stored separately in `AnchorData.elementTag`.\n */\nexport function generateFingerprint(element: Element): string {\n const childCount = element.children.length;\n\n // Position among same-tag siblings\n let siblingIdx = 0;\n const parent = element.parentElement;\n if (parent) {\n for (const child of parent.children) {\n if (child === element) break;\n if (child.tagName === element.tagName) siblingIdx++;\n }\n }\n\n // Hash stable attributes\n const attrs: string[] = [];\n for (const attr of STABLE_ATTRS) {\n const val = element.getAttribute(attr);\n if (val) attrs.push(`${attr}=${val}`);\n }\n const attrHash = attrs.length > 0 ? djb2(attrs.join(\",\")) : \"0\";\n\n return `${childCount}:${siblingIdx}:${attrHash}`;\n}\n\n/**\n * Score how well a candidate element matches a stored fingerprint.\n * Returns 0–1.\n *\n * Weights:\n * - Child count match: 0.2 (tolerant — ±2 gets partial credit)\n * - Sibling index match: 0.4 (positional — most discriminating)\n * - Attribute hash match: 0.4 (identity — exact or nothing)\n */\nexport function scoreFingerprint(candidate: Element, storedFingerprint: string): number {\n const parts = storedFingerprint.split(\":\");\n if (parts.length !== 3) return 0;\n\n const [storedChildren, storedSibIdx, storedAttrHash] = parts;\n const storedChildCount = Number(storedChildren);\n const storedSibIndex = Number(storedSibIdx);\n if (Number.isNaN(storedChildCount) || Number.isNaN(storedSibIndex)) return 0;\n\n const candidateFp = generateFingerprint(candidate);\n const [candChildren, candSibIdx, candAttrHash] = candidateFp.split(\":\");\n\n let score = 0;\n\n // Child count (0.2)\n const childDiff = Math.abs(Number(candChildren) - storedChildCount);\n if (childDiff === 0) score += 0.2;\n else if (childDiff <= 2) score += 0.1;\n else if (childDiff <= 5) score += 0.03;\n\n // Sibling index (0.4)\n const sibDiff = Math.abs(Number(candSibIdx) - storedSibIndex);\n if (sibDiff === 0) score += 0.4;\n else if (sibDiff === 1) score += 0.2;\n else if (sibDiff <= 3) score += 0.08;\n\n // Attribute hash (0.4)\n if (candAttrHash === storedAttrHash) score += 0.4;\n\n return score;\n}\n","/**\n * Shared text-context helpers for DOM anchoring.\n * Used by both anchor generation (anchor.ts) and resolution (resolver.ts).\n */\n\n/**\n * Extract ~32 chars of text from the nearest sibling with content.\n * Walks up to 3 siblings in the given direction.\n */\nexport function adjacentText(element: Element, direction: \"before\" | \"after\"): string {\n const prop = direction === \"before\" ? \"previousElementSibling\" : \"nextElementSibling\";\n let sibling: Element | null = element[prop];\n let attempts = 3;\n\n while (sibling && attempts > 0) {\n const text = sibling.textContent?.trim();\n if (text) {\n return direction === \"before\" ? text.slice(-32) : text.slice(0, 32);\n }\n sibling = sibling[prop];\n attempts--;\n }\n\n return \"\";\n}\n\n/** Collect text from immediate siblings for disambiguation context. */\nexport function neighborText(element: Element): string {\n const prev = element.previousElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n const next = element.nextElementSibling?.textContent?.trim().slice(0, 40) ?? \"\";\n return [prev, next].filter(Boolean).join(\" | \");\n}\n","/**\n * Generate an optimized XPath for a DOM element.\n *\n * Strategy:\n * - If the element has a unique id → //tag[@id='value']\n * - Otherwise, walk up the tree building /tag[position] segments\n * until we hit an ancestor with an id or reach <body>\n * - Cap depth at 6 levels to keep paths short\n */\nexport function generateXPath(element: Element): string {\n if (element.id) {\n const safeId = element.id.includes(\"'\") ? `concat('${element.id.replace(/'/g, \"',\\\"'\\\",'\")}')` : `'${element.id}'`;\n return `//${element.localName}[@id=${safeId}]`;\n }\n\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.body && segments.length < 6) {\n const tag = current.localName;\n const parent: Element | null = current.parentElement;\n\n if (current.id) {\n const safeId = current.id.includes(\"'\")\n ? `concat('${current.id.replace(/'/g, \"',\\\"'\\\",'\")}')`\n : `'${current.id}'`;\n segments.unshift(`/${tag}[@id=${safeId}]`);\n return \"/\" + segments.join(\"\");\n }\n\n // Compute position among same-tag siblings\n let position = 1;\n if (parent) {\n for (const sibling of parent.children) {\n if (sibling === current) break;\n if (sibling.localName === tag) position++;\n }\n }\n\n segments.unshift(`/${tag}[${position}]`);\n current = parent;\n }\n\n return \"/html/body\" + segments.join(\"\");\n}\n","import { finder } from \"@medv/finder\";\nimport type { AnchorData, RectData } from \"@siteping/core\";\nimport { generateFingerprint } from \"./fingerprint.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\nimport { generateXPath } from \"./xpath.js\";\n\n/** HTML attribute hosts use to mark stable semantic anchors. */\nexport const ANCHOR_KEY_ATTR = \"data-feedback-anchor\";\n\n/**\n * Generate a multi-selector anchor for a DOM element.\n *\n * Resolution priority (used by `resolveAnchor`):\n * 1. Semantic anchor (`data-feedback-anchor` on closest ancestor) — hosts opt\n * into stable, narrow anchors that survive viewport changes and refactors\n * 2. Element id\n * 3. CSS selector via @medv/finder\n * 4. XPath\n * 5. Smart scan (fingerprint + text + prefix/suffix + neighbor)\n */\nexport function generateAnchor(element: Element): AnchorData {\n const cssSelector = finder(element, {\n // Filter out CSS-in-JS hashed class names\n className: (name: string) => !/^(css|sc|emotion|styled)-/.test(name) && !/^[a-z]{1,3}[A-Za-z0-9]{4,8}$/.test(name),\n // Prefer stable attributes\n attr: (name: string) => [\"data-testid\", \"data-id\", \"role\", \"aria-label\"].includes(name),\n // Exclude framework-generated dynamic IDs\n idName: (name: string) => !name.startsWith(\"radix-\") && !/^:r[0-9]+:$/.test(name),\n seedMinLength: 3,\n optimizedMinLength: 2,\n });\n\n const xpath = generateXPath(element);\n\n const rawText = element.textContent?.trim() ?? \"\";\n const textSnippet = rawText.slice(0, 120);\n\n const textPrefix = adjacentText(element, \"before\");\n const textSuffix = adjacentText(element, \"after\");\n const fingerprint = generateFingerprint(element);\n const neighbor = neighborText(element);\n\n const semanticAncestor = element.closest(`[${ANCHOR_KEY_ATTR}]`);\n const anchorKey = semanticAncestor?.getAttribute(ANCHOR_KEY_ATTR) ?? null;\n\n return {\n cssSelector,\n xpath,\n textSnippet,\n textPrefix,\n textSuffix,\n fingerprint,\n neighborText: neighbor,\n elementTag: element.tagName,\n elementId: element.id || undefined,\n anchorKey,\n };\n}\n\n/** Whether `el`'s bounding box fully contains `rect`. */\nfunction containsRect(el: Element, rect: DOMRect): boolean {\n const b = el.getBoundingClientRect();\n return b.left <= rect.x && b.top <= rect.y && b.right >= rect.x + rect.width && b.bottom >= rect.y + rect.height;\n}\n\n/**\n * Find the best DOM element to use as the rect's anchor.\n *\n * Priority:\n * 1. Closest ancestor with `data-feedback-anchor` whose bounds contain the rect —\n * semantic anchors are typically narrow section roots, so anchoring against\n * them keeps the percentage-based rect stable across viewport changes\n * instead of stretching to the width of `<main>` or `<body>`.\n * 2. Smallest ancestor that contains the rect (legacy behavior).\n * 3. `document.body` fallback — keeps percentages in [0, 1].\n */\nexport function findAnchorElement(rect: DOMRect, root: Element = document.documentElement): Element {\n const centerX = rect.x + rect.width / 2;\n const centerY = rect.y + rect.height / 2;\n\n const elementAtCenter = document.elementFromPoint(centerX, centerY);\n if (!elementAtCenter || elementAtCenter === root) return document.body;\n\n // Pass 1 — semantic anchor (host-controlled, most stable)\n let current: Element | null = elementAtCenter;\n while (current && current !== document.body) {\n if (current.hasAttribute(ANCHOR_KEY_ATTR) && containsRect(current, rect)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Pass 2 — original behavior: smallest ancestor that contains the rect\n current = elementAtCenter;\n while (current && current !== document.body) {\n if (containsRect(current, rect)) return current;\n current = current.parentElement;\n }\n\n return document.body;\n}\n\n/**\n * Convert absolute rectangle coordinates to percentages\n * relative to an anchor element's bounding box.\n */\nexport function rectToPercentages(rect: DOMRect, anchorBounds: DOMRect): RectData {\n // Guard against zero-dimension anchors (collapsed/hidden elements)\n if (anchorBounds.width <= 0 || anchorBounds.height <= 0) {\n return { xPct: 0, yPct: 0, wPct: 1, hPct: 1 };\n }\n return {\n xPct: (rect.x - anchorBounds.x) / anchorBounds.width,\n yPct: (rect.y - anchorBounds.y) / anchorBounds.height,\n wPct: rect.width / anchorBounds.width,\n hPct: rect.height / anchorBounds.height,\n };\n}\n","/**\n * Safe DOM creation utilities.\n * All user content is set via textContent (never innerHTML).\n * SVG icons use a DOMParser for trusted static strings.\n */\n\n/**\n * Parse a trusted SVG string into an SVGElement.\n * Only use with hardcoded icon constants — never with user input.\n * Uses createContextualFragment for native document-context parsing\n * (DOMParser creates nodes in a foreign document that don't render in Shadow DOM).\n */\nexport function parseSvg(svgString: string): SVGSVGElement {\n const range = document.createRange();\n const fragment = range.createContextualFragment(svgString);\n const svg = fragment.firstElementChild;\n if (!svg || svg.nodeName.toLowerCase() !== \"svg\") {\n throw new Error(\"[siteping] Invalid SVG string\");\n }\n // Safety: strip any event handlers in case of accidental misuse\n for (const attr of [...svg.attributes]) {\n if (attr.name.startsWith(\"on\")) svg.removeAttribute(attr.name);\n }\n // Also strip from all descendants\n for (const el of svg.querySelectorAll(\"*\")) {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith(\"on\")) el.removeAttribute(attr.name);\n }\n }\n return svg as SVGSVGElement;\n}\n\n/** Create an element with optional class and style */\nexport function el(tag: string, attrs?: Record<string, string>): HTMLElement {\n const element = document.createElement(tag);\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (key === \"class\") {\n element.className = value;\n } else if (key === \"style\") {\n element.style.cssText = value;\n } else {\n element.setAttribute(key, value);\n }\n }\n }\n return element;\n}\n\n/** Set text content safely (no HTML injection possible) */\nexport function setText(element: HTMLElement | SVGElement, text: string): void {\n element.textContent = text;\n}\n\n/** Format a relative date string using Intl.RelativeTimeFormat for locale support */\nexport function formatRelativeDate(isoString: string, locale = \"en\"): string {\n const diff = Date.now() - new Date(isoString).getTime();\n const seconds = Math.floor(diff / 1000);\n\n if (seconds < 60) {\n return new Intl.RelativeTimeFormat(locale, { numeric: \"auto\" }).format(0, \"second\");\n }\n\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: \"always\", style: \"narrow\" });\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return rtf.format(-minutes, \"minute\");\n\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return rtf.format(-hours, \"hour\");\n\n const days = Math.floor(hours / 24);\n if (days < 7) return rtf.format(-days, \"day\");\n\n return new Date(isoString).toLocaleDateString(locale);\n}\n","/** SVG icon strings for the widget UI. Kept as template strings to avoid DOM parsing overhead. */\n\nexport const ICON_SITEPING = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/><circle cx=\"12\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"8\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"16\" cy=\"10\" r=\"1\" fill=\"currentColor\" stroke=\"none\"/></svg>`;\n\nexport const ICON_CHAT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>`;\n\nexport const ICON_ANNOTATE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><path d=\"M3 9h18\"/><path d=\"M9 3v18\"/></svg>`;\n\nexport const ICON_EYE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`;\n\nexport const ICON_EYE_OFF = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94\"/><path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19\"/><line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\"/></svg>`;\n\nexport const ICON_CLOSE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\nexport const ICON_SEARCH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><line x1=\"21\" y1=\"21\" x2=\"16.65\" y2=\"16.65\"/></svg>`;\n\nexport const ICON_CHECK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n\nexport const ICON_QUESTION = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\"/><line x1=\"12\" y1=\"17\" x2=\"12.01\" y2=\"17\"/></svg>`;\n\nexport const ICON_CHANGE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`;\n\nexport const ICON_BUG = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"8\" y=\"6\" width=\"8\" height=\"14\" rx=\"4\"/><path d=\"M19 9h2\"/><path d=\"M3 9h2\"/><path d=\"M19 13h2\"/><path d=\"M3 13h2\"/><path d=\"M19 17h2\"/><path d=\"M3 17h2\"/><path d=\"M10 2h4\"/></svg>`;\n\nexport const ICON_OTHER = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"1\"/><circle cx=\"19\" cy=\"12\" r=\"1\"/><circle cx=\"5\" cy=\"12\" r=\"1\"/></svg>`;\n\nexport const ICON_LAYERS = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polygon points=\"12 2 2 7 12 12 22 7 12 2\"/><polyline points=\"2 17 12 22 22 17\"/><polyline points=\"2 12 12 17 22 12\"/></svg>`;\n\nexport const ICON_DOT_OPEN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"3\" fill=\"currentColor\" stroke=\"none\"/></svg>`;\n\nexport const ICON_CHEVRON_DOWN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"6 9 12 15 18 9\"/></svg>`;\n\nexport const ICON_UNDO = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>`;\n\nexport const ICON_TRASH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/></svg>`;\n","/** Color palette and glassmorphism tokens derived from the accent color */\nexport interface ThemeColors {\n accent: string;\n accentLight: string;\n accentDark: string;\n accentGlow: string;\n accentGradient: string;\n bg: string;\n bgHover: string;\n text: string;\n textSecondary: string;\n textTertiary: string;\n border: string;\n shadow: string;\n // Glass tokens\n glassBg: string;\n glassBgHeavy: string;\n glassBorder: string;\n glassBorderSubtle: string;\n // Feedback type colors\n typeQuestion: string;\n typeChange: string;\n typeBug: string;\n typeOther: string;\n // Soft type backgrounds (pastel)\n typeQuestionBg: string;\n typeChangeBg: string;\n typeBugBg: string;\n typeOtherBg: string;\n // Status filter colors\n statusOpen: string;\n statusOpenBg: string;\n statusResolved: string;\n statusResolvedBg: string;\n}\n\nconst DEFAULT_ACCENT = \"#0066ff\";\nconst HEX6_RE = /^#[0-9a-fA-F]{6}$/;\nconst HEX3_RE = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/;\nconst HEX8_RE = /^#[0-9a-fA-F]{8}$/;\n\n/**\n * Normalize an accent color to a 6-digit hex string.\n *\n * **Only hex formats are accepted:**\n * - `#RGB` (3-digit shorthand, expanded to 6-digit)\n * - `#RRGGBB` (standard 6-digit)\n * - `#RRGGBBAA` (8-digit with alpha, alpha is stripped)\n *\n * Any other CSS color format (named colors like `\"red\"`, `hsl()`, `rgb()`,\n * `oklch()`, etc.) is **not** supported and will fall back to the default\n * accent color with a console warning.\n */\nfunction normalizeHex(raw: string): string {\n if (HEX6_RE.test(raw)) return raw;\n const short = HEX3_RE.test(raw) ? raw.match(HEX3_RE) : null;\n if (short) return `#${short[1]}${short[1]}${short[2]}${short[2]}${short[3]}${short[3]}`;\n if (HEX8_RE.test(raw)) return raw.slice(0, 7);\n\n console.warn(\n `[siteping] Invalid accentColor \"${raw}\" — only hex colors (#RGB, #RRGGBB, #RRGGBBAA) are supported. Using default.`,\n );\n return DEFAULT_ACCENT;\n}\n\n/** Darken a hex color by a percentage (0-1) */\nfunction darkenHex(hex: string, amount: number): string {\n const r = Math.max(0, Math.round(parseInt(hex.slice(1, 3), 16) * (1 - amount)));\n const g = Math.max(0, Math.round(parseInt(hex.slice(3, 5), 16) * (1 - amount)));\n const b = Math.max(0, Math.round(parseInt(hex.slice(5, 7), 16) * (1 - amount)));\n return `#${r.toString(16).padStart(2, \"0\")}${g.toString(16).padStart(2, \"0\")}${b.toString(16).padStart(2, \"0\")}`;\n}\n\n/** Detect if user prefers dark mode via media query */\nfunction prefersDark(): boolean {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\n/** Resolve 'auto' theme to 'light' or 'dark' based on system preference */\nexport function resolveTheme(theme?: \"light\" | \"dark\" | \"auto\"): \"light\" | \"dark\" {\n if (theme === \"dark\") return \"dark\";\n if (theme === \"auto\") return prefersDark() ? \"dark\" : \"light\";\n return \"light\";\n}\n\nexport function buildThemeColors(accent: string = DEFAULT_ACCENT, theme?: \"light\" | \"dark\" | \"auto\"): ThemeColors {\n const hex = normalizeHex(accent);\n const dark = darkenHex(hex, 0.15);\n const resolved = resolveTheme(theme);\n\n if (resolved === \"dark\") {\n return {\n accent: hex,\n accentLight: hex + \"22\", // slightly more visible on dark bg\n accentDark: dark,\n accentGlow: hex + \"44\",\n accentGradient: `linear-gradient(135deg, ${hex}, ${dark})`,\n bg: \"#0f172a\",\n bgHover: \"#1e293b\",\n text: \"#f1f5f9\",\n textSecondary: \"#94a3b8\",\n textTertiary: \"#64748b\",\n border: \"#334155\",\n shadow: \"rgba(0, 0, 0, 0.3)\",\n // Glass tokens — dark frosted glass\n glassBg: \"rgba(15, 23, 42, 0.78)\",\n glassBgHeavy: \"rgba(15, 23, 42, 0.88)\",\n glassBorder: \"rgba(51, 65, 85, 0.5)\",\n glassBorderSubtle: \"rgba(51, 65, 85, 0.3)\",\n // Type colors stay vibrant on dark\n typeQuestion: \"#60a5fa\",\n typeChange: \"#fbbf24\",\n typeBug: \"#f87171\",\n typeOther: \"#94a3b8\",\n // Dark pastel backgrounds\n typeQuestionBg: \"rgba(59, 130, 246, 0.15)\",\n typeChangeBg: \"rgba(245, 158, 11, 0.15)\",\n typeBugBg: \"rgba(239, 68, 68, 0.15)\",\n typeOtherBg: \"rgba(100, 116, 139, 0.15)\",\n // Status colors — vivid green / cool gray on dark\n statusOpen: \"#4ade80\",\n statusOpenBg: \"rgba(74, 222, 128, 0.15)\",\n statusResolved: \"#94a3b8\",\n statusResolvedBg: \"rgba(148, 163, 184, 0.15)\",\n };\n }\n\n return {\n accent: hex,\n accentLight: hex + \"14\", // 8% opacity\n accentDark: dark,\n accentGlow: hex + \"33\", // 20% opacity\n accentGradient: `linear-gradient(135deg, ${hex}, ${dark})`,\n bg: \"#ffffff\",\n bgHover: \"#f8f9fb\",\n text: \"#0f172a\",\n textSecondary: \"#475569\",\n textTertiary: \"#64748b\",\n border: \"#e2e8f0\",\n shadow: \"rgba(0, 0, 0, 0.06)\",\n // Glass tokens\n glassBg: \"rgba(255, 255, 255, 0.72)\",\n glassBgHeavy: \"rgba(255, 255, 255, 0.85)\",\n glassBorder: \"rgba(255, 255, 255, 0.35)\",\n glassBorderSubtle: \"rgba(255, 255, 255, 0.18)\",\n // Vibrant type colors\n typeQuestion: \"#3b82f6\",\n typeChange: \"#b45309\",\n typeBug: \"#ef4444\",\n typeOther: \"#64748b\",\n // Pastel backgrounds\n typeQuestionBg: \"#eff6ff\",\n typeChangeBg: \"#fffbeb\",\n typeBugBg: \"#fef2f2\",\n typeOtherBg: \"#f8fafc\",\n // Status colors — saturated green / cool gray on light\n statusOpen: \"#16a34a\",\n statusOpenBg: \"#f0fdf4\",\n statusResolved: \"#64748b\",\n statusResolvedBg: \"#f1f5f9\",\n };\n}\n\nexport function getTypeColor(type: string, colors: ThemeColors): string {\n switch (type) {\n case \"question\":\n return colors.typeQuestion;\n case \"change\":\n return colors.typeChange;\n case \"bug\":\n return colors.typeBug;\n default:\n return colors.typeOther;\n }\n}\n\nexport function getTypeBgColor(type: string, colors: ThemeColors): string {\n switch (type) {\n case \"question\":\n return colors.typeQuestionBg;\n case \"change\":\n return colors.typeChangeBg;\n case \"bug\":\n return colors.typeBugBg;\n default:\n return colors.typeOtherBg;\n }\n}\n\nexport function cssVariables(colors: ThemeColors): string {\n return `\n --sp-accent: ${colors.accent};\n --sp-accent-light: ${colors.accentLight};\n --sp-accent-dark: ${colors.accentDark};\n --sp-accent-glow: ${colors.accentGlow};\n --sp-accent-gradient: ${colors.accentGradient};\n --sp-bg: ${colors.bg};\n --sp-bg-hover: ${colors.bgHover};\n --sp-text: ${colors.text};\n --sp-text-secondary: ${colors.textSecondary};\n --sp-text-tertiary: ${colors.textTertiary};\n --sp-border: ${colors.border};\n --sp-shadow: ${colors.shadow};\n --sp-glass-bg: ${colors.glassBg};\n --sp-glass-bg-heavy: ${colors.glassBgHeavy};\n --sp-glass-border: ${colors.glassBorder};\n --sp-glass-border-subtle: ${colors.glassBorderSubtle};\n --sp-type-question: ${colors.typeQuestion};\n --sp-type-change: ${colors.typeChange};\n --sp-type-bug: ${colors.typeBug};\n --sp-type-other: ${colors.typeOther};\n --sp-type-question-bg: ${colors.typeQuestionBg};\n --sp-type-change-bg: ${colors.typeChangeBg};\n --sp-type-bug-bg: ${colors.typeBugBg};\n --sp-type-other-bg: ${colors.typeOtherBg};\n --sp-radius: 12px;\n --sp-radius-lg: 16px;\n --sp-radius-xl: 20px;\n --sp-radius-full: 9999px;\n --sp-blur: 20px;\n --sp-blur-heavy: 32px;\n --sp-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);\n --sp-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.04);\n --sp-shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.04);\n --sp-shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.04);\n --sp-shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.12), 0 8px 16px rgba(0, 0, 0, 0.06);\n --sp-font: \"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n `;\n}\n","import type { FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { ICON_BUG, ICON_CHANGE, ICON_OTHER, ICON_QUESTION } from \"./icons.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\ninterface PopupResult {\n type: FeedbackType;\n message: string;\n}\n\ninterface TypeOption {\n type: FeedbackType;\n label: string;\n icon: string;\n}\n\n/**\n * Popup form shown after drawing an annotation rectangle.\n *\n * Glassmorphism design: frosted glass background, soft shadows,\n * pill-shaped type buttons, gradient submit button.\n * Lives outside Shadow DOM.\n */\nexport class Popup {\n private root: HTMLElement;\n private selectedType: FeedbackType | null = null;\n private textarea: HTMLTextAreaElement;\n private submitBtn: HTMLButtonElement;\n private resolve: ((result: PopupResult | null) => void) | null = null;\n private previouslyFocused: HTMLElement | null = null;\n private onKeydownTrap: ((e: KeyboardEvent) => void) | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly t: TFunction,\n ) {\n this.root = el(\"div\", {\n style: `\n position:fixed;\n z-index:${Z_INDEX_MAX};\n width:300px;\n padding:16px;\n border-radius:16px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border:1px solid ${this.colors.glassBorder};\n box-shadow:0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n opacity:0;\n transform:translateY(8px) scale(0.98);\n transition:opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n display:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"dialog\");\n this.root.setAttribute(\"aria-modal\", \"true\");\n this.root.setAttribute(\"aria-label\", this.t(\"popup.ariaLabel\"));\n\n // Type selector grid (2x2)\n const typeOptions: TypeOption[] = [\n { type: \"question\", label: this.t(\"type.question\"), icon: ICON_QUESTION },\n { type: \"change\", label: this.t(\"type.change\"), icon: ICON_CHANGE },\n { type: \"bug\", label: this.t(\"type.bug\"), icon: ICON_BUG },\n { type: \"other\", label: this.t(\"type.other\"), icon: ICON_OTHER },\n ];\n const typeRow = el(\"div\", { style: \"display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:12px;\" });\n for (const option of typeOptions) {\n const btn = document.createElement(\"button\");\n btn.style.cssText = `\n height:44px;\n border-radius:9999px;border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};cursor:pointer;\n display:flex;align-items:center;justify-content:center;gap:5px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;color:${this.colors.textTertiary};\n transition:all 0.2s ease;\n padding:0 12px;\n `;\n const icon = parseSvg(option.icon);\n icon.setAttribute(\"style\", \"width:13px;height:13px;flex-shrink:0;\");\n btn.appendChild(icon);\n const labelSpan = document.createElement(\"span\");\n setText(labelSpan, option.label);\n btn.appendChild(labelSpan);\n btn.dataset.type = option.type;\n btn.setAttribute(\"aria-pressed\", \"false\");\n\n btn.addEventListener(\"click\", () => {\n this.selectType(option.type, typeRow);\n });\n\n btn.addEventListener(\"mouseenter\", () => {\n if (btn.dataset.type !== this.selectedType) {\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = bgColor;\n btn.style.borderColor = getTypeColor(btn.dataset.type ?? \"\", this.colors) + \"40\";\n }\n });\n\n btn.addEventListener(\"mouseleave\", () => {\n if (btn.dataset.type !== this.selectedType) {\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n }\n });\n\n typeRow.appendChild(btn);\n }\n\n // Textarea\n this.textarea = document.createElement(\"textarea\");\n this.textarea.style.cssText = `\n width:100%;min-height:72px;max-height:152px;\n padding:10px 12px;border-radius:12px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBgHeavy};\n color:${this.colors.text};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;line-height:1.5;resize:vertical;\n outline:none;transition:all 0.2s ease;\n box-sizing:border-box;\n `;\n this.textarea.placeholder = this.t(\"popup.placeholder\");\n this.textarea.maxLength = 5000;\n this.textarea.setAttribute(\"aria-label\", this.t(\"popup.textareaAria\"));\n\n // Keyboard shortcut hint\n const hint = el(\"div\", {\n style: `\n font-size:11px;color:${this.colors.textTertiary};\n text-align:right;margin-top:4px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n letter-spacing:0.01em;\n `,\n });\n // navigator.userAgentData is preferred; navigator.platform is deprecated\n // but still needed as fallback. If both are unavailable, fall back to user agent string parsing.\n const uaData = (navigator as Navigator & { userAgentData?: { platform?: string } }).userAgentData;\n const isMac = uaData\n ? uaData.platform === \"macOS\"\n : (navigator.platform?.includes(\"Mac\") ?? /Macintosh|Mac OS X/i.test(navigator.userAgent));\n setText(hint, isMac ? this.t(\"popup.submitHintMac\") : this.t(\"popup.submitHintOther\"));\n\n this.textarea.addEventListener(\"focus\", () => {\n this.textarea.style.borderColor = this.colors.accent;\n this.textarea.style.boxShadow = `0 0 0 3px ${this.colors.accent}14`;\n this.textarea.style.background = this.colors.bg;\n });\n this.textarea.addEventListener(\"blur\", () => {\n this.textarea.style.borderColor = this.colors.border;\n this.textarea.style.boxShadow = \"none\";\n this.textarea.style.background = this.colors.glassBgHeavy;\n });\n this.textarea.addEventListener(\"input\", () => {\n this.updateSubmitState();\n });\n this.textarea.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && (e.ctrlKey || e.metaKey)) {\n e.preventDefault();\n this.submit();\n }\n if (e.key === \"Escape\") {\n this.cancel();\n }\n });\n\n // Button row\n const btnRow = el(\"div\", { style: \"display:flex;justify-content:flex-end;gap:8px;margin-top:12px;\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 16px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"popup.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.cancel());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.accent;\n cancelBtn.style.color = this.colors.accent;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n });\n\n this.submitBtn = document.createElement(\"button\");\n this.submitBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:none;background:${this.colors.accentGradient};\n color:#fff;font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:600;cursor:pointer;\n opacity:0.35;pointer-events:none;\n transition:all 0.2s ease;\n box-shadow:0 2px 8px ${this.colors.accentGlow};\n `;\n setText(this.submitBtn, this.t(\"popup.submit\"));\n this.submitBtn.addEventListener(\"click\", () => this.submit());\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(this.submitBtn);\n\n this.root.appendChild(typeRow);\n this.root.appendChild(this.textarea);\n this.root.appendChild(hint);\n this.root.appendChild(btnRow);\n document.body.appendChild(this.root);\n }\n\n /**\n * Show the popup near a drawn rectangle and return the user's input.\n * Returns null if cancelled.\n */\n show(rectBounds: DOMRect): Promise<PopupResult | null> {\n return new Promise((resolve) => {\n this.resolve = resolve;\n this.selectedType = null;\n this.textarea.value = \"\";\n this.updateSubmitState();\n this.resetTypeButtons();\n\n // Save focus to restore on close\n this.previouslyFocused = document.activeElement as HTMLElement | null;\n\n // Position: bottom-left of rect, 8px below\n const popupH = 220;\n const popupW = 300;\n let top = rectBounds.bottom + 8;\n let left = rectBounds.left;\n\n // Vertical: prefer below; fall back to above; otherwise clamp inside viewport\n if (top + popupH > window.innerHeight) {\n const aboveTop = rectBounds.top - popupH - 8;\n if (aboveTop >= 8) {\n top = aboveTop;\n } else {\n // Rect is taller than the viewport allows on either side —\n // clamp to keep the popup fully visible.\n top = window.innerHeight - popupH - 8;\n }\n }\n // Collision: flip right if not enough space on left\n if (left + popupW > window.innerWidth) {\n left = rectBounds.right - popupW;\n }\n left = Math.max(8, left);\n top = Math.max(8, top);\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n this.root.style.display = \"block\";\n\n // Install focus trap\n this.onKeydownTrap = (e: KeyboardEvent) => {\n if (e.key === \"Tab\") {\n const focusableEls = Array.from(\n this.root.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), textarea, input, [tabindex]:not([tabindex=\"-1\"])',\n ),\n );\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n if (e.shiftKey) {\n if (document.activeElement === first || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (document.activeElement === last || !this.root.contains(document.activeElement)) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n };\n this.root.addEventListener(\"keydown\", this.onKeydownTrap);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n // Trigger animation\n requestAnimationFrame(() => {\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n this.textarea.focus();\n });\n });\n }\n\n private selectType(type: FeedbackType, container: HTMLElement): void {\n this.selectedType = type;\n const buttons = container.querySelectorAll<HTMLButtonElement>(\"button\");\n for (const btn of buttons) {\n const isActive = btn.dataset.type === type;\n const color = getTypeColor(btn.dataset.type ?? \"\", this.colors);\n const bgColor = getTypeBgColor(btn.dataset.type ?? \"\", this.colors);\n btn.style.background = isActive ? bgColor : this.colors.glassBg;\n btn.style.borderColor = isActive ? color + \"60\" : this.colors.border;\n btn.style.color = isActive ? color : this.colors.textTertiary;\n btn.style.fontWeight = isActive ? \"600\" : \"500\";\n btn.setAttribute(\"aria-pressed\", String(isActive));\n }\n this.updateSubmitState();\n }\n\n private resetTypeButtons(): void {\n const buttons = this.root.querySelectorAll<HTMLButtonElement>(\"button[data-type]\");\n for (const btn of buttons) {\n btn.setAttribute(\"aria-pressed\", \"false\");\n btn.style.background = this.colors.glassBg;\n btn.style.borderColor = this.colors.border;\n btn.style.color = this.colors.textTertiary;\n btn.style.fontWeight = \"500\";\n }\n }\n\n private updateSubmitState(): void {\n const enabled = this.selectedType !== null && this.textarea.value.trim().length > 0;\n this.submitBtn.disabled = !enabled;\n this.submitBtn.style.opacity = enabled ? \"1\" : \"0.35\";\n this.submitBtn.style.pointerEvents = enabled ? \"auto\" : \"none\";\n }\n\n private submit(): void {\n if (!this.selectedType || !this.textarea.value.trim()) return;\n this.resolve?.({ type: this.selectedType, message: this.textarea.value.trim() });\n this.resolve = null;\n this.hideElement();\n }\n\n private cancel(): void {\n this.resolve?.(null);\n this.resolve = null;\n this.hideElement();\n }\n\n private hideElement(): void {\n // Remove focus trap\n if (this.onKeydownTrap) {\n this.root.removeEventListener(\"keydown\", this.onKeydownTrap);\n this.onKeydownTrap = null;\n }\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(8px) scale(0.98)\";\n // Restore focus to the previously focused element\n this.previouslyFocused?.focus();\n this.previouslyFocused = null;\n setTimeout(() => {\n this.root.style.display = \"none\";\n }, 250);\n }\n\n destroy(): void {\n this.root.remove();\n }\n}\n","/**\n * Screenshot capture via html2canvas.\n *\n * `html2canvas` is a regular `dependency` of `@siteping/widget` — every\n * install gets it. We dynamic-import it so bundlers emit a separate chunk\n * loaded only when `enableScreenshot: true` triggers the first capture;\n * hosts that never enable screenshots pay only the disk-space cost.\n *\n * On capture failure (content-tainted canvas, version mismatch, missing 2D\n * context) we return `null` rather than throwing — the feedback is still\n * submitted, just without an image.\n */\n\ntype Html2CanvasFn = (element: HTMLElement, options?: Html2CanvasOptions) => Promise<HTMLCanvasElement>;\n\ninterface Html2CanvasOptions {\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n useCORS?: boolean;\n allowTaint?: boolean;\n logging?: boolean;\n ignoreElements?: (element: Element) => boolean;\n}\n\nlet cachedHtml2Canvas: Html2CanvasFn | null | undefined; // undefined = not loaded yet, null = failed\nlet warnedAboutMissingDep = false;\n\nasync function loadHtml2Canvas(): Promise<Html2CanvasFn | null> {\n if (cachedHtml2Canvas !== undefined) return cachedHtml2Canvas;\n try {\n // Static dynamic import — bundlers (Vite, webpack, esbuild) resolve this\n // at build time and emit a separate chunk loaded only on first capture.\n // html2canvas ships as a regular dependency so this resolves on every\n // install. Earlier attempts to dodge static resolution via magic comments\n // silently broke production: bare specifiers can't be resolved at runtime\n // in browsers without import maps.\n const mod = (await import(\"html2canvas\")) as { default?: Html2CanvasFn } & Html2CanvasFn;\n cachedHtml2Canvas = (mod.default ?? mod) as Html2CanvasFn;\n return cachedHtml2Canvas;\n } catch (err) {\n cachedHtml2Canvas = null;\n if (!warnedAboutMissingDep) {\n warnedAboutMissingDep = true;\n console.warn(\n \"[siteping] html2canvas import failed unexpectedly. Capture is disabled for this session — feedbacks are still submitted, just without screenshots. Underlying error:\",\n err,\n );\n }\n return null;\n }\n}\n\nexport interface CaptureOptions {\n /** JPEG quality 0..1 (default 0.85). */\n quality?: number;\n /** Max output width in CSS pixels (default 1200). Wider canvases are downscaled. */\n maxWidth?: number;\n}\n\n/**\n * Capture the page region within `rect` as a JPEG data URL. Returns `null`\n * on any failure — callers should not abort feedback submission.\n *\n * - Excludes Siteping's own overlay elements via `ignoreElements`\n * - Honors devicePixelRatio for crisp captures, then downscales to `maxWidth`\n * - JPEG at `quality` (0.85 = ~50–150 KB for a typical annotated area)\n */\nexport async function captureScreenshot(rect: DOMRect, options?: CaptureOptions): Promise<string | null> {\n const html2canvas = await loadHtml2Canvas();\n if (!html2canvas) return null;\n\n const quality = options?.quality ?? 0.85;\n const maxWidth = options?.maxWidth ?? 1200;\n\n try {\n const canvas = await html2canvas(document.body, {\n x: window.scrollX + rect.x,\n y: window.scrollY + rect.y,\n width: rect.width,\n height: rect.height,\n scale: window.devicePixelRatio,\n useCORS: true,\n allowTaint: true,\n logging: false,\n ignoreElements: (element: Element) => {\n return (\n element.tagName === \"SITEPING-WIDGET\" ||\n element.closest?.(\"siteping-widget\") !== null ||\n element.getAttribute?.(\"data-siteping-ignore\") === \"true\"\n );\n },\n });\n\n if (canvas.width <= maxWidth) {\n return canvas.toDataURL(\"image/jpeg\", quality);\n }\n\n // Downscale via an off-DOM canvas — keeps payload reasonable on\n // hi-DPI displays where the raw capture can be 2x–3x intended size.\n const ratio = maxWidth / canvas.width;\n const targetW = maxWidth;\n const targetH = Math.round(canvas.height * ratio);\n\n const scaled = document.createElement(\"canvas\");\n scaled.width = targetW;\n scaled.height = targetH;\n const ctx = scaled.getContext(\"2d\");\n if (!ctx) return null;\n ctx.drawImage(canvas, 0, 0, targetW, targetH);\n return scaled.toDataURL(\"image/jpeg\", quality);\n } catch (err) {\n console.warn(\"[siteping] Screenshot capture failed:\", err);\n return null;\n }\n}\n\n/** @internal — exposed for tests. Resets the dynamic-import cache. */\nexport function _resetScreenshotCacheForTests(): void {\n cachedHtml2Canvas = undefined;\n warnedAboutMissingDep = false;\n}\n","import type { AnnotationPayload, FeedbackType } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { findAnchorElement, generateAnchor, rectToPercentages } from \"./dom/anchor.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { Popup } from \"./popup.js\";\nimport { captureScreenshot } from \"./screenshot.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\nexport interface AnnotationComplete {\n annotation: AnnotationPayload;\n type: FeedbackType;\n message: string;\n /**\n * Base64 JPEG `data:` URL captured by html2canvas, or null when capture\n * is disabled / failed / the peer dep is missing.\n */\n screenshotDataUrl?: string | null | undefined;\n}\n\n/**\n * Annotation mode: full-page overlay with rectangle drawing.\n *\n * Glassmorphism design:\n * - Frosted glass toolbar at top\n * - Subtle tinted overlay\n * - Accent-colored drawing rectangle with glow\n */\nexport class Annotator {\n private overlay: HTMLElement | null = null;\n private toolbar: HTMLElement | null = null;\n private drawingRect: HTMLElement | null = null;\n private startX = 0;\n private startY = 0;\n private isDrawing = false;\n private isActive = false;\n private popup: Popup;\n private savedOverflow = \"\";\n private preActiveFocusElement: Element | null = null;\n private rafId: number | null = null;\n private pendingMoveEvent: MouseEvent | Touch | null = null;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n private readonly enableScreenshot: boolean = false,\n ) {\n this.popup = new Popup(colors, t);\n\n this.bus.on(\"annotation:start\", () => this.activate());\n }\n\n /**\n * Capture a screenshot of the drawn rect when `enableScreenshot` is on.\n * Returns null on disable / capture failure / missing peer dep — the\n * feedback is always submitted regardless.\n */\n private async maybeCapture(rect: DOMRect): Promise<string | null> {\n if (!this.enableScreenshot) return null;\n return captureScreenshot(rect);\n }\n\n private activate(): void {\n if (this.isActive) return;\n this.isActive = true;\n\n // Capture the focused element before activation for keyboard annotation\n this.preActiveFocusElement = document.activeElement;\n\n // Lock page scroll\n this.savedOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n\n // Overlay — subtle blue tint for depth\n this.overlay = el(\"div\", {\n style: `\n position:fixed;inset:0;\n z-index:${Z_INDEX_MAX - 1};\n background:rgba(15, 23, 42, 0.04);\n cursor:crosshair;\n `,\n });\n this.overlay.setAttribute(\"aria-hidden\", \"true\");\n\n // Toolbar — glassmorphism bar\n this.toolbar = el(\"div\", {\n style: `\n position:fixed;top:0;left:0;right:0;\n z-index:${Z_INDEX_MAX};\n height:52px;\n background:${this.colors.glassBg};\n backdrop-filter:blur(24px);\n -webkit-backdrop-filter:blur(24px);\n border-bottom:1px solid ${this.colors.glassBorder};\n display:flex;align-items:center;justify-content:center;gap:16px;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:14px;color:${this.colors.text};\n box-shadow:0 4px 16px ${this.colors.shadow};\n -webkit-font-smoothing:antialiased;\n `,\n });\n\n const dot = el(\"span\", {\n style: `\n width:8px;height:8px;border-radius:50%;\n background:${this.colors.accent};\n box-shadow:0 0 8px ${this.colors.accentGlow};\n animation:pulse 1.5s ease-in-out infinite;\n `,\n });\n\n // Add pulse animation inline (respects prefers-reduced-motion)\n const style = document.createElement(\"style\");\n style.textContent = [\n \"@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.4}}\",\n \"@media(prefers-reduced-motion:reduce){@keyframes pulse{from,to{opacity:1}}}\",\n ].join(\"\");\n this.toolbar.appendChild(style);\n\n const instruction = el(\"span\", { style: \"font-weight:500;letter-spacing:-0.01em;\" });\n setText(instruction, this.t(\"annotator.instruction\"));\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.style.cssText = `\n height:34px;padding:0 18px;border-radius:9999px;\n border:1px solid ${this.colors.border};\n background:${this.colors.glassBg};\n color:${this.colors.textTertiary};font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:13px;font-weight:500;cursor:pointer;\n transition:all 0.2s ease;\n `;\n setText(cancelBtn, this.t(\"annotator.cancel\"));\n cancelBtn.addEventListener(\"click\", () => this.deactivate());\n cancelBtn.addEventListener(\"mouseenter\", () => {\n cancelBtn.style.borderColor = this.colors.typeBug;\n cancelBtn.style.color = this.colors.typeBug;\n cancelBtn.style.background = this.colors.typeBugBg;\n });\n cancelBtn.addEventListener(\"mouseleave\", () => {\n cancelBtn.style.borderColor = this.colors.border;\n cancelBtn.style.color = this.colors.textTertiary;\n cancelBtn.style.background = this.colors.glassBg;\n });\n\n this.toolbar.appendChild(dot);\n this.toolbar.appendChild(instruction);\n this.toolbar.appendChild(cancelBtn);\n\n // Mouse events\n this.overlay.addEventListener(\"mousedown\", this.onMouseDown);\n this.overlay.addEventListener(\"mousemove\", this.onMouseMove);\n this.overlay.addEventListener(\"mouseup\", this.onMouseUp);\n\n // Touch events (Surface Pro, iPad, etc.)\n this.overlay.addEventListener(\"touchstart\", this.onTouchStart, { passive: false });\n this.overlay.addEventListener(\"touchmove\", this.onTouchMove, { passive: false });\n this.overlay.addEventListener(\"touchend\", this.onTouchEnd);\n\n // Keyboard annotation: Enter selects the pre-activation focused element\n this.overlay.addEventListener(\"keydown\", this.onOverlayKeyDown);\n\n // Allow tab-through so keyboard users can reach underlying elements\n this.overlay.setAttribute(\"tabindex\", \"0\");\n\n // Escape to cancel\n document.addEventListener(\"keydown\", this.onKeyDown);\n\n document.body.appendChild(this.overlay);\n document.body.appendChild(this.toolbar);\n }\n\n private deactivate(): void {\n if (!this.isActive) return;\n this.isActive = false;\n this.isDrawing = false;\n this.preActiveFocusElement = null;\n\n // Cancel any pending rAF to prevent stale callbacks\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.pendingMoveEvent = null;\n\n document.body.style.overflow = this.savedOverflow;\n document.removeEventListener(\"keydown\", this.onKeyDown);\n\n this.overlay?.remove();\n this.toolbar?.remove();\n this.drawingRect?.remove();\n this.overlay = null;\n this.toolbar = null;\n this.drawingRect = null;\n\n this.bus.emit(\"annotation:end\");\n }\n\n private onKeyDown = (e: KeyboardEvent): void => {\n if (e.key === \"Escape\") this.deactivate();\n };\n\n /**\n * Keyboard annotation: pressing Enter while the overlay is active selects\n * the element that was focused before activation and creates a full-bounds\n * annotation covering that element (WCAG 2.1.1 Level A).\n */\n private onOverlayKeyDown = async (e: KeyboardEvent): Promise<void> => {\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n\n const target = this.preActiveFocusElement;\n if (!target || !(target instanceof HTMLElement)) return;\n\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return;\n\n const rectBounds = new DOMRect(bounds.x, bounds.y, bounds.width, bounds.height);\n\n const result = await this.popup.show(rectBounds);\n if (!result) return;\n\n const anchor = generateAnchor(target);\n const annotation: AnnotationPayload = {\n anchor,\n rect: { xPct: 0, yPct: 0, wPct: 1, hPct: 1 },\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n\n // Capture before deactivate — overlay is intentionally ignored by the\n // capture predicate but the rect must still be on the page.\n const screenshotDataUrl = await this.maybeCapture(rectBounds);\n\n this.deactivate();\n\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: result.type,\n message: result.message,\n screenshotDataUrl,\n });\n };\n\n private onMouseDown = (e: MouseEvent): void => {\n this.startDrawing(e.clientX, e.clientY);\n };\n\n private onTouchStart = (e: TouchEvent): void => {\n e.preventDefault();\n const touch = e.touches[0];\n if (touch) this.startDrawing(touch.clientX, touch.clientY);\n };\n\n private startDrawing(clientX: number, clientY: number): void {\n this.isDrawing = true;\n this.startX = clientX;\n this.startY = clientY;\n\n this.drawingRect?.remove();\n this.drawingRect = el(\"div\", {\n style: `\n position:fixed;\n border:2px solid ${this.colors.accent};\n background:${this.colors.accent}12;\n pointer-events:none;\n border-radius:8px;\n box-shadow:0 0 16px ${this.colors.accentGlow};\n transition:box-shadow 0.15s ease;\n `,\n });\n this.overlay?.appendChild(this.drawingRect);\n }\n\n private onMouseMove = (e: MouseEvent): void => {\n this.scheduleRectUpdate(e);\n };\n\n private onTouchMove = (e: TouchEvent): void => {\n e.preventDefault();\n if (e.touches[0]) this.scheduleRectUpdate(e.touches[0]);\n };\n\n private scheduleRectUpdate(source: MouseEvent | Touch): void {\n if (!this.isDrawing || !this.drawingRect) return;\n\n this.pendingMoveEvent = source;\n if (this.rafId !== null) return;\n\n this.rafId = requestAnimationFrame(() => {\n this.rafId = null;\n const evt = this.pendingMoveEvent;\n if (!evt || !this.drawingRect) return;\n\n const x = Math.min(evt.clientX, this.startX);\n const y = Math.min(evt.clientY, this.startY);\n const w = Math.abs(evt.clientX - this.startX);\n const h = Math.abs(evt.clientY - this.startY);\n\n this.drawingRect.style.left = `${x}px`;\n this.drawingRect.style.top = `${y}px`;\n this.drawingRect.style.width = `${w}px`;\n this.drawingRect.style.height = `${h}px`;\n });\n }\n\n private onTouchEnd = async (e: TouchEvent): Promise<void> => {\n const touch = e.changedTouches[0];\n if (touch) await this.finishDrawing(touch.clientX, touch.clientY);\n };\n\n private onMouseUp = async (e: MouseEvent): Promise<void> => {\n await this.finishDrawing(e.clientX, e.clientY);\n };\n\n private finishDrawing = async (clientX: number, clientY: number): Promise<void> => {\n if (!this.isDrawing || !this.drawingRect) return;\n this.isDrawing = false;\n\n const x = Math.min(clientX, this.startX);\n const y = Math.min(clientY, this.startY);\n const w = Math.abs(clientX - this.startX);\n const h = Math.abs(clientY - this.startY);\n\n // Ignore tiny rectangles (accidental clicks)\n if (w < 10 || h < 10) {\n this.drawingRect.remove();\n this.drawingRect = null;\n return;\n }\n\n const rectBounds = new DOMRect(x, y, w, h);\n\n // Show popup for type + message\n const result = await this.popup.show(rectBounds);\n\n if (!result) {\n this.drawingRect?.remove();\n this.drawingRect = null;\n return;\n }\n\n // Build annotation payload BEFORE deactivating (needs overlay for elementFromPoint)\n const annotation = this.buildAnnotation(rectBounds);\n this.drawingRect?.remove();\n this.drawingRect = null;\n\n // Capture before deactivate — html2canvas walks the live DOM, and the\n // capture predicate skips siteping-widget elements so the overlay being\n // present on screen doesn't matter.\n const screenshotDataUrl = await this.maybeCapture(rectBounds);\n\n this.deactivate();\n\n // Emit via event bus (not DOM — overlay is already null after deactivate)\n this.bus.emit(\"annotation:complete\", {\n annotation,\n type: result.type,\n message: result.message,\n screenshotDataUrl,\n });\n };\n\n /**\n * Build an AnnotationPayload from a drawn rectangle.\n * Temporarily hides the overlay to access the real DOM underneath.\n */\n private buildAnnotation(rectBounds: DOMRect): AnnotationPayload {\n // Temporarily hide overlay to find the real element underneath\n if (this.overlay) this.overlay.style.pointerEvents = \"none\";\n const anchorElement = findAnchorElement(rectBounds);\n if (this.overlay) this.overlay.style.pointerEvents = \"auto\";\n\n const anchor = generateAnchor(anchorElement);\n const anchorBounds = anchorElement.getBoundingClientRect();\n const rect = rectToPercentages(rectBounds, anchorBounds);\n\n return {\n anchor,\n rect,\n scrollX: window.scrollX,\n scrollY: window.scrollY,\n viewportW: window.innerWidth,\n viewportH: window.innerHeight,\n devicePixelRatio: window.devicePixelRatio,\n };\n }\n destroy(): void {\n this.deactivate();\n this.popup.destroy();\n }\n}\n","import type { FeedbackPayload, FeedbackResponse, FeedbackStatus, FeedbackType } from \"@siteping/core\";\n\n/**\n * Abstract client interface used by the widget internals.\n *\n * `ApiClient` (HTTP mode) and `StoreClient` (direct store mode) both satisfy\n * this interface, allowing the widget to work identically in either mode.\n */\nexport interface WidgetClient {\n sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse>;\n getFeedbacks(\n projectName: string,\n options?: GetFeedbacksOptions,\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }>;\n resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse>;\n deleteFeedback(id: string): Promise<void>;\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/** Options accepted by `WidgetClient.getFeedbacks`. */\nexport interface GetFeedbacksOptions {\n page?: number;\n limit?: number;\n type?: FeedbackType;\n status?: FeedbackStatus;\n search?: string;\n /** Restrict to feedbacks created on this exact URL (path). */\n url?: string;\n /** Restrict to feedbacks created on this URL pattern (e.g. `/orders/:orderId`). */\n urlPattern?: string;\n}\n\nconst MAX_RETRIES = 3;\nconst TIMEOUT_MS = 10_000;\nconst RETRY_QUEUE_KEY = \"siteping_retry_queue\";\nconst MAX_QUEUE_SIZE = 20;\n\n// ---------------------------------------------------------------------------\n// Core fetch with retry + exponential backoff + jitter\n// ---------------------------------------------------------------------------\n\nasync function resilientFetch(url: string, init: RequestInit, retries = MAX_RETRIES): Promise<Response> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n clearTimeout(timeout);\n\n // Don't retry client errors (4xx) — only server errors (5xx)\n if (response.ok || (response.status >= 400 && response.status < 500)) {\n return response;\n }\n\n if (attempt === retries) return response;\n } catch (error) {\n clearTimeout(timeout);\n if (attempt === retries) throw error;\n }\n\n // Exponential backoff with jitter: 1s, 2s, 4s + random ±500ms\n const baseDelay = 1000 * 2 ** attempt;\n const jitter = Math.random() * 1000 - 500;\n await new Promise((r) => setTimeout(r, baseDelay + jitter));\n }\n\n throw new Error(\"Max retries exceeded\");\n}\n\n// ---------------------------------------------------------------------------\n// Retry queue — persist failed feedbacks for retry on next page load\n// ---------------------------------------------------------------------------\n\ntype RetryEntry = { endpoint: string; payload: FeedbackPayload };\n\nconst LOCK_NAME = \"siteping_retry_queue\";\n\n/**\n * Acquire a Web Lock to serialize cross-tab access to the retry queue.\n * Falls back to running the callback without locking on older browsers.\n */\nasync function withRetryLock<T>(callback: () => T | Promise<T>): Promise<T> {\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(LOCK_NAME, () => callback());\n }\n return callback();\n}\n\nfunction queueForRetry(endpoint: string, payload: FeedbackPayload): void {\n // Fire-and-forget — we don't want to block the caller on the lock\n void withRetryLock(() => {\n try {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n const parsed: unknown = raw ? JSON.parse(raw) : [];\n const queue: RetryEntry[] = Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n\n // Cap queue size to prevent unbounded localStorage growth\n if (queue.length >= MAX_QUEUE_SIZE) {\n queue.shift(); // Drop oldest entry\n }\n\n queue.push({ endpoint, payload });\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(queue));\n } catch {\n // localStorage full or unavailable — silently drop\n }\n });\n}\n\nexport async function flushRetryQueue(endpoint: string): Promise<void> {\n await withRetryLock(async () => {\n try {\n const raw = localStorage.getItem(RETRY_QUEUE_KEY);\n if (!raw) return;\n\n const parsed: unknown = JSON.parse(raw);\n const queue: RetryEntry[] = Array.isArray(parsed) ? (parsed as RetryEntry[]) : [];\n\n const toRetry = queue.filter((e) => e.endpoint === endpoint);\n if (toRetry.length === 0) return;\n\n // Process items sequentially to avoid overwhelming the server\n const failed: RetryEntry[] = [];\n for (const entry of toRetry) {\n try {\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(entry.payload),\n });\n if (!res.ok) {\n failed.push(entry);\n }\n } catch {\n failed.push(entry);\n }\n }\n\n // Rebuild queue: keep unrelated entries + failed retries\n const remaining = queue.filter((e) => e.endpoint !== endpoint).concat(failed);\n if (remaining.length > 0) {\n localStorage.setItem(RETRY_QUEUE_KEY, JSON.stringify(remaining));\n } else {\n localStorage.removeItem(RETRY_QUEUE_KEY);\n }\n } catch {\n // Ignore — localStorage may be unavailable\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// API client\n// ---------------------------------------------------------------------------\n\nexport class ApiClient {\n constructor(\n private readonly endpoint: string,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n try {\n const response = await resilientFetch(this.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"Unknown error\");\n throw new Error(`Failed to send feedback: ${response.status} ${text}`);\n }\n\n return (await response.json()) as FeedbackResponse; // Server validates via Zod\n } catch (error) {\n queueForRetry(this.endpoint, payload);\n throw error;\n }\n }\n\n async getFeedbacks(\n projectName: string,\n options?: GetFeedbacksOptions,\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }> {\n const params = new URLSearchParams({ projectName });\n if (options?.page) params.set(\"page\", String(options.page));\n if (options?.limit) params.set(\"limit\", String(options.limit));\n if (options?.type) params.set(\"type\", options.type);\n if (options?.status) params.set(\"status\", options.status);\n if (options?.search) params.set(\"search\", options.search);\n if (options?.url) params.set(\"url\", options.url);\n if (options?.urlPattern) params.set(\"urlPattern\", options.urlPattern);\n\n const response = await resilientFetch(`${this.endpoint}?${params.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch feedbacks: ${response.status}`);\n }\n\n return (await response.json()) as { feedbacks: FeedbackResponse[]; total: number }; // Server validates via Zod\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const response = await resilientFetch(this.endpoint, {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName, status: resolved ? \"resolved\" : \"open\" }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to update feedback: ${response.status}`);\n }\n\n return (await response.json()) as FeedbackResponse; // Server validates via Zod\n }\n\n async deleteFeedback(id: string): Promise<void> {\n const response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ id, projectName: this.projectName }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to delete feedback: ${response.status}`);\n }\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n const response = await resilientFetch(this.endpoint, {\n method: \"DELETE\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ projectName, deleteAll: true }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to delete all feedbacks: ${response.status}`);\n }\n }\n}\n","type Listener = (...args: unknown[]) => void;\n\n/**\n * Lightweight typed EventEmitter — zero dependencies.\n */\nexport class EventBus<E extends { [K in keyof E]: unknown[] }> {\n private listeners = new Map<keyof E, Set<Listener>>();\n\n on<K extends keyof E>(event: K, listener: (...args: E[K]) => void): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n const set = this.listeners.get(event)!;\n set.add(listener as Listener);\n\n return () => {\n set.delete(listener as Listener);\n };\n }\n\n off<K extends keyof E>(event: K, listener: (...args: E[K]) => void): void {\n const set = this.listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n }\n }\n\n emit<K extends keyof E>(event: K, ...args: E[K]): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const fn of set) {\n try {\n fn(...args);\n } catch (err) {\n // Isolate listener errors — one bad listener must not kill others\n console.error(`[siteping] Error in event listener for \"${String(event)}\":`, err);\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget event types\n// ---------------------------------------------------------------------------\n\nexport interface WidgetEvents {\n open: [];\n close: [];\n \"feedback:sent\": [import(\"@siteping/core\").FeedbackResponse];\n \"feedback:deleted\": [string];\n \"feedback:all-deleted\": [];\n \"feedback:error\": [Error];\n \"annotation:start\": [];\n \"annotation:end\": [];\n \"annotation:complete\": [import(\"./annotator.js\").AnnotationComplete];\n \"annotations:toggle\": [boolean];\n \"panel:toggle\": [boolean];\n}\n\n/** Subset of WidgetEvents exposed to consumers via SitepingInstance */\nexport interface PublicWidgetEvents {\n \"feedback:sent\": [import(\"@siteping/core\").FeedbackResponse];\n \"feedback:deleted\": [string];\n \"panel:open\": [];\n \"panel:close\": [];\n}\n","import type { SitepingConfig } from \"@siteping/core\";\nimport { parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport type { TFunction } from \"./i18n/index.js\";\nimport { ICON_ANNOTATE, ICON_CHAT, ICON_CLOSE, ICON_EYE, ICON_EYE_OFF, ICON_SITEPING } from \"./icons.js\";\n\ninterface RadialItem {\n id: string;\n icon: string;\n iconAlt?: string;\n label: string;\n}\n\nconst ITEM_GAP = 54;\n\n/**\n * Floating Action Button with radial menu and notification badge.\n *\n * Glassmorphism: gradient background, glow shadow, glass radial items.\n * Badge shows unresolved feedback count.\n */\nexport class Fab {\n private root: HTMLElement;\n private fab: HTMLButtonElement;\n private radialContainer: HTMLElement;\n private badgeEl: HTMLElement | null = null;\n private isOpen = false;\n private annotationsVisible = true;\n private items: RadialItem[];\n\n constructor(\n shadowRoot: ShadowRoot,\n config: SitepingConfig,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n const position = config.position ?? \"bottom-right\";\n const isRight = position === \"bottom-right\";\n\n // Vertical stack above the FAB\n this.items = [\n { id: \"chat\", icon: ICON_CHAT, label: t(\"fab.messages\") },\n { id: \"annotate\", icon: ICON_ANNOTATE, label: t(\"fab.annotate\") },\n { id: \"toggle-annotations\", icon: ICON_EYE, iconAlt: ICON_EYE_OFF, label: t(\"fab.annotations\") },\n ];\n\n // FAB button — needs position:relative for badge positioning\n this.fab = document.createElement(\"button\");\n this.fab.className = `sp-fab sp-fab--${position} sp-anim-fab-in`;\n this.fab.style.position = \"fixed\"; // ensure fixed even with relative children\n this.fab.appendChild(parseSvg(ICON_SITEPING));\n this.fab.setAttribute(\"aria-label\", t(\"fab.aria\"));\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n this.fab.addEventListener(\"click\", () => this.toggle());\n\n // Radial container\n this.radialContainer = document.createElement(\"div\");\n this.radialContainer.className = `sp-radial sp-radial--${position}`;\n this.radialContainer.setAttribute(\"role\", \"menu\");\n\n for (let i = 0; i < this.items.length; i++) {\n const item = this.items[i];\n if (!item) continue;\n const btn = document.createElement(\"button\");\n btn.className = \"sp-radial-item\";\n btn.style.setProperty(\"--sp-i\", String(i));\n btn.appendChild(parseSvg(item.icon));\n btn.setAttribute(\"role\", \"menuitem\");\n btn.setAttribute(\"aria-label\", item.label);\n btn.dataset.itemId = item.id;\n\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.handleItemClick(item.id);\n });\n\n const label = document.createElement(\"span\");\n label.className = \"sp-radial-label\";\n label.textContent = item.label;\n label.style.cssText = isRight\n ? \"position:absolute; right:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\"\n : \"position:absolute; left:54px; top:50%; transform:translateY(-50%); white-space:nowrap;\";\n btn.appendChild(label);\n\n this.radialContainer.appendChild(btn);\n }\n\n this.root = document.createElement(\"div\");\n this.root.appendChild(this.radialContainer);\n this.root.appendChild(this.fab);\n shadowRoot.appendChild(this.root);\n\n // Close radial menu on click outside.\n const host = shadowRoot.host;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !e.composedPath().includes(host)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick);\n\n // Escape on FAB or menu container closes the menu\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && this.isOpen) {\n e.stopPropagation();\n this.close();\n }\n };\n this.fab.addEventListener(\"keydown\", handleEscape);\n this.radialContainer.addEventListener(\"keydown\", handleEscape);\n\n // Arrow key navigation within the radial menu\n this.radialContainer.addEventListener(\"keydown\", (e) => {\n const items = Array.from(this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\"));\n if (items.length === 0 || !this.isOpen) return;\n const activeEl = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement;\n const currentIndex = items.indexOf(activeEl as HTMLButtonElement);\n\n switch (e.key) {\n case \"ArrowUp\": {\n e.preventDefault();\n const nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"ArrowDown\": {\n e.preventDefault();\n const nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;\n items[nextIndex]?.focus();\n break;\n }\n case \"Home\": {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n });\n }\n\n private onDocumentClick: (e: MouseEvent) => void;\n\n /** Update the badge count. Pass 0 to hide. */\n updateBadge(count: number): void {\n if (count <= 0) {\n this.badgeEl?.remove();\n this.badgeEl = null;\n return;\n }\n\n if (!this.badgeEl) {\n this.badgeEl = document.createElement(\"span\");\n this.badgeEl.className = \"sp-fab-badge\";\n this.badgeEl.setAttribute(\"role\", \"status\");\n this.badgeEl.setAttribute(\"aria-live\", \"polite\");\n this.fab.appendChild(this.badgeEl);\n }\n\n const displayText = count > 99 ? \"99+\" : String(count);\n setText(this.badgeEl, displayText);\n this.badgeEl.setAttribute(\"aria-label\", this.t(\"fab.badge\").replace(\"{count}\", String(count)));\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.setFabIcon(ICON_CLOSE);\n this.fab.setAttribute(\"aria-expanded\", \"true\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn, i) => {\n // Stack vertically above the FAB with initial offset + gap\n const y = -(16 + ITEM_GAP * (i + 1));\n btn.style.transform = `translate(0px, ${y}px) scale(1)`;\n btn.classList.add(\"sp-radial-item--open\");\n });\n\n // Focus the first menu item after animation\n requestAnimationFrame(() => {\n const firstItem = this.radialContainer.querySelector<HTMLButtonElement>(\".sp-radial-item\");\n firstItem?.focus();\n });\n }\n\n private close(): void {\n this.isOpen = false;\n this.setFabIcon(ICON_SITEPING);\n this.fab.setAttribute(\"aria-expanded\", \"false\");\n\n const buttons = this.radialContainer.querySelectorAll<HTMLButtonElement>(\".sp-radial-item\");\n buttons.forEach((btn) => {\n btn.style.transform = \"translate(0, 0) scale(0.8)\";\n btn.classList.remove(\"sp-radial-item--open\");\n });\n\n // Return focus to FAB\n this.fab.focus();\n }\n\n private setFabIcon(svgStr: string): void {\n const badge = this.badgeEl;\n this.fab.replaceChildren(parseSvg(svgStr));\n // Re-append badge after icon swap\n if (badge) this.fab.appendChild(badge);\n }\n\n private handleItemClick(id: string): void {\n this.close();\n\n switch (id) {\n case \"chat\":\n this.bus.emit(\"panel:toggle\", true);\n break;\n case \"annotate\":\n this.bus.emit(\"annotation:start\");\n break;\n case \"toggle-annotations\": {\n this.annotationsVisible = !this.annotationsVisible;\n this.bus.emit(\"annotations:toggle\", this.annotationsVisible);\n const btn = this.radialContainer.querySelector('[data-item-id=\"toggle-annotations\"]');\n if (btn) {\n btn.replaceChildren(parseSvg(this.annotationsVisible ? ICON_EYE : ICON_EYE_OFF));\n }\n break;\n }\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick);\n this.root.remove();\n }\n}\n","import type { Translations } from \"./types.js\";\n\nexport const de: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Siteping-Feedback-Panel\",\n \"panel.feedbackList\": \"Feedbackliste\",\n \"panel.loading\": \"Feedbacks werden geladen\",\n \"panel.close\": \"Panel schließen\",\n \"panel.deleteAll\": \"Alle löschen\",\n \"panel.deleteAllConfirmTitle\": \"Alle löschen\",\n \"panel.deleteAllConfirmMessage\":\n \"Alle Feedbacks für dieses Projekt löschen? Diese Aktion kann nicht rückgängig gemacht werden.\",\n \"panel.search\": \"Suchen...\",\n \"panel.searchAria\": \"Feedbacks suchen\",\n \"panel.filterAll\": \"Alle\",\n \"panel.loadError\": \"Laden fehlgeschlagen\",\n \"panel.retry\": \"Erneut versuchen\",\n \"panel.empty\": \"Noch kein Feedback\",\n \"panel.showMore\": \"Mehr anzeigen\",\n \"panel.showLess\": \"Weniger anzeigen\",\n \"panel.resolve\": \"Erledigen\",\n \"panel.reopen\": \"Wieder öffnen\",\n \"panel.delete\": \"Löschen\",\n \"panel.cancel\": \"Abbrechen\",\n \"panel.confirmDelete\": \"Löschen\",\n \"panel.loadMore\": \"Mehr laden ({remaining} verbleibend)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Alle\",\n \"panel.statusOpen\": \"Offen\",\n \"panel.statusResolved\": \"Erledigt\",\n\n // Feedback type labels\n \"type.label\": \"Typ\",\n \"type.question\": \"Frage\",\n \"type.change\": \"Änderung\",\n \"type.bug\": \"Fehler\",\n \"type.other\": \"Sonstiges\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // Page scope segmented control\n \"scope.label\": \"Bereich\",\n \"scope.thisPage\": \"Diese Seite\",\n \"scope.thisType\": \"Dieser Typ\",\n \"scope.all\": \"Alle Seiten\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Feedback-Menü\",\n \"fab.messages\": \"Nachrichten\",\n \"fab.annotate\": \"Kommentieren\",\n \"fab.annotations\": \"Anmerkungen\",\n\n // Annotator\n \"annotator.instruction\": \"Zeichne ein Rechteck um den Bereich, den du kommentieren möchtest\",\n \"annotator.cancel\": \"Abbrechen\",\n\n // Popup\n \"popup.ariaLabel\": \"Feedbackformular\",\n \"popup.placeholder\": \"Beschreibe dein Feedback...\",\n \"popup.textareaAria\": \"Feedbacknachricht\",\n \"popup.submitHintMac\": \"⌘+Enter zum Senden\",\n \"popup.submitHintOther\": \"Strg+Enter zum Senden\",\n \"popup.cancel\": \"Abbrechen\",\n \"popup.submit\": \"Senden\",\n\n // Identity modal\n \"identity.title\": \"Identifiziere dich\",\n \"identity.nameLabel\": \"Name\",\n \"identity.namePlaceholder\": \"Dein Name\",\n \"identity.emailLabel\": \"E-Mail\",\n \"identity.emailPlaceholder\": \"deine@email.de\",\n \"identity.cancel\": \"Abbrechen\",\n \"identity.submit\": \"Fortfahren\",\n\n // Markers\n \"marker.approximate\": \"Ungefähre Position (Konfidenz: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} unerledigte Feedbacks\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback erfolgreich gesendet\",\n \"feedback.error.message\": \"Feedback konnte nicht gesendet werden\",\n \"feedback.deleted.confirmation\": \"Feedback gelöscht\",\n\n // Badge\n \"badge.count\": \"{count} unerledigte Feedbacks\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const en: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Siteping feedback panel\",\n \"panel.feedbackList\": \"Feedback list\",\n \"panel.loading\": \"Loading feedbacks\",\n \"panel.close\": \"Close panel\",\n \"panel.deleteAll\": \"Delete all\",\n \"panel.deleteAllConfirmTitle\": \"Delete all\",\n \"panel.deleteAllConfirmMessage\": \"Delete all feedbacks for this project? This action cannot be undone.\",\n \"panel.search\": \"Search...\",\n \"panel.searchAria\": \"Search feedbacks\",\n \"panel.filterAll\": \"All\",\n \"panel.loadError\": \"Failed to load\",\n \"panel.retry\": \"Retry\",\n \"panel.empty\": \"No feedback yet\",\n \"panel.showMore\": \"Show more\",\n \"panel.showLess\": \"Show less\",\n \"panel.resolve\": \"Resolve\",\n \"panel.reopen\": \"Reopen\",\n \"panel.delete\": \"Delete\",\n \"panel.cancel\": \"Cancel\",\n \"panel.confirmDelete\": \"Delete\",\n \"panel.loadMore\": \"Load more ({remaining} remaining)\",\n\n // Status filter labels\n \"panel.statusAll\": \"All\",\n \"panel.statusOpen\": \"Open\",\n \"panel.statusResolved\": \"Resolved\",\n\n // Feedback type labels\n \"type.label\": \"Type\",\n \"type.question\": \"Question\",\n \"type.change\": \"Change\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Other\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // Page scope segmented control\n \"scope.label\": \"Scope\",\n \"scope.thisPage\": \"This page\",\n \"scope.thisType\": \"This type\",\n \"scope.all\": \"All pages\",\n\n // FAB menu\n \"fab.aria\": \"Siteping \\u2014 Feedback menu\",\n \"fab.messages\": \"Messages\",\n \"fab.annotate\": \"Annotate\",\n \"fab.annotations\": \"Annotations\",\n\n // Annotator\n \"annotator.instruction\": \"Draw a rectangle on the area to comment\",\n \"annotator.cancel\": \"Cancel\",\n\n // Popup\n \"popup.ariaLabel\": \"Feedback form\",\n \"popup.placeholder\": \"Describe your feedback...\",\n \"popup.textareaAria\": \"Feedback message\",\n \"popup.submitHintMac\": \"\\u2318+Enter to send\",\n \"popup.submitHintOther\": \"Ctrl+Enter to send\",\n \"popup.cancel\": \"Cancel\",\n \"popup.submit\": \"Send\",\n\n // Identity modal\n \"identity.title\": \"Identify yourself\",\n \"identity.nameLabel\": \"Name\",\n \"identity.namePlaceholder\": \"Your name\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"your@email.com\",\n \"identity.cancel\": \"Cancel\",\n \"identity.submit\": \"Continue\",\n\n // Markers\n \"marker.approximate\": \"Approximate position (confidence: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} unresolved feedbacks\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback sent successfully\",\n \"feedback.error.message\": \"Failed to send feedback\",\n \"feedback.deleted.confirmation\": \"Feedback deleted\",\n\n // Badge\n \"badge.count\": \"{count} unresolved feedbacks\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const es: Translations = {\n // Panel\n \"panel.title\": \"Comentarios\",\n \"panel.ariaLabel\": \"Panel de comentarios de Siteping\",\n \"panel.feedbackList\": \"Lista de comentarios\",\n \"panel.loading\": \"Cargando comentarios\",\n \"panel.close\": \"Cerrar panel\",\n \"panel.deleteAll\": \"Eliminar todo\",\n \"panel.deleteAllConfirmTitle\": \"Eliminar todo\",\n \"panel.deleteAllConfirmMessage\":\n \"¿Eliminar todos los comentarios de este proyecto? Esta acción no se puede deshacer.\",\n \"panel.search\": \"Buscar...\",\n \"panel.searchAria\": \"Buscar comentarios\",\n \"panel.filterAll\": \"Todos\",\n \"panel.loadError\": \"No se pudo cargar\",\n \"panel.retry\": \"Reintentar\",\n \"panel.empty\": \"Aún no hay comentarios\",\n \"panel.showMore\": \"Mostrar más\",\n \"panel.showLess\": \"Mostrar menos\",\n \"panel.resolve\": \"Resolver\",\n \"panel.reopen\": \"Reabrir\",\n \"panel.delete\": \"Eliminar\",\n \"panel.cancel\": \"Cancelar\",\n \"panel.confirmDelete\": \"Eliminar\",\n \"panel.loadMore\": \"Cargar más ({remaining} restantes)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Todos\",\n \"panel.statusOpen\": \"Abiertos\",\n \"panel.statusResolved\": \"Resueltos\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Pregunta\",\n \"type.change\": \"Cambio\",\n \"type.bug\": \"Error\",\n \"type.other\": \"Otro\",\n\n // Status segmented control label\n \"status.label\": \"Estado\",\n\n // Page scope segmented control\n \"scope.label\": \"Ámbito\",\n \"scope.thisPage\": \"Esta página\",\n \"scope.thisType\": \"Este tipo\",\n \"scope.all\": \"Todas las páginas\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menú de comentarios\",\n \"fab.messages\": \"Mensajes\",\n \"fab.annotate\": \"Anotar\",\n \"fab.annotations\": \"Anotaciones\",\n\n // Annotator\n \"annotator.instruction\": \"Dibuja un rectángulo sobre el área que quieres comentar\",\n \"annotator.cancel\": \"Cancelar\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulario de comentarios\",\n \"popup.placeholder\": \"Describe tu comentario...\",\n \"popup.textareaAria\": \"Mensaje de comentario\",\n \"popup.submitHintMac\": \"⌘+Enter para enviar\",\n \"popup.submitHintOther\": \"Ctrl+Enter para enviar\",\n \"popup.cancel\": \"Cancelar\",\n \"popup.submit\": \"Enviar\",\n\n // Identity modal\n \"identity.title\": \"Identifícate\",\n \"identity.nameLabel\": \"Nombre\",\n \"identity.namePlaceholder\": \"Tu nombre\",\n \"identity.emailLabel\": \"Correo electrónico\",\n \"identity.emailPlaceholder\": \"tu@email.com\",\n \"identity.cancel\": \"Cancelar\",\n \"identity.submit\": \"Continuar\",\n\n // Markers\n \"marker.approximate\": \"Posición aproximada (confianza: {confidence}%)\",\n \"marker.aria\": \"Comentario #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} comentarios sin resolver\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Comentario enviado correctamente\",\n \"feedback.error.message\": \"No se pudo enviar el comentario\",\n \"feedback.deleted.confirmation\": \"Comentario eliminado\",\n\n // Badge\n \"badge.count\": \"{count} comentarios sin resolver\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const fr: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Panneau de feedback Siteping\",\n \"panel.feedbackList\": \"Liste des feedbacks\",\n \"panel.loading\": \"Chargement des feedbacks\",\n \"panel.close\": \"Fermer le panneau\",\n \"panel.deleteAll\": \"Tout supprimer\",\n \"panel.deleteAllConfirmTitle\": \"Tout supprimer\",\n \"panel.deleteAllConfirmMessage\": \"Supprimer tous les feedbacks de ce projet ? Cette action est irr\\u00e9versible.\",\n \"panel.search\": \"Rechercher...\",\n \"panel.searchAria\": \"Rechercher dans les feedbacks\",\n \"panel.filterAll\": \"Tous\",\n \"panel.loadError\": \"Erreur de chargement\",\n \"panel.retry\": \"R\\u00e9essayer\",\n \"panel.empty\": \"Aucun feedback pour le moment\",\n \"panel.showMore\": \"Voir plus\",\n \"panel.showLess\": \"Voir moins\",\n \"panel.resolve\": \"R\\u00e9soudre\",\n \"panel.reopen\": \"Rouvrir\",\n \"panel.delete\": \"Supprimer\",\n \"panel.cancel\": \"Annuler\",\n \"panel.confirmDelete\": \"Supprimer\",\n \"panel.loadMore\": \"Voir plus ({remaining} restants)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Tous\",\n \"panel.statusOpen\": \"Ouvert\",\n \"panel.statusResolved\": \"Résolu\",\n\n // Feedback type labels\n \"type.label\": \"Type\",\n \"type.question\": \"Question\",\n \"type.change\": \"Changement\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Autre\",\n\n // Status segmented control label\n \"status.label\": \"Statut\",\n\n // Page scope segmented control\n \"scope.label\": \"Portée\",\n \"scope.thisPage\": \"Cette page\",\n \"scope.thisType\": \"Ce type\",\n \"scope.all\": \"Toutes les pages\",\n\n // FAB menu\n \"fab.aria\": \"Siteping \\u2014 Menu feedback\",\n \"fab.messages\": \"Messages\",\n \"fab.annotate\": \"Annoter\",\n \"fab.annotations\": \"Annotations\",\n\n // Annotator\n \"annotator.instruction\": \"Tracez un rectangle sur la zone \\u00e0 commenter\",\n \"annotator.cancel\": \"Annuler\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulaire de feedback\",\n \"popup.placeholder\": \"D\\u00e9crivez votre retour...\",\n \"popup.textareaAria\": \"Message de feedback\",\n \"popup.submitHintMac\": \"\\u2318+Entr\\u00e9e pour envoyer\",\n \"popup.submitHintOther\": \"Ctrl+Entr\\u00e9e pour envoyer\",\n \"popup.cancel\": \"Annuler\",\n \"popup.submit\": \"Envoyer\",\n\n // Identity modal\n \"identity.title\": \"Identifiez-vous\",\n \"identity.nameLabel\": \"Nom\",\n \"identity.namePlaceholder\": \"Votre nom\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"votre@email.com\",\n \"identity.cancel\": \"Annuler\",\n \"identity.submit\": \"Continuer\",\n\n // Markers\n \"marker.approximate\": \"Position approximative (confiance : {confidence}%)\",\n \"marker.aria\": \"Feedback n°{number} : {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedbacks non résolus\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback envoyé avec succès\",\n \"feedback.error.message\": \"Échec de l'envoi du feedback\",\n \"feedback.deleted.confirmation\": \"Feedback supprimé\",\n\n // Badge\n \"badge.count\": \"{count} feedbacks non résolus\",\n};\n","import type { Translations } from \"./types.js\";\n\n/** Italian translations (it-IT). */\nexport const it: Translations = {\n // Panel\n \"panel.title\": \"Feedback\",\n \"panel.ariaLabel\": \"Pannello feedback di Siteping\",\n \"panel.feedbackList\": \"Elenco feedback\",\n \"panel.loading\": \"Caricamento feedback\",\n \"panel.close\": \"Chiudi pannello\",\n \"panel.deleteAll\": \"Elimina tutto\",\n \"panel.deleteAllConfirmTitle\": \"Elimina tutto\",\n \"panel.deleteAllConfirmMessage\":\n \"Eliminare tutti i feedback per questo progetto? Questa azione non può essere annullata.\",\n \"panel.search\": \"Cerca...\",\n \"panel.searchAria\": \"Cerca feedback\",\n \"panel.filterAll\": \"Tutti\",\n \"panel.loadError\": \"Caricamento non riuscito\",\n \"panel.retry\": \"Riprova\",\n \"panel.empty\": \"Nessun feedback ancora\",\n \"panel.showMore\": \"Mostra di più\",\n \"panel.showLess\": \"Mostra meno\",\n \"panel.resolve\": \"Risolvi\",\n \"panel.reopen\": \"Riapri\",\n \"panel.delete\": \"Elimina\",\n \"panel.cancel\": \"Annulla\",\n \"panel.confirmDelete\": \"Elimina\",\n \"panel.loadMore\": \"Carica altro ({remaining} rimanenti)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Tutti\",\n \"panel.statusOpen\": \"Aperti\",\n \"panel.statusResolved\": \"Risolti\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Domanda\",\n \"type.change\": \"Modifica\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Altro\",\n\n // Status segmented control label\n \"status.label\": \"Stato\",\n\n // Page scope segmented control\n \"scope.label\": \"Ambito\",\n \"scope.thisPage\": \"Questa pagina\",\n \"scope.thisType\": \"Questo tipo\",\n \"scope.all\": \"Tutte le pagine\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menu feedback\",\n \"fab.messages\": \"Messaggi\",\n \"fab.annotate\": \"Annota\",\n \"fab.annotations\": \"Annotazioni\",\n\n // Annotator\n \"annotator.instruction\": \"Disegna un rettangolo sull'area da commentare\",\n \"annotator.cancel\": \"Annulla\",\n\n // Popup\n \"popup.ariaLabel\": \"Modulo feedback\",\n \"popup.placeholder\": \"Descrivi il tuo feedback...\",\n \"popup.textareaAria\": \"Messaggio di feedback\",\n \"popup.submitHintMac\": \"⌘+Invio per inviare\",\n \"popup.submitHintOther\": \"Ctrl+Invio per inviare\",\n \"popup.cancel\": \"Annulla\",\n \"popup.submit\": \"Invia\",\n\n // Identity modal\n \"identity.title\": \"Identificati\",\n \"identity.nameLabel\": \"Nome\",\n \"identity.namePlaceholder\": \"Il tuo nome\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"tua@email.com\",\n \"identity.cancel\": \"Annulla\",\n \"identity.submit\": \"Continua\",\n\n // Markers\n \"marker.approximate\": \"Posizione approssimativa (confidenza: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedback non risolti\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback inviato con successo\",\n \"feedback.error.message\": \"Invio del feedback non riuscito\",\n \"feedback.deleted.confirmation\": \"Feedback eliminato\",\n\n // Badge\n \"badge.count\": \"{count} feedback non risolti\",\n};\n","import type { Translations } from \"./types.js\";\n\n/** Brazilian Portuguese translations (pt-BR). */\nexport const pt: Translations = {\n // Panel\n \"panel.title\": \"Feedbacks\",\n \"panel.ariaLabel\": \"Painel de feedback do Siteping\",\n \"panel.feedbackList\": \"Lista de feedbacks\",\n \"panel.loading\": \"Carregando feedbacks\",\n \"panel.close\": \"Fechar painel\",\n \"panel.deleteAll\": \"Excluir tudo\",\n \"panel.deleteAllConfirmTitle\": \"Excluir tudo\",\n \"panel.deleteAllConfirmMessage\": \"Excluir todos os feedbacks deste projeto? Esta ação não pode ser desfeita.\",\n \"panel.search\": \"Pesquisar...\",\n \"panel.searchAria\": \"Pesquisar feedbacks\",\n \"panel.filterAll\": \"Todos\",\n \"panel.loadError\": \"Falha ao carregar\",\n \"panel.retry\": \"Tentar novamente\",\n \"panel.empty\": \"Nenhum feedback ainda\",\n \"panel.showMore\": \"Mostrar mais\",\n \"panel.showLess\": \"Mostrar menos\",\n \"panel.resolve\": \"Resolver\",\n \"panel.reopen\": \"Reabrir\",\n \"panel.delete\": \"Excluir\",\n \"panel.cancel\": \"Cancelar\",\n \"panel.confirmDelete\": \"Excluir\",\n \"panel.loadMore\": \"Carregar mais ({remaining} restantes)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Todos\",\n \"panel.statusOpen\": \"Abertos\",\n \"panel.statusResolved\": \"Resolvidos\",\n\n // Feedback type labels\n \"type.label\": \"Tipo\",\n \"type.question\": \"Pergunta\",\n \"type.change\": \"Alteração\",\n \"type.bug\": \"Bug\",\n \"type.other\": \"Outro\",\n\n // Status segmented control label\n \"status.label\": \"Status\",\n\n // Page scope segmented control\n \"scope.label\": \"Escopo\",\n \"scope.thisPage\": \"Esta página\",\n \"scope.thisType\": \"Este tipo\",\n \"scope.all\": \"Todas as páginas\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Menu de feedback\",\n \"fab.messages\": \"Mensagens\",\n \"fab.annotate\": \"Anotar\",\n \"fab.annotations\": \"Anotações\",\n\n // Annotator\n \"annotator.instruction\": \"Desenhe um retângulo na área que deseja comentar\",\n \"annotator.cancel\": \"Cancelar\",\n\n // Popup\n \"popup.ariaLabel\": \"Formulário de feedback\",\n \"popup.placeholder\": \"Descreva seu feedback...\",\n \"popup.textareaAria\": \"Mensagem de feedback\",\n \"popup.submitHintMac\": \"⌘+Enter para enviar\",\n \"popup.submitHintOther\": \"Ctrl+Enter para enviar\",\n \"popup.cancel\": \"Cancelar\",\n \"popup.submit\": \"Enviar\",\n\n // Identity modal\n \"identity.title\": \"Identifique-se\",\n \"identity.nameLabel\": \"Nome\",\n \"identity.namePlaceholder\": \"Seu nome\",\n \"identity.emailLabel\": \"E-mail\",\n \"identity.emailPlaceholder\": \"seu@email.com\",\n \"identity.cancel\": \"Cancelar\",\n \"identity.submit\": \"Continuar\",\n\n // Markers\n \"marker.approximate\": \"Posição aproximada (confiança: {confidence}%)\",\n \"marker.aria\": \"Feedback #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"{count} feedbacks não resolvidos\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Feedback enviado com sucesso\",\n \"feedback.error.message\": \"Falha ao enviar feedback\",\n \"feedback.deleted.confirmation\": \"Feedback excluído\",\n\n // Badge\n \"badge.count\": \"{count} feedbacks não resolvidos\",\n};\n","import type { Translations } from \"./types.js\";\n\nexport const ru: Translations = {\n // Panel\n \"panel.title\": \"Обратная связь\",\n \"panel.ariaLabel\": \"Панель обратной связи Siteping\",\n \"panel.feedbackList\": \"Список отзывов\",\n \"panel.loading\": \"Загрузка отзывов\",\n \"panel.close\": \"Закрыть панель\",\n \"panel.deleteAll\": \"Удалить всё\",\n \"panel.deleteAllConfirmTitle\": \"Удалить всё\",\n \"panel.deleteAllConfirmMessage\": \"Удалить все отзывы этого проекта? Это действие необратимо.\",\n \"panel.search\": \"Поиск...\",\n \"panel.searchAria\": \"Поиск по отзывам\",\n \"panel.filterAll\": \"Все\",\n \"panel.loadError\": \"Ошибка загрузки\",\n \"panel.retry\": \"Повторить\",\n \"panel.empty\": \"Пока нет отзывов\",\n \"panel.showMore\": \"Показать больше\",\n \"panel.showLess\": \"Показать меньше\",\n \"panel.resolve\": \"Решено\",\n \"panel.reopen\": \"Открыть заново\",\n \"panel.delete\": \"Удалить\",\n \"panel.cancel\": \"Отмена\",\n \"panel.confirmDelete\": \"Удалить\",\n \"panel.loadMore\": \"Показать ещё ({remaining} осталось)\",\n\n // Status filter labels\n \"panel.statusAll\": \"Все\",\n \"panel.statusOpen\": \"Открытые\",\n \"panel.statusResolved\": \"Решённые\",\n\n // Feedback type labels\n \"type.label\": \"Тип\",\n \"type.question\": \"Вопрос\",\n \"type.change\": \"Улучшение\",\n \"type.bug\": \"Баг\",\n \"type.other\": \"Другое\",\n\n // Status segmented control label\n \"status.label\": \"Статус\",\n\n // Page scope segmented control\n \"scope.label\": \"Область\",\n \"scope.thisPage\": \"Эта страница\",\n \"scope.thisType\": \"Этот тип\",\n \"scope.all\": \"Все страницы\",\n\n // FAB menu\n \"fab.aria\": \"Siteping — Меню обратной связи\",\n \"fab.messages\": \"Сообщения\",\n \"fab.annotate\": \"Аннотация\",\n \"fab.annotations\": \"Аннотации\",\n\n // Annotator\n \"annotator.instruction\": \"Выделите область для комментария\",\n \"annotator.cancel\": \"Отмена\",\n\n // Popup\n \"popup.ariaLabel\": \"Форма обратной связи\",\n \"popup.placeholder\": \"Опишите проблему или предложение...\",\n \"popup.textareaAria\": \"Сообщение\",\n \"popup.submitHintMac\": \"⌘+Enter — отправить\",\n \"popup.submitHintOther\": \"Ctrl+Enter — отправить\",\n \"popup.cancel\": \"Отмена\",\n \"popup.submit\": \"Отправить\",\n\n // Identity modal\n \"identity.title\": \"Представьтесь\",\n \"identity.nameLabel\": \"Имя\",\n \"identity.namePlaceholder\": \"Ваше имя\",\n \"identity.emailLabel\": \"Email\",\n \"identity.emailPlaceholder\": \"ваш@email.com\",\n \"identity.cancel\": \"Отмена\",\n \"identity.submit\": \"Продолжить\",\n\n // Markers\n \"marker.approximate\": \"Приблизительная позиция (точность: {confidence}%)\",\n \"marker.aria\": \"Отзыв #{number}: {type} — {message}\",\n\n // FAB badge\n \"fab.badge\": \"Нерешённых отзывов: {count}\",\n\n // Accessibility — screen reader announcements\n \"feedback.sent.confirmation\": \"Отзыв успешно отправлен\",\n \"feedback.error.message\": \"Не удалось отправить отзыв\",\n \"feedback.deleted.confirmation\": \"Отзыв удалён\",\n\n // Badge\n \"badge.count\": \"Нерешённых отзывов: {count}\",\n};\n","import type { TFunction, Translations } from \"./types.js\";\n\nexport type { TFunction, Translations } from \"./types.js\";\n\n// Static imports — bundler (tsup) will include them all.\n// For tree-shaking in consumer apps, use dynamic import() with a bundler plugin.\nimport { de } from \"./de.js\";\nimport { en } from \"./en.js\";\nimport { es } from \"./es.js\";\nimport { fr } from \"./fr.js\";\nimport { it } from \"./it.js\";\nimport { pt } from \"./pt.js\";\nimport { ru } from \"./ru.js\";\n\nconst LOCALES: Record<string, Translations> = { de, en, es, fr, it, pt, ru };\n\n/** Register a custom locale at runtime. */\nexport function registerLocale(code: string, translations: Translations): void {\n LOCALES[code] = translations;\n}\n\n/**\n * Create a translation function for the given locale.\n *\n * Locale resolution: exact match > language prefix > English fallback.\n */\nexport function createT(locale: string): TFunction {\n const lang = (locale.split(\"-\")[0] ?? locale).toLowerCase();\n if (!LOCALES[lang]) {\n console.warn(`[siteping] Unknown locale \"${locale}\", falling back to \"en\"`);\n }\n const dict = LOCALES[lang] ?? LOCALES.en ?? ({} as Translations);\n return (key) => dict[key] ?? key;\n}\n\n/**\n * Returns the type label for a FeedbackType value.\n * Maps API enum values (english) to localized display labels.\n */\nexport function getTypeLabel(type: string, t: TFunction): string {\n switch (type) {\n case \"question\":\n return t(\"type.question\");\n case \"change\":\n return t(\"type.change\");\n case \"bug\":\n return t(\"type.bug\");\n case \"other\":\n return t(\"type.other\");\n default:\n return type;\n }\n}\n","const STORAGE_KEY = \"siteping_identity\";\n\nexport interface Identity {\n name: string;\n email: string;\n}\n\nexport function getIdentity(): Identity | null {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"name\" in parsed &&\n typeof (parsed as Record<string, unknown>).name === \"string\" &&\n \"email\" in parsed &&\n typeof (parsed as Record<string, unknown>).email === \"string\"\n ) {\n const identity = parsed as Identity;\n if (identity.name && identity.email) return identity;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function saveIdentity(identity: Identity): void {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(identity));\n } catch {\n // Quota exceeded or localStorage disabled — identity works for this session only\n }\n}\n","/**\n * Lightweight fuzzy text matching for DOM re-anchoring.\n * Zero dependencies — bundled into the widget.\n * Uses Levenshtein distance, optimized for short strings (~50 chars).\n */\n\n/**\n * Levenshtein edit distance.\n * O(n*m) time, O(min(n,m)) space.\n */\nexport function editDistance(a: string, b: string): number {\n if (a === b) return 0;\n if (a.length === 0) return b.length;\n if (b.length === 0) return a.length;\n\n // Ensure `a` is the shorter string for space optimization\n if (a.length > b.length) {\n const t = a;\n a = b;\n b = t;\n }\n\n const aLen = a.length;\n const bLen = b.length;\n let prev = new Array<number>(aLen + 1);\n for (let k = 0; k <= aLen; k++) prev[k] = k;\n let curr = new Array<number>(aLen + 1);\n\n for (let j = 1; j <= bLen; j++) {\n curr[0] = j;\n for (let i = 1; i <= aLen; i++) {\n // Indices are valid: i-1 in [0, aLen-1], j-1 in [0, bLen-1], loop bounds guarantee access\n const prevDiag = prev[i - 1] ?? 0;\n curr[i] = a[i - 1] === b[j - 1] ? prevDiag : 1 + Math.min(prevDiag, prev[i] ?? 0, curr[i - 1] ?? 0);\n }\n const tmp = prev;\n prev = curr;\n curr = tmp;\n }\n\n return prev[aLen] ?? 0; // aLen is within bounds — prev has aLen+1 entries\n}\n\n/**\n * Normalized similarity score (0–1, where 1 = identical).\n */\nexport function similarity(a: string, b: string): number {\n if (a === b) return 1;\n const maxLen = Math.max(a.length, b.length);\n if (maxLen === 0) return 1;\n return 1 - editDistance(a, b) / maxLen;\n}\n\n/**\n * Fuzzy substring search — checks if `needle` approximately exists in `haystack`.\n * Slides a window of `needle.length` over the haystack and returns the best\n * similarity score found. Returns 0 if below `minScore`.\n */\nexport function fuzzyIncludes(haystack: string, needle: string, minScore = 0.6): number {\n if (!needle || !haystack) return 0;\n if (haystack.includes(needle)) return 1;\n\n const nLen = needle.length;\n\n // If needle is longer than haystack, compare directly\n if (nLen > haystack.length) {\n const score = similarity(haystack, needle);\n return score >= minScore ? score : 0;\n }\n\n let best = 0;\n\n // Cap haystack to avoid O(n²) on huge text nodes\n const capped = haystack.length > 500 ? haystack.slice(0, 500) : haystack;\n const limit = capped.length - nLen;\n\n for (let i = 0; i <= limit; i++) {\n const window = capped.slice(i, i + nLen);\n const score = similarity(window, needle);\n if (score > best) best = score;\n if (best >= 0.95) break;\n }\n\n return best >= minScore ? best : 0;\n}\n","import type { AnchorData, RectData } from \"@siteping/core\";\nimport { ANCHOR_KEY_ATTR } from \"./anchor.js\";\nimport { scoreFingerprint } from \"./fingerprint.js\";\nimport { fuzzyIncludes, similarity } from \"./fuzzy.js\";\nimport { adjacentText, neighborText } from \"./text-context.js\";\n\nexport type ResolutionStrategy = \"anchorKey\" | \"id\" | \"css\" | \"xpath\" | \"scan\";\n\nexport interface AnchorResolution {\n element: Element;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\nexport interface ResolvedAnnotation {\n element: Element;\n rect: DOMRect;\n confidence: number;\n strategy: ResolutionStrategy;\n}\n\n/** Max elements to scan during smart fallback. */\nconst MAX_SCAN_CANDIDATES = 300;\n\n/** Minimum fuzzy text match score for CSS/XPath verification. */\nconst TEXT_MATCH_THRESHOLD = 0.3;\n\n/**\n * Verify that a resolved element's text content matches the stored snippet.\n * If no snippet is stored, returns true (no verification possible).\n * Uses fuzzy matching to tolerate minor text changes.\n */\nfunction textMatches(el: Element, anchor: AnchorData): boolean {\n if (!anchor.textSnippet) return true;\n const text = (el.textContent?.trim() ?? \"\").slice(0, 500);\n return fuzzyIncludes(text, anchor.textSnippet, 0.5) > TEXT_MATCH_THRESHOLD;\n}\n\n/**\n * Re-anchor an annotation using a multi-level fallback strategy\n * with text verification and confidence scoring.\n *\n * Resolution order:\n * 0. Semantic anchor key (`[data-feedback-anchor=\"X\"]`) — confidence 1.0\n * when host explicitly tagged the section. Tag name is NOT enforced —\n * hosts may legitimately refactor the wrapper element while keeping the\n * semantic key stable.\n * 1. getElementById + text verification — confidence 1.0\n * 2. CSS selector + text verification — confidence 0.95\n * 3. XPath + text verification — confidence 0.9\n * 4. Smart scan (fingerprint + text + prefix/suffix + neighbor) — up to 0.85\n *\n * Text verification prevents false matches when DOM elements are reordered.\n * Returns null if all strategies fail (annotation is orphaned).\n */\nexport function resolveAnchor(anchor: AnchorData): AnchorResolution | null {\n // Level 0: Semantic anchor key (host-controlled, most stable)\n if (anchor.anchorKey) {\n // Escape backslash and double-quote so an arbitrary key never breaks the selector\n const escaped = anchor.anchorKey.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n try {\n const el = document.querySelector(`[${ANCHOR_KEY_ATTR}=\"${escaped}\"]`);\n // Skip tagName check — semantic anchor identifies a section, not a tag\n if (el && textMatches(el, anchor)) {\n return { element: el, confidence: 1.0, strategy: \"anchorKey\" };\n }\n } catch {\n // Invalid attribute value — fall through to next strategy\n }\n }\n\n // Level 1: Element ID (most stable, still verify text)\n if (anchor.elementId) {\n const el = document.getElementById(anchor.elementId);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 1.0, strategy: \"id\" };\n }\n }\n\n // Level 2: CSS Selector (with text verification)\n try {\n const el = document.querySelector(anchor.cssSelector);\n if (el && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.95, strategy: \"css\" };\n }\n } catch {\n // Invalid selector — skip\n }\n\n // Level 3: XPath (with text verification)\n try {\n const result = document.evaluate(anchor.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n const el = result.singleNodeValue;\n if (el instanceof Element && el.tagName === anchor.elementTag && textMatches(el, anchor)) {\n return { element: el, confidence: 0.9, strategy: \"xpath\" };\n }\n } catch {\n // Invalid XPath — skip\n }\n\n // Level 4: Smart scan — combine all available signals\n return smartScan(anchor);\n}\n\n/**\n * Scan DOM elements by tag and score each candidate using multiple signals:\n * fingerprint, text similarity, prefix/suffix context, neighbor text.\n *\n * Returns the best candidate above a 0.4 threshold, capped at 0.85 confidence\n * (smart scan is never 100% certain).\n */\nfunction smartScan(anchor: AnchorData): AnchorResolution | null {\n const tag = anchor.elementTag.toLowerCase();\n const candidates = document.querySelectorAll(tag);\n if (candidates.length === 0) return null;\n\n let bestElement: Element | null = null;\n let bestScore = 0;\n\n const limit = Math.min(candidates.length, MAX_SCAN_CANDIDATES);\n\n for (let i = 0; i < limit; i++) {\n const el = candidates[i];\n if (!el) continue;\n const score = scoreCandidate(el, anchor);\n if (score > bestScore) {\n bestScore = score;\n bestElement = el;\n if (bestScore >= 0.85) break;\n }\n }\n\n if (!bestElement || bestScore < 0.4) return null;\n\n return {\n element: bestElement,\n confidence: Math.min(bestScore, 0.85),\n strategy: \"scan\",\n };\n}\n\n/**\n * Score a candidate element against all stored anchor signals.\n *\n * Dynamic weighting — only active signals contribute, then normalized:\n * - Text snippet (fuzzy substring match): weight 40 (most reliable for reordering)\n * - Fingerprint (structural match): weight 20\n * - Prefix/suffix context: weight 20\n * - Neighbor text: weight 20\n */\nfunction scoreCandidate(candidate: Element, anchor: AnchorData): number {\n let score = 0;\n let totalWeight = 0;\n\n // Truncate to avoid O(n*m) explosion on huge text nodes\n const candidateText = (candidate.textContent?.trim() ?? \"\").slice(0, 500);\n\n // --- Text snippet (weight 40 — most important for reordered elements) ---\n if (anchor.textSnippet) {\n totalWeight += 40;\n score += fuzzyIncludes(candidateText, anchor.textSnippet, 0.5) * 40;\n }\n\n // --- Fingerprint (weight 20) ---\n if (anchor.fingerprint) {\n totalWeight += 20;\n score += scoreFingerprint(candidate, anchor.fingerprint) * 20;\n }\n\n // --- Prefix/suffix context (weight 20) ---\n if (anchor.textPrefix || anchor.textSuffix) {\n totalWeight += 20;\n let contextScore = 0;\n let contextParts = 0;\n\n if (anchor.textPrefix) {\n const prevText = adjacentText(candidate, \"before\");\n contextScore += prevText ? similarity(prevText, anchor.textPrefix) : 0;\n contextParts++;\n }\n\n if (anchor.textSuffix) {\n const nextText = adjacentText(candidate, \"after\");\n contextScore += nextText ? similarity(nextText, anchor.textSuffix) : 0;\n contextParts++;\n }\n\n if (contextParts > 0) {\n score += (contextScore / contextParts) * 20;\n }\n }\n\n // --- Neighbor text (weight 20) ---\n if (anchor.neighborText) {\n totalWeight += 20;\n const candidateNeighbor = neighborText(candidate);\n score += candidateNeighbor ? similarity(candidateNeighbor, anchor.neighborText) * 20 : 0;\n }\n\n return totalWeight > 0 ? score / totalWeight : 0;\n}\n\n/**\n * Resolve an annotation's position on the page.\n * Converts stored percentage-based rect back to absolute coordinates\n * using the current bounding box of the resolved anchor element.\n */\nexport function resolveAnnotation(anchor: AnchorData, rect: RectData): ResolvedAnnotation | null {\n const resolution = resolveAnchor(anchor);\n\n if (!resolution) return null;\n\n const bounds = resolution.element.getBoundingClientRect();\n const absoluteRect = new DOMRect(\n bounds.x + rect.xPct * bounds.width,\n bounds.y + rect.yPct * bounds.height,\n rect.wPct * bounds.width,\n rect.hPct * bounds.height,\n );\n\n return {\n element: resolution.element,\n rect: absoluteRect,\n confidence: resolution.confidence,\n strategy: resolution.strategy,\n };\n}\n","import type { AnchorData, FeedbackResponse, RectData } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { resolveAnnotation } from \"./dom/resolver.js\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport { getTypeColor, type ThemeColors } from \"./styles/theme.js\";\nimport type { Tooltip } from \"./tooltip.js\";\n\ntype Annotation = FeedbackResponse[\"annotations\"][number];\n\nfunction toAnchorData(a: Annotation): AnchorData {\n return {\n cssSelector: a.cssSelector,\n xpath: a.xpath,\n textSnippet: a.textSnippet,\n elementTag: a.elementTag,\n elementId: a.elementId ?? undefined,\n textPrefix: a.textPrefix,\n textSuffix: a.textSuffix,\n fingerprint: a.fingerprint,\n neighborText: a.neighborText,\n anchorKey: a.anchorKey ?? null,\n };\n}\n\nfunction toRectData(a: Annotation): RectData {\n return { xPct: a.xPct, yPct: a.yPct, wPct: a.wPct, hPct: a.hPct };\n}\n\n/** Half of the 26px marker diameter — used for centering on anchor corner. */\nconst MARKER_OFFSET = 13;\n\n/** Convert a resolved rect to document-absolute marker position. */\nfunction markerPosition(rect: DOMRect): { top: number; left: number } {\n return {\n top: rect.top + window.scrollY - MARKER_OFFSET,\n left: rect.right + window.scrollX - MARKER_OFFSET,\n };\n}\n\ninterface MarkerEntry {\n feedback: FeedbackResponse;\n elements: HTMLElement[];\n baseTop: number;\n baseLeft: number;\n}\n\ninterface Cluster {\n entries: MarkerEntry[];\n elementIndices: number[];\n expanded: boolean;\n}\n\n/** Get the i-th marker element from a cluster. */\nfunction clusterMarker(cluster: Cluster, i: number): HTMLElement | undefined {\n const entry = cluster.entries[i];\n const elIdx = cluster.elementIndices[i];\n if (!entry || elIdx === undefined) return undefined;\n return entry.elements[elIdx];\n}\n\nconst HIGHLIGHT_FADE = 300;\nconst REPOSITION_DEBOUNCE = 200;\nconst LOW_CONFIDENCE_THRESHOLD = 0.7;\nconst CLUSTER_DISTANCE = 28;\nconst FAN_SPACING = 32;\n\n/**\n * Numbered markers on the page for each feedback annotation.\n *\n * Cluster system: click-to-expand (same pattern as Google Maps / Spiderfier).\n * Hover is only used for tooltip/scale on individual markers — never for expansion.\n */\nexport class MarkerManager {\n private container: HTMLElement;\n private entries: MarkerEntry[] = [];\n private highlightElements: HTMLElement[] = [];\n private pinnedFeedback: FeedbackResponse | null = null;\n private onDocumentClick: ((e: MouseEvent) => void) | null = null;\n private repositionTimer: number | null = null;\n private mutationObserver: MutationObserver | null = null;\n private scrollHandler: (() => void) | null = null;\n private resizeHandler: (() => void) | null = null;\n private anchorCache = new Map<string, WeakRef<Element>>();\n private clusters: Cluster[] = [];\n private onDocumentClickForClusters: ((e: MouseEvent) => void) | null = null;\n\n get count(): number {\n return this.entries.length;\n }\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly tooltip: Tooltip,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly t: TFunction,\n ) {\n this.container = el(\"div\", {\n style: `position:absolute;top:0;left:0;pointer-events:none;z-index:${Z_INDEX_MAX - 1};`,\n });\n this.container.id = \"siteping-markers\";\n document.body.appendChild(this.container);\n\n this.bus.on(\"annotations:toggle\", (visible) => {\n this.container.style.display = visible ? \"block\" : \"none\";\n });\n\n this.resizeHandler = () => this.scheduleReposition();\n window.addEventListener(\"resize\", this.resizeHandler, { passive: true });\n\n this.scrollHandler = () => this.scheduleReposition();\n window.addEventListener(\"scroll\", this.scrollHandler, { passive: true, capture: true });\n\n // Re-resolve after DOM changes (SPA, lazy-load).\n // Filter out widget-owned mutations and skip batches with only irrelevant\n // changes. Filtering short-circuits at the first non-widget mutation, so\n // even large batches stop after one DOM walk.\n //\n // The filter is applied unconditionally — earlier versions had a >20-batch\n // fast-path that skipped filtering, but that lets reposition self-trigger\n // when `repositionAll` re-renders the pinned highlight (showHighlight\n // appends N elements to `this.container`); a host page churning lots of\n // DOM (infinite scroll) would then loop at the 200ms debounce interval.\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasRelevantMutation = false;\n for (const m of mutations) {\n if (this.container.contains(m.target) || this.tooltip.contains(m.target)) continue;\n hasRelevantMutation = true;\n break;\n }\n if (hasRelevantMutation) this.scheduleReposition();\n });\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: false,\n characterData: false,\n });\n\n this.onDocumentClickForClusters = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.collapseAllClusters();\n };\n document.addEventListener(\"click\", this.onDocumentClickForClusters);\n }\n\n private scheduleReposition(): void {\n if (this.repositionTimer) return;\n if (\"requestIdleCallback\" in window) {\n this.repositionTimer = window.requestIdleCallback(\n () => {\n this.repositionTimer = null;\n this.repositionAll();\n },\n { timeout: REPOSITION_DEBOUNCE + 100 },\n );\n } else {\n this.repositionTimer = +setTimeout(() => {\n this.repositionTimer = null;\n this.repositionAll();\n }, REPOSITION_DEBOUNCE);\n }\n }\n\n private repositionAll(): void {\n // Build set of valid keys to prune stale cache entries afterwards.\n const validKeys = new Set<string>();\n\n for (const entry of this.entries) {\n for (let i = 0; i < entry.feedback.annotations.length; i++) {\n const markerEl = entry.elements[i];\n if (!markerEl) continue;\n\n const annotation = entry.feedback.annotations[i];\n if (!annotation) continue;\n const cacheKey = `${entry.feedback.id}:${i}`;\n validKeys.add(cacheKey);\n\n // Try cached element first to avoid full resolution chain.\n const cachedRef = this.anchorCache.get(cacheKey);\n const cachedEl = cachedRef?.deref();\n let resolved: ReturnType<typeof resolveAnnotation>;\n\n if (cachedEl?.isConnected) {\n const anchorRect = cachedEl.getBoundingClientRect();\n const r = toRectData(annotation);\n resolved = {\n element: cachedEl,\n rect: new DOMRect(\n anchorRect.left + r.xPct * anchorRect.width,\n anchorRect.top + r.yPct * anchorRect.height,\n r.wPct * anchorRect.width,\n r.hPct * anchorRect.height,\n ),\n confidence: 1,\n strategy: \"css\",\n };\n } else {\n resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (resolved?.element) {\n this.anchorCache.set(cacheKey, new WeakRef(resolved.element));\n }\n }\n\n if (!resolved) {\n markerEl.style.display = \"none\";\n continue;\n }\n\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n markerEl.style.display = \"flex\";\n this.applyConfidenceStyle(markerEl, resolved.confidence, entry.feedback);\n }\n }\n\n // Prune cache keys from deleted feedbacks to prevent memory leak.\n for (const key of this.anchorCache.keys()) {\n if (!validKeys.has(key)) this.anchorCache.delete(key);\n }\n\n this.applyClusterPositions();\n\n // Re-render the pinned highlight rectangle so it tracks the layout after\n // resize / SPA mutation. Marker dots reposition above; without this,\n // the highlight rect keeps its old pixel position and visibly drifts\n // away from the underlying content.\n if (this.pinnedFeedback) {\n this.showHighlight(this.pinnedFeedback);\n }\n }\n\n private applyClusterPositions(): void {\n for (const cluster of this.clusters) {\n if (cluster.expanded) {\n this.applyFanPositions(cluster);\n } else {\n this.applyStackPositions(cluster);\n }\n }\n }\n\n render(feedbacks: FeedbackResponse[]): void {\n this.clear();\n feedbacks.forEach((feedback, i) => {\n const entry = this.buildEntry(feedback, i + 1);\n this.entries.push(entry);\n });\n this.buildClusters();\n }\n\n addFeedback(feedback: FeedbackResponse, index: number): void {\n const entry = this.buildEntry(feedback, index);\n for (const m of entry.elements) {\n m.style.animation = \"sp-marker-in 0.35s cubic-bezier(0.34,1.56,0.64,1) both\";\n }\n this.entries.push(entry);\n this.buildClusters();\n }\n\n private buildEntry(feedback: FeedbackResponse, index: number): MarkerEntry {\n const entry: MarkerEntry = { feedback, elements: [], baseTop: 0, baseLeft: 0 };\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n const pos = markerPosition(resolved.rect);\n entry.baseTop = pos.top;\n entry.baseLeft = pos.left;\n const marker = this.createMarker(index, feedback, pos);\n this.applyConfidenceStyle(marker, resolved.confidence, feedback);\n this.container.appendChild(marker);\n entry.elements.push(marker);\n }\n return entry;\n }\n\n private buildClusters(): void {\n for (const badge of this.container.querySelectorAll<HTMLElement>(\".sp-cluster-badge\")) {\n badge.remove();\n }\n\n const allItems: { entry: MarkerEntry; elIdx: number }[] = [];\n for (const entry of this.entries) {\n for (let i = 0; i < entry.elements.length; i++) {\n allItems.push({ entry, elIdx: i });\n }\n }\n\n const used = new Set<number>();\n this.clusters = [];\n\n for (let i = 0; i < allItems.length; i++) {\n if (used.has(i)) continue;\n const itemI = allItems[i];\n if (!itemI) continue;\n const cluster: Cluster = {\n entries: [itemI.entry],\n elementIndices: [itemI.elIdx],\n expanded: false,\n };\n used.add(i);\n\n for (let j = i + 1; j < allItems.length; j++) {\n if (used.has(j)) continue;\n const a = itemI.entry;\n const itemJ = allItems[j];\n if (!itemJ) continue;\n const b = itemJ.entry;\n const dist = Math.sqrt((a.baseLeft - b.baseLeft) ** 2 + (a.baseTop - b.baseTop) ** 2);\n if (dist < CLUSTER_DISTANCE) {\n cluster.entries.push(b);\n cluster.elementIndices.push(itemJ.elIdx);\n used.add(j);\n }\n }\n\n this.clusters.push(cluster);\n }\n\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n this.applyStackPositions(cluster);\n this.addClusterBadge(cluster);\n }\n }\n\n private applyStackPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const isSolo = cluster.entries.length <= 1;\n for (let i = 0; i < cluster.entries.length; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop + (isSolo ? 0 : i * 3)}px`;\n m.style.left = `${baseLeft + (isSolo ? 0 : i * 3)}px`;\n m.style.zIndex = String(i + 1);\n }\n }\n\n private applyFanPositions(cluster: Cluster): void {\n const first = cluster.entries[0];\n if (!first) return;\n const { baseTop, baseLeft } = first;\n const count = cluster.entries.length;\n const totalWidth = (count - 1) * FAN_SPACING;\n const startLeft = baseLeft - totalWidth / 2;\n\n for (let i = 0; i < count; i++) {\n const m = clusterMarker(cluster, i);\n if (!m) continue;\n m.style.top = `${baseTop}px`;\n m.style.left = `${startLeft + i * FAN_SPACING}px`;\n m.style.zIndex = String(10 + i);\n }\n }\n\n private addClusterBadge(cluster: Cluster): void {\n const topMarker = clusterMarker(cluster, cluster.entries.length - 1);\n if (!topMarker) return;\n const badge = el(\"div\", {\n class: \"sp-cluster-badge\",\n style: `\n position:absolute;top:-6px;right:-6px;\n min-width:16px;height:16px;padding:0 4px;\n border-radius:9999px;\n background:${this.colors.accent};color:#fff;\n font-size:10px;font-weight:700;\n display:flex;align-items:center;justify-content:center;\n border:1.5px solid #fff;\n pointer-events:none;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n line-height:1;\n `,\n });\n setText(badge, String(cluster.entries.length));\n topMarker.appendChild(badge);\n }\n\n private setBadgesVisible(cluster: Cluster, visible: boolean): void {\n for (let i = 0; i < cluster.entries.length; i++) {\n const badge = clusterMarker(cluster, i)?.querySelector(\".sp-cluster-badge\") as HTMLElement | null;\n if (badge) badge.style.display = visible ? \"flex\" : \"none\";\n }\n }\n\n private findCluster(marker: HTMLElement): Cluster | null {\n for (const cluster of this.clusters) {\n if (cluster.entries.length <= 1) continue;\n for (let i = 0; i < cluster.entries.length; i++) {\n if (clusterMarker(cluster, i) === marker) return cluster;\n }\n }\n return null;\n }\n\n private handleClusterClick(marker: HTMLElement, e: MouseEvent): boolean {\n const cluster = this.findCluster(marker);\n if (!cluster) return false;\n if (!cluster.expanded) {\n e.stopPropagation();\n this.collapseAllClusters();\n cluster.expanded = true;\n this.applyFanPositions(cluster);\n this.setBadgesVisible(cluster, false);\n return true;\n }\n return false;\n }\n\n private collapseCluster(cluster: Cluster): void {\n if (!cluster.expanded) return;\n cluster.expanded = false;\n this.applyStackPositions(cluster);\n this.setBadgesVisible(cluster, true);\n }\n\n private collapseAllClusters(): void {\n for (const cluster of this.clusters) {\n this.collapseCluster(cluster);\n }\n }\n\n private applyConfidenceStyle(marker: HTMLElement, confidence: number, feedback: FeedbackResponse): void {\n const isResolved = feedback.status === \"resolved\";\n if (confidence < LOW_CONFIDENCE_THRESHOLD && !isResolved) {\n marker.style.borderStyle = \"dashed\";\n marker.style.opacity = \"0.7\";\n marker.title = this.t(\"marker.approximate\").replace(\"{confidence}\", String(Math.round(confidence * 100)));\n } else {\n marker.style.borderStyle = \"solid\";\n marker.style.opacity = \"1\";\n marker.title = \"\";\n }\n }\n\n private createMarker(number: number, feedback: FeedbackResponse, pos: { top: number; left: number }): HTMLElement {\n const typeColor = getTypeColor(feedback.type, this.colors);\n const isResolved = feedback.status === \"resolved\";\n\n const marker = el(\"div\", {\n style: `\n position:absolute;\n top:${pos.top}px;\n left:${pos.left}px;\n width:26px;height:26px;\n border-radius:50%;\n background:${isResolved ? \"rgba(241,245,249,0.9)\" : \"rgba(255,255,255,0.92)\"};\n border:2px solid ${isResolved ? \"#cbd5e1\" : typeColor};\n display:flex;align-items:center;justify-content:center;\n font-family:\"Inter\",system-ui,-apple-system,sans-serif;\n font-size:11px;font-weight:700;\n color:${isResolved ? \"#94a3b8\" : typeColor};\n cursor:pointer;pointer-events:auto;\n box-shadow:${isResolved ? \"0 2px 8px rgba(0,0,0,0.06)\" : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`};\n transition:top 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.15s ease, box-shadow 0.15s ease;\n user-select:none;\n -webkit-font-smoothing:antialiased;\n `,\n });\n marker.dataset.feedbackId = feedback.id;\n marker.setAttribute(\"tabindex\", \"0\");\n marker.setAttribute(\"role\", \"button\");\n const truncatedMessage = feedback.message.length > 60 ? `${feedback.message.slice(0, 60)}...` : feedback.message;\n const ariaLabel = this.t(\"marker.aria\")\n .replace(\"{number}\", String(number))\n .replace(\"{type}\", getTypeLabel(feedback.type, this.t))\n .replace(\"{message}\", truncatedMessage);\n marker.setAttribute(\"aria-label\", ariaLabel);\n marker.setAttribute(\"aria-describedby\", this.tooltip.tooltipId);\n setText(marker, isResolved ? \"\\u2713\" : String(number));\n\n marker.addEventListener(\"mouseenter\", () => {\n marker.style.transform = \"scale(1.2)\";\n marker.style.boxShadow = isResolved\n ? \"0 4px 16px rgba(0,0,0,0.1)\"\n : `0 4px 20px ${typeColor}35, 0 4px 12px rgba(0,0,0,0.08)`;\n this.tooltip.show(feedback, marker.getBoundingClientRect());\n if (!this.pinnedFeedback) this.showHighlight(feedback);\n });\n\n marker.addEventListener(\"mouseleave\", () => {\n marker.style.transform = \"scale(1)\";\n marker.style.boxShadow = isResolved\n ? \"0 2px 8px rgba(0,0,0,0.06)\"\n : `0 2px 12px ${typeColor}25, 0 2px 6px rgba(0,0,0,0.06)`;\n this.tooltip.scheduleHide();\n if (!this.pinnedFeedback) this.clearHighlight();\n });\n\n const activateMarker = (e: MouseEvent | KeyboardEvent) => {\n if (e instanceof MouseEvent && this.handleClusterClick(marker, e)) return;\n this.pinHighlight(feedback);\n this.bus.emit(\"panel:toggle\", true);\n marker.dispatchEvent(\n new CustomEvent(\"sp-marker-click\", {\n detail: { feedbackId: feedback.id },\n bubbles: true,\n }),\n );\n };\n\n marker.addEventListener(\"click\", (e) => activateMarker(e));\n marker.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n activateMarker(e);\n }\n });\n\n return marker;\n }\n\n highlight(feedbackId: string): void {\n for (const entry of this.entries) {\n if (entry.feedback.id === feedbackId) {\n for (const markerEl of entry.elements) {\n markerEl.style.animation = \"sp-pulse-ring 0.7s ease-out\";\n markerEl.addEventListener(\n \"animationend\",\n () => {\n markerEl.style.animation = \"\";\n },\n { once: true },\n );\n }\n }\n }\n }\n\n showHighlight(feedback: FeedbackResponse): void {\n this.removeHighlightElements();\n for (const annotation of feedback.annotations) {\n const resolved = resolveAnnotation(toAnchorData(annotation), toRectData(annotation));\n if (!resolved) continue;\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const rect = resolved.rect;\n const highlight = el(\"div\", {\n style: `\n position:absolute;\n top:${rect.top + window.scrollY}px;\n left:${rect.left + window.scrollX}px;\n width:${rect.width}px;height:${rect.height}px;\n border:2px solid ${typeColor};\n background:${typeColor}0c;\n border-radius:8px;\n pointer-events:none;z-index:-1;\n opacity:0;\n box-shadow:0 0 16px ${typeColor}20;\n transition:opacity ${HIGHLIGHT_FADE}ms ease;\n `,\n });\n this.container.appendChild(highlight);\n this.highlightElements.push(highlight);\n void highlight.offsetHeight; // Force reflow for CSS transition\n highlight.style.opacity = \"1\";\n }\n }\n\n pinHighlight(feedback: FeedbackResponse): void {\n this.unpinHighlight();\n this.showHighlight(feedback);\n this.pinnedFeedback = feedback;\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.container.contains(e.target as Node)) return;\n this.unpinHighlight();\n };\n document.addEventListener(\"click\", this.onDocumentClick, { capture: true });\n }\n\n private unpinHighlight(): void {\n if (this.onDocumentClick) {\n document.removeEventListener(\"click\", this.onDocumentClick, { capture: true });\n this.onDocumentClick = null;\n }\n this.pinnedFeedback = null;\n this.clearHighlight();\n }\n\n private clearHighlight(): void {\n for (const h of this.highlightElements) {\n h.style.opacity = \"0\";\n setTimeout(() => h.remove(), HIGHLIGHT_FADE);\n }\n this.highlightElements = [];\n }\n\n private removeHighlightElements(): void {\n for (const h of this.highlightElements) h.remove();\n this.highlightElements = [];\n }\n\n clear(): void {\n this.unpinHighlight();\n this.container.replaceChildren();\n this.entries = [];\n this.clusters = [];\n this.anchorCache.clear();\n }\n\n destroy(): void {\n this.unpinHighlight();\n if (this.repositionTimer) {\n if (\"cancelIdleCallback\" in window) {\n window.cancelIdleCallback(this.repositionTimer);\n }\n clearTimeout(this.repositionTimer);\n }\n if (this.resizeHandler) window.removeEventListener(\"resize\", this.resizeHandler);\n if (this.scrollHandler) window.removeEventListener(\"scroll\", this.scrollHandler, { capture: true });\n if (this.onDocumentClickForClusters) document.removeEventListener(\"click\", this.onDocumentClickForClusters);\n this.mutationObserver?.disconnect();\n this.container.remove();\n }\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_EXPORT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" y1=\"15\" x2=\"12\" y2=\"3\"/></svg>`;\n\nconst ICON_CSV = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/><line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\"/><line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\"/><line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\"/></svg>`;\n\nconst ICON_JSON = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M8 3H6a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2 2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h2\"/><path d=\"M16 3h2a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2 2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// i18n\n// ---------------------------------------------------------------------------\n\nexport const EXPORT_I18N_EN = {\n \"export.label\": \"Export\",\n \"export.csv\": \"Export CSV\",\n \"export.json\": \"Export JSON\",\n};\n\nexport const EXPORT_I18N_FR = {\n \"export.label\": \"Exporter\",\n \"export.csv\": \"Exporter CSV\",\n \"export.json\": \"Exporter JSON\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const EXPORT_CSS = `\n /* ============================\n Export Button & Menu\n ============================ */\n\n .sp-export-btn {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .sp-export-btn svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-export-btn:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-export-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-export-menu {\n position: absolute;\n top: calc(100% + 6px);\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-lg);\n z-index: 10;\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n transition: opacity 0.15s ease, transform 0.15s ease;\n pointer-events: none;\n }\n\n .sp-export-menu--open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .sp-export-option {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 16px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n text-align: left;\n }\n\n .sp-export-option:hover,\n .sp-export-option:focus-visible {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n .sp-export-option-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .sp-export-option-icon svg {\n width: 16px;\n height: 16px;\n }\n\n .sp-export-option-label {\n flex: 1;\n }\n\n @media (forced-colors: active) {\n .sp-export-btn,\n .sp-export-option,\n .sp-export-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-export-btn:focus-visible,\n .sp-export-option:focus-visible {\n outline: 3px solid Highlight !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// CSV / JSON conversion\n// ---------------------------------------------------------------------------\n\nconst CSV_COLUMNS = [\n \"id\",\n \"type\",\n \"status\",\n \"message\",\n \"url\",\n \"authorName\",\n \"authorEmail\",\n \"createdAt\",\n \"resolvedAt\",\n \"viewport\",\n] as const;\n\n/** Escape a value for CSV: wrap in double-quotes if it contains commas, newlines, or quotes. */\nfunction escapeCsvField(value: string): string {\n if (value.includes('\"') || value.includes(\",\") || value.includes(\"\\n\") || value.includes(\"\\r\")) {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n }\n return value;\n}\n\n/** Convert feedbacks to CSV string */\nexport function feedbacksToCsv(feedbacks: FeedbackResponse[]): string {\n const header = CSV_COLUMNS.join(\",\");\n const rows = feedbacks.map((fb) =>\n CSV_COLUMNS.map((col) => {\n const raw = fb[col];\n return escapeCsvField(raw == null ? \"\" : String(raw));\n }).join(\",\"),\n );\n return [header, ...rows].join(\"\\n\");\n}\n\n/** Convert feedbacks to formatted JSON string */\nexport function feedbacksToJson(feedbacks: FeedbackResponse[]): string {\n return JSON.stringify(feedbacks, null, 2);\n}\n\n// ---------------------------------------------------------------------------\n// Download helper\n// ---------------------------------------------------------------------------\n\n/** Trigger browser download of a string as file */\nexport function downloadFile(content: string, filename: string, mimeType: string): void {\n const blob = new Blob([content], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = filename;\n anchor.style.display = \"none\";\n document.body.appendChild(anchor);\n anchor.click();\n // Clean up after a tick to ensure the download starts\n requestAnimationFrame(() => {\n URL.revokeObjectURL(url);\n anchor.remove();\n });\n}\n\n// ---------------------------------------------------------------------------\n// ExportButton component\n// ---------------------------------------------------------------------------\n\nexport class ExportButton {\n readonly element: HTMLElement;\n\n private menu: HTMLElement;\n private isOpen = false;\n private onDocumentClick: (e: MouseEvent) => void;\n\n constructor(\n _colors: ThemeColors,\n private readonly getFeedbacks: () => FeedbackResponse[],\n ) {\n // Wrapper for relative positioning of the menu\n this.element = el(\"div\", { style: \"position: relative; display: inline-flex;\" });\n\n // Trigger button — matches .sp-btn-delete-all pill style\n const btn = document.createElement(\"button\");\n btn.className = \"sp-export-btn\";\n btn.setAttribute(\"aria-haspopup\", \"true\");\n btn.setAttribute(\"aria-expanded\", \"false\");\n btn.appendChild(parseSvg(ICON_EXPORT));\n const label = document.createElement(\"span\");\n setText(label, EXPORT_I18N_EN[\"export.label\"]);\n btn.appendChild(label);\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggle();\n });\n\n // Dropdown menu\n this.menu = el(\"div\", { class: \"sp-export-menu\" });\n this.menu.setAttribute(\"role\", \"menu\");\n\n // CSV option\n const csvOption = this.createOption(ICON_CSV, EXPORT_I18N_EN[\"export.csv\"], () => {\n this.exportAs(\"csv\");\n });\n\n // JSON option\n const jsonOption = this.createOption(ICON_JSON, EXPORT_I18N_EN[\"export.json\"], () => {\n this.exportAs(\"json\");\n });\n\n this.menu.appendChild(csvOption);\n this.menu.appendChild(jsonOption);\n\n this.element.appendChild(btn);\n this.element.appendChild(this.menu);\n\n // Close on outside click\n this.onDocumentClick = (e: MouseEvent) => {\n if (this.isOpen && !this.element.contains(e.target as Node)) {\n this.close();\n }\n };\n document.addEventListener(\"click\", this.onDocumentClick, true);\n }\n\n /** Update the button label (used for i18n switching) */\n setLabels(labels: typeof EXPORT_I18N_EN): void {\n const btn = this.element.querySelector<HTMLElement>(\".sp-export-btn\");\n if (btn) {\n const span = btn.querySelector(\"span\");\n if (span) setText(span, labels[\"export.label\"]);\n }\n\n const options = this.menu.querySelectorAll<HTMLElement>(\".sp-export-option-label\");\n if (options[0]) setText(options[0], labels[\"export.csv\"]);\n if (options[1]) setText(options[1], labels[\"export.json\"]);\n }\n\n private createOption(iconSvg: string, labelText: string, onClick: () => void): HTMLButtonElement {\n const option = document.createElement(\"button\");\n option.className = \"sp-export-option\";\n option.setAttribute(\"role\", \"menuitem\");\n\n const iconWrap = el(\"span\", { class: \"sp-export-option-icon\" });\n iconWrap.appendChild(parseSvg(iconSvg));\n\n const labelEl = el(\"span\", { class: \"sp-export-option-label\" });\n setText(labelEl, labelText);\n\n option.appendChild(iconWrap);\n option.appendChild(labelEl);\n\n option.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n onClick();\n this.close();\n });\n\n return option;\n }\n\n private toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n private open(): void {\n this.isOpen = true;\n this.menu.classList.add(\"sp-export-menu--open\");\n const btn = this.element.querySelector<HTMLButtonElement>(\".sp-export-btn\");\n btn?.setAttribute(\"aria-expanded\", \"true\");\n }\n\n private close(): void {\n this.isOpen = false;\n this.menu.classList.remove(\"sp-export-menu--open\");\n const btn = this.element.querySelector<HTMLButtonElement>(\".sp-export-btn\");\n btn?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n private exportAs(format: \"csv\" | \"json\"): void {\n const feedbacks = this.getFeedbacks();\n if (feedbacks.length === 0) return;\n\n const projectName = feedbacks[0]?.projectName ?? \"feedbacks\";\n const date = new Date().toISOString().slice(0, 10);\n const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\n if (format === \"csv\") {\n const content = feedbacksToCsv(feedbacks);\n downloadFile(content, `feedbacks-${safeName}-${date}.csv`, \"text/csv;charset=utf-8\");\n } else {\n const content = feedbacksToJson(feedbacks);\n downloadFile(content, `feedbacks-${safeName}-${date}.json`, \"application/json;charset=utf-8\");\n }\n }\n\n destroy(): void {\n document.removeEventListener(\"click\", this.onDocumentClick, true);\n this.element.remove();\n }\n}\n","/**\n * Bulk Actions system for the feedback panel.\n *\n * Allows multi-select on feedback cards with a floating action bar\n * for batch resolve/delete operations. Glassmorphism design with\n * spring animations and smooth transitions.\n */\n\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_CHECKBOX = `<svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"4\" stroke=\"currentColor\" stroke-width=\"2\"/></svg>`;\n\nexport const ICON_CHECKBOX_CHECKED = `<svg viewBox=\"0 0 18 18\" fill=\"none\" aria-hidden=\"true\"><rect x=\"1\" y=\"1\" width=\"16\" height=\"16\" rx=\"4\" fill=\"url(#sp-cb-grad)\" stroke=\"none\"/><polyline points=\"5 9 8 12 13 6\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><defs><linearGradient id=\"sp-cb-grad\" x1=\"0\" y1=\"0\" x2=\"18\" y2=\"18\" gradientUnits=\"userSpaceOnUse\"><stop offset=\"0%\" stop-color=\"var(--sp-accent)\"/><stop offset=\"100%\" stop-color=\"var(--sp-accent-dark)\"/></linearGradient></defs></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18N\n// ---------------------------------------------------------------------------\n\nexport const BULK_I18N_EN = {\n \"bulk.selectAll\": \"Select all\",\n \"bulk.selected\": \"{count} selected\",\n \"bulk.resolve\": \"Resolve\",\n \"bulk.delete\": \"Delete\",\n \"bulk.deselect\": \"Deselect\",\n};\n\nexport const BULK_I18N_FR = {\n \"bulk.selectAll\": \"Tout sélectionner\",\n \"bulk.selected\": \"{count} sélectionné(s)\",\n \"bulk.resolve\": \"Résoudre\",\n \"bulk.delete\": \"Supprimer\",\n \"bulk.deselect\": \"Désélectionner\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const BULK_CSS = `\n /* ============================\n Bulk Checkbox\n ============================ */\n\n .sp-bulk-checkbox {\n position: relative;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n cursor: pointer;\n border-radius: 4px;\n color: var(--sp-border);\n opacity: 0;\n transition: opacity 0.15s ease, color 0.15s ease, transform 0.15s ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n .sp-bulk-checkbox svg {\n width: 16px;\n height: 16px;\n display: block;\n }\n\n .sp-bulk-checkbox:hover {\n color: var(--sp-accent);\n transform: scale(1.1);\n }\n\n .sp-bulk-checkbox--checked {\n color: var(--sp-accent);\n opacity: 1 !important;\n filter: drop-shadow(0 0 4px var(--sp-accent-glow));\n }\n\n /* Show checkboxes when hovering a card */\n .sp-card:hover .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* When any card has selection, show ALL checkboxes */\n .sp-list--has-selection .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* ============================\n Card Selected State\n ============================ */\n\n .sp-card--selected {\n border-left: 3px solid var(--sp-accent) !important;\n background: var(--sp-accent-light) !important;\n }\n\n .sp-card--selected:hover {\n background: var(--sp-accent-light) !important;\n }\n\n /* ============================\n Select All Bar\n ============================ */\n\n .sp-bulk-select-all {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n margin-bottom: 4px;\n border-radius: var(--sp-radius);\n background: transparent;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.2s ease, background 0.2s ease;\n user-select: none;\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n }\n\n .sp-bulk-select-all:hover {\n background: var(--sp-bg-hover);\n }\n\n /* Show select-all on list hover or when selections exist */\n .sp-list:hover .sp-bulk-select-all,\n .sp-list--has-selection .sp-bulk-select-all {\n opacity: 1;\n }\n\n .sp-bulk-select-all .sp-bulk-checkbox {\n opacity: 1;\n }\n\n /* ============================\n Floating Action Bar\n ============================ */\n\n @keyframes sp-bulk-bar-in {\n from {\n transform: translateY(100%) scale(0.95);\n opacity: 0;\n }\n to {\n transform: translateY(0) scale(1);\n opacity: 1;\n }\n }\n\n @keyframes sp-bulk-bar-out {\n from {\n transform: translateY(0) scale(1);\n opacity: 1;\n }\n to {\n transform: translateY(100%) scale(0.95);\n opacity: 0;\n }\n }\n\n .sp-bulk-bar {\n position: absolute;\n bottom: 16px;\n left: 16px;\n right: 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 12px 16px;\n border-radius: 16px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n z-index: 10;\n pointer-events: none;\n opacity: 0;\n transform: translateY(100%) scale(0.95);\n transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),\n opacity 0.25s ease;\n font-family: var(--sp-font);\n }\n\n .sp-bulk-bar--visible {\n pointer-events: auto;\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n\n .sp-bulk-bar-count {\n font-size: 13px;\n font-weight: 600;\n color: var(--sp-text);\n white-space: nowrap;\n letter-spacing: -0.01em;\n }\n\n .sp-bulk-bar-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-bulk-btn-resolve,\n .sp-bulk-btn-delete {\n padding: 7px 14px;\n border-radius: var(--sp-radius-full);\n border: 1.5px solid transparent;\n background: transparent;\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 5px;\n transition: all 0.2s ease;\n white-space: nowrap;\n }\n\n .sp-bulk-btn-resolve {\n color: #22c55e;\n border-color: #22c55e;\n }\n\n .sp-bulk-btn-resolve:hover {\n background: rgba(34, 197, 94, 0.1);\n box-shadow: 0 0 12px rgba(34, 197, 94, 0.15);\n }\n\n .sp-bulk-btn-resolve:active {\n transform: scale(0.96);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-delete {\n color: #ef4444;\n border-color: #ef4444;\n }\n\n .sp-bulk-btn-delete:hover {\n background: rgba(239, 68, 68, 0.1);\n box-shadow: 0 0 12px rgba(239, 68, 68, 0.15);\n }\n\n .sp-bulk-btn-delete:active {\n transform: scale(0.96);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-resolve:disabled,\n .sp-bulk-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-bulk-btn-deselect {\n width: 28px;\n height: 28px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n flex-shrink: 0;\n padding: 0;\n }\n\n .sp-bulk-btn-deselect:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n border-color: var(--sp-text-tertiary);\n }\n\n .sp-bulk-btn-deselect:active {\n transform: scale(0.92);\n transition-duration: 0.1s;\n }\n\n .sp-bulk-btn-deselect svg {\n width: 12px;\n height: 12px;\n }\n\n /* Spinner inside bulk bar buttons */\n .sp-bulk-btn-resolve .sp-spinner,\n .sp-bulk-btn-delete .sp-spinner {\n width: 14px;\n height: 14px;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-bulk-checkbox,\n .sp-bulk-btn-resolve,\n .sp-bulk-btn-delete,\n .sp-bulk-btn-deselect,\n .sp-bulk-bar {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-bulk-checkbox--checked {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-card--selected {\n border-left: 4px solid Highlight !important;\n }\n }\n\n /* ============================\n Reduced Motion\n ============================ */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-bulk-bar {\n transition-duration: 0.01ms !important;\n }\n\n .sp-bulk-checkbox {\n transition-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface BulkActionCallbacks {\n onResolve: (ids: string[]) => Promise<void>;\n onDelete: (ids: string[]) => Promise<void>;\n}\n\n// ---------------------------------------------------------------------------\n// BulkActions Class\n// ---------------------------------------------------------------------------\n\nexport class BulkActions {\n /** The floating action bar element — append to panel root */\n readonly barElement: HTMLElement;\n\n private selected = new Set<string>();\n private checkboxMap = new Map<string, HTMLElement>();\n private countLabel: HTMLElement;\n private resolveBtn: HTMLButtonElement;\n private deleteBtn: HTMLButtonElement;\n private selectAllCheckbox: HTMLElement | null = null;\n private listContainer: HTMLElement | null = null;\n private isProcessing = false;\n private readonly i18n: typeof BULK_I18N_EN;\n\n constructor(\n _colors: ThemeColors,\n private readonly callbacks: BulkActionCallbacks,\n locale?: string,\n ) {\n this.i18n = locale === \"fr\" ? BULK_I18N_FR : BULK_I18N_EN;\n // ----- Build floating bar -----\n this.barElement = el(\"div\", { class: \"sp-bulk-bar\" });\n this.barElement.setAttribute(\"role\", \"toolbar\");\n this.barElement.setAttribute(\"aria-label\", \"Bulk actions\");\n\n // Left: count label\n this.countLabel = el(\"span\", { class: \"sp-bulk-bar-count\" });\n setText(this.countLabel, this.i18n[\"bulk.selected\"].replace(\"{count}\", \"0\"));\n\n // Right: action buttons\n const actions = el(\"div\", { class: \"sp-bulk-bar-actions\" });\n\n this.resolveBtn = document.createElement(\"button\");\n this.resolveBtn.className = \"sp-bulk-btn-resolve\";\n this.resolveBtn.type = \"button\";\n this.resolveBtn.addEventListener(\"click\", () => this.handleResolve());\n\n this.deleteBtn = document.createElement(\"button\");\n this.deleteBtn.className = \"sp-bulk-btn-delete\";\n this.deleteBtn.type = \"button\";\n this.deleteBtn.addEventListener(\"click\", () => this.handleDelete());\n\n const deselectBtn = document.createElement(\"button\");\n deselectBtn.className = \"sp-bulk-btn-deselect\";\n deselectBtn.type = \"button\";\n deselectBtn.setAttribute(\"aria-label\", this.i18n[\"bulk.deselect\"]);\n deselectBtn.appendChild(\n parseSvg(\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n ),\n );\n deselectBtn.addEventListener(\"click\", () => this.deselectAll());\n\n actions.appendChild(this.resolveBtn);\n actions.appendChild(this.deleteBtn);\n actions.appendChild(deselectBtn);\n\n this.barElement.appendChild(this.countLabel);\n this.barElement.appendChild(actions);\n\n // Initial button text\n this.updateButtonLabels();\n }\n\n /** Create a checkbox element for a card. Returns the checkbox wrapper. */\n createCheckbox(feedbackId: string): HTMLElement {\n const wrapper = el(\"div\", { class: \"sp-bulk-checkbox\" });\n wrapper.setAttribute(\"role\", \"checkbox\");\n wrapper.setAttribute(\"aria-checked\", \"false\");\n wrapper.setAttribute(\"tabindex\", \"0\");\n wrapper.setAttribute(\"aria-label\", `Select feedback ${feedbackId}`);\n\n // Render unchecked icon\n wrapper.appendChild(parseSvg(ICON_CHECKBOX));\n\n // Click handler\n wrapper.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggle(feedbackId);\n });\n\n // Keyboard: space/enter to toggle\n wrapper.addEventListener(\"keydown\", (e) => {\n if ((e as KeyboardEvent).key === \" \" || (e as KeyboardEvent).key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n this.toggle(feedbackId);\n }\n });\n\n this.checkboxMap.set(feedbackId, wrapper);\n return wrapper;\n }\n\n /**\n * Create a \"Select all\" bar element.\n * The caller should insert this at the top of the list container.\n */\n createSelectAllBar(feedbackIds: string[], label: string): HTMLElement {\n const wrapper = el(\"div\", { class: \"sp-bulk-select-all\" });\n\n const checkbox = el(\"div\", { class: \"sp-bulk-checkbox\" });\n checkbox.appendChild(parseSvg(ICON_CHECKBOX));\n this.selectAllCheckbox = checkbox;\n\n const labelEl = el(\"span\");\n setText(labelEl, label);\n\n wrapper.appendChild(checkbox);\n wrapper.appendChild(labelEl);\n\n wrapper.addEventListener(\"click\", () => {\n // If all selected, deselect; otherwise select all\n if (this.selected.size === feedbackIds.length && feedbackIds.length > 0) {\n this.deselectAll();\n } else {\n this.selectAll(feedbackIds);\n }\n });\n\n return wrapper;\n }\n\n /** Set the list container reference (for toggling .sp-list--has-selection) */\n setListContainer(container: HTMLElement): void {\n this.listContainer = container;\n }\n\n /** Toggle selection for a feedback */\n toggle(feedbackId: string): void {\n if (this.isProcessing) return;\n\n if (this.selected.has(feedbackId)) {\n this.selected.delete(feedbackId);\n } else {\n this.selected.add(feedbackId);\n }\n this.updateCheckbox(feedbackId);\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n this.updateCardSelectedState(feedbackId);\n }\n\n /** Select all from the given list */\n selectAll(feedbackIds: string[]): void {\n if (this.isProcessing) return;\n\n for (const id of feedbackIds) {\n this.selected.add(id);\n this.updateCheckbox(id);\n this.updateCardSelectedState(id);\n }\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n }\n\n /** Clear all selections */\n deselectAll(): void {\n const prevSelected = [...this.selected];\n this.selected.clear();\n for (const id of prevSelected) {\n this.updateCheckbox(id);\n this.updateCardSelectedState(id);\n }\n this.updateBar();\n this.updateSelectAllCheckbox();\n this.updateListSelectionClass();\n }\n\n /** Get currently selected IDs */\n get selectedIds(): string[] {\n return [...this.selected];\n }\n\n /** Get selection count */\n get count(): number {\n return this.selected.size;\n }\n\n /** Whether any items are selected */\n get hasSelection(): boolean {\n return this.selected.size > 0;\n }\n\n /** Reset state (e.g., after feedbacks reload) */\n reset(): void {\n this.selected.clear();\n this.checkboxMap.clear();\n this.selectAllCheckbox = null;\n\n this.isProcessing = false;\n this.updateBar();\n this.updateListSelectionClass();\n }\n\n /** Destroy / cleanup */\n destroy(): void {\n this.selected.clear();\n this.checkboxMap.clear();\n this.selectAllCheckbox = null;\n\n this.listContainer = null;\n this.barElement.remove();\n }\n\n // -----------------------------------------------------------------------\n // Private\n // -----------------------------------------------------------------------\n\n /** Update the bar visibility and counts */\n private updateBar(): void {\n const count = this.selected.size;\n const visible = count > 0;\n\n this.barElement.classList.toggle(\"sp-bulk-bar--visible\", visible);\n setText(this.countLabel, this.i18n[\"bulk.selected\"].replace(\"{count}\", String(count)));\n this.updateButtonLabels();\n }\n\n private updateButtonLabels(): void {\n const count = this.selected.size;\n\n // Resolve button\n this.resolveBtn.replaceChildren();\n const resolveLabel = document.createElement(\"span\");\n setText(resolveLabel, count > 0 ? `${this.i18n[\"bulk.resolve\"]} ${count}` : this.i18n[\"bulk.resolve\"]);\n this.resolveBtn.appendChild(resolveLabel);\n\n // Delete button\n this.deleteBtn.replaceChildren();\n const deleteLabel = document.createElement(\"span\");\n setText(deleteLabel, count > 0 ? `${this.i18n[\"bulk.delete\"]} ${count}` : this.i18n[\"bulk.delete\"]);\n this.deleteBtn.appendChild(deleteLabel);\n }\n\n private updateCheckbox(feedbackId: string): void {\n const checkbox = this.checkboxMap.get(feedbackId);\n if (!checkbox) return;\n\n const isChecked = this.selected.has(feedbackId);\n checkbox.classList.toggle(\"sp-bulk-checkbox--checked\", isChecked);\n checkbox.setAttribute(\"aria-checked\", String(isChecked));\n\n // Swap SVG icon\n checkbox.replaceChildren();\n checkbox.appendChild(parseSvg(isChecked ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX));\n }\n\n private updateSelectAllCheckbox(): void {\n if (!this.selectAllCheckbox) return;\n\n const allSelected = this.selected.size > 0 && this.selected.size === this.checkboxMap.size;\n this.selectAllCheckbox.classList.toggle(\"sp-bulk-checkbox--checked\", allSelected);\n this.selectAllCheckbox.setAttribute(\"aria-checked\", String(allSelected));\n\n this.selectAllCheckbox.replaceChildren();\n this.selectAllCheckbox.appendChild(parseSvg(allSelected ? ICON_CHECKBOX_CHECKED : ICON_CHECKBOX));\n }\n\n private updateListSelectionClass(): void {\n if (!this.listContainer) return;\n this.listContainer.classList.toggle(\"sp-list--has-selection\", this.selected.size > 0);\n }\n\n private updateCardSelectedState(feedbackId: string): void {\n if (!this.listContainer) return;\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.classList.toggle(\"sp-card--selected\", this.selected.has(feedbackId));\n }\n }\n\n private setButtonLoading(btn: HTMLButtonElement): () => void {\n const snapshot = Array.from(btn.childNodes).map((n) => n.cloneNode(true));\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n return () => {\n btn.replaceChildren(...snapshot);\n btn.disabled = false;\n };\n }\n\n private async handleResolve(): Promise<void> {\n if (this.isProcessing || this.selected.size === 0) return;\n this.isProcessing = true;\n\n const ids = [...this.selected];\n const restoreResolve = this.setButtonLoading(this.resolveBtn);\n this.deleteBtn.disabled = true;\n\n try {\n await this.callbacks.onResolve(ids);\n this.reset();\n } catch {\n restoreResolve();\n this.deleteBtn.disabled = false;\n } finally {\n this.isProcessing = false;\n }\n }\n\n private async handleDelete(): Promise<void> {\n if (this.isProcessing || this.selected.size === 0) return;\n this.isProcessing = true;\n\n const ids = [...this.selected];\n const restoreDelete = this.setButtonLoading(this.deleteBtn);\n this.resolveBtn.disabled = true;\n\n try {\n await this.callbacks.onDelete(ids);\n this.reset();\n } catch {\n restoreDelete();\n this.resolveBtn.disabled = false;\n } finally {\n this.isProcessing = false;\n }\n }\n}\n","/**\n * Detail View for the feedback panel.\n *\n * Slides in from the right (panel-in-panel pattern) when a user clicks\n * a feedback card, showing full details: message, metadata, annotation\n * info, status actions, and a \"Go to annotation\" button.\n *\n * Glassmorphism design — frosted glass surfaces, staggered section\n * animations, accent gradients, premium micro-interactions.\n */\n\nimport type { FeedbackResponse } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_ARROW_LEFT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"19\" y1=\"12\" x2=\"5\" y2=\"12\"/><polyline points=\"12 19 5 12 12 5\"/></svg>`;\n\nexport const ICON_MAP_PIN = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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\nexport const ICON_LINK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`;\n\nexport const ICON_USER = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></svg>`;\n\nexport const ICON_CALENDAR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"/><line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"/><line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\"/><line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\"/></svg>`;\n\nexport const ICON_MONITOR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\"/><line x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\"/><line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\"/></svg>`;\n\nconst ICON_CHECK = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"20 6 9 17 4 12\"/></svg>`;\n\nconst ICON_UNDO = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"1 4 1 10 7 10\"/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"/></svg>`;\n\nconst ICON_TRASH = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/></svg>`;\n\nconst ICON_CODE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"16 18 22 12 16 6\"/><polyline points=\"8 6 2 12 8 18\"/></svg>`;\n\nconst ICON_CROSSHAIR = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"22\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"6\" y1=\"12\" x2=\"2\" y2=\"12\"/><line x1=\"12\" y1=\"6\" x2=\"12\" y2=\"2\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"18\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18n\n// ---------------------------------------------------------------------------\n\nexport const DETAIL_I18N_EN = {\n \"detail.back\": \"Back\",\n \"detail.title\": \"Feedback #{number}\",\n \"detail.status\": \"Status\",\n \"detail.message\": \"Message\",\n \"detail.screenshot\": \"Screenshot\",\n \"detail.screenshotAlt\": \"Screenshot of the annotated area\",\n \"detail.metadata\": \"Details\",\n \"detail.annotation\": \"Annotation\",\n \"detail.page\": \"Page\",\n \"detail.author\": \"Author\",\n \"detail.date\": \"Created\",\n \"detail.viewport\": \"Viewport\",\n \"detail.browser\": \"Browser\",\n \"detail.resolvedAt\": \"Resolved at\",\n \"detail.goToAnnotation\": \"Go to annotation\",\n \"detail.element\": \"Element\",\n \"detail.selector\": \"Selector\",\n \"detail.position\": \"Position\",\n \"detail.resolve\": \"Resolve\",\n \"detail.reopen\": \"Reopen\",\n \"detail.delete\": \"Delete\",\n};\n\nexport const DETAIL_I18N_FR = {\n \"detail.back\": \"Retour\",\n \"detail.title\": \"Feedback n\\u00b0{number}\",\n \"detail.status\": \"Statut\",\n \"detail.message\": \"Message\",\n \"detail.screenshot\": \"Capture d'\\u00e9cran\",\n \"detail.screenshotAlt\": \"Capture d'\\u00e9cran de la zone annot\\u00e9e\",\n \"detail.metadata\": \"D\\u00e9tails\",\n \"detail.annotation\": \"Annotation\",\n \"detail.page\": \"Page\",\n \"detail.author\": \"Auteur\",\n \"detail.date\": \"Cr\\u00e9\\u00e9 le\",\n \"detail.viewport\": \"Viewport\",\n \"detail.browser\": \"Navigateur\",\n \"detail.resolvedAt\": \"R\\u00e9solu le\",\n \"detail.goToAnnotation\": \"Aller \\u00e0 l'annotation\",\n \"detail.element\": \"\\u00c9l\\u00e9ment\",\n \"detail.selector\": \"S\\u00e9lecteur\",\n \"detail.position\": \"Position\",\n \"detail.resolve\": \"R\\u00e9soudre\",\n \"detail.reopen\": \"Rouvrir\",\n \"detail.delete\": \"Supprimer\",\n};\n\ntype DetailI18nKey = keyof typeof DETAIL_I18N_EN;\ntype DetailI18n = Record<DetailI18nKey, string>;\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const DETAIL_CSS = /* css */ `\n /* ============================\n Detail View — Panel-in-Panel\n ============================ */\n\n .sp-detail {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n z-index: 20;\n transform: translateX(100%);\n transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);\n will-change: transform;\n overflow: hidden;\n }\n\n .sp-detail--visible {\n transform: translateX(0);\n }\n\n /* ---- Header ---- */\n\n .sp-detail-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n flex-shrink: 0;\n min-height: 64px;\n }\n\n .sp-detail-back {\n width: 40px;\n height: 40px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n flex-shrink: 0;\n padding: 0;\n }\n\n .sp-detail-back:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-detail-back:active {\n transform: scale(0.92);\n transition-duration: 0.1s;\n }\n\n .sp-detail-back svg {\n width: 18px;\n height: 18px;\n }\n\n .sp-detail-title {\n font-size: 16px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-detail-header .sp-badge {\n flex-shrink: 0;\n }\n\n /* ---- Content ---- */\n\n .sp-detail-content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 0;\n }\n\n .sp-detail-content::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-detail-content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-detail-content::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-detail-content::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n /* ---- Section ---- */\n\n .sp-detail-section {\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n opacity: 0;\n transform: translateY(8px);\n animation: sp-detail-section-in 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards;\n }\n\n @keyframes sp-detail-section-in {\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .sp-detail-section:last-child {\n border-bottom: none;\n }\n\n .sp-detail-section-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n margin-bottom: 14px;\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-detail-section-title svg {\n width: 14px;\n height: 14px;\n opacity: 0.6;\n }\n\n /* ---- Status + Actions Section ---- */\n\n .sp-detail-status {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 16px;\n }\n\n .sp-detail-status-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 14px;\n border-radius: var(--sp-radius-full);\n font-size: 12px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-detail-status-pill--open {\n background: rgba(34, 197, 94, 0.1);\n color: #22c55e;\n border: 1px solid rgba(34, 197, 94, 0.2);\n }\n\n .sp-detail-status-pill--resolved {\n background: rgba(156, 163, 175, 0.1);\n color: #9ca3af;\n border: 1px solid rgba(156, 163, 175, 0.2);\n }\n\n .sp-detail-status-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .sp-detail-actions {\n display: flex;\n gap: 8px;\n }\n\n .sp-detail-actions button {\n flex: 1;\n height: 40px;\n padding: 0 16px;\n border-radius: var(--sp-radius);\n font-family: var(--sp-font);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n transition: all 0.2s ease;\n }\n\n .sp-detail-actions button svg {\n width: 15px;\n height: 15px;\n }\n\n .sp-detail-btn-resolve {\n border: 1.5px solid #22c55e;\n background: rgba(34, 197, 94, 0.06);\n color: #22c55e;\n }\n\n .sp-detail-btn-resolve:hover {\n background: rgba(34, 197, 94, 0.14);\n box-shadow: 0 0 16px rgba(34, 197, 94, 0.12);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-resolve:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-btn-reopen {\n border: 1.5px solid var(--sp-accent);\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n .sp-detail-btn-reopen:hover {\n background: rgba(var(--sp-accent), 0.14);\n box-shadow: 0 0 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-reopen:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-btn-delete {\n border: 1.5px solid #ef4444;\n background: rgba(239, 68, 68, 0.06);\n color: #ef4444;\n }\n\n .sp-detail-btn-delete:hover {\n background: rgba(239, 68, 68, 0.14);\n box-shadow: 0 0 16px rgba(239, 68, 68, 0.12);\n transform: translateY(-1px);\n }\n\n .sp-detail-btn-delete:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-detail-actions button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n transform: none;\n box-shadow: none;\n }\n\n /* ---- Message Section ---- */\n\n .sp-detail-message {\n font-size: 14px;\n line-height: 1.65;\n color: var(--sp-text);\n padding: 14px 16px;\n border-left: 3px solid var(--sp-accent);\n border-radius: 0 var(--sp-radius) var(--sp-radius) 0;\n background: var(--sp-glass-bg-heavy);\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n /* ---- Screenshot Section ---- */\n\n .sp-detail-screenshot {\n display: block;\n width: 100%;\n height: auto;\n max-height: 400px;\n object-fit: contain;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-glass-border);\n background: var(--sp-glass-bg-heavy);\n }\n\n /* ---- Metadata Section ---- */\n\n .sp-detail-meta {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .sp-detail-meta-row {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n }\n\n .sp-detail-meta-row svg {\n width: 14px;\n height: 14px;\n color: var(--sp-text-tertiary);\n flex-shrink: 0;\n margin-top: 1px;\n }\n\n .sp-detail-meta-content {\n flex: 1;\n min-width: 0;\n }\n\n .sp-detail-meta-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n line-height: 1;\n margin-bottom: 4px;\n }\n\n .sp-detail-meta-value {\n font-size: 13px;\n line-height: 1.4;\n color: var(--sp-text);\n word-break: break-all;\n }\n\n .sp-detail-meta-value--mono {\n font-family: \"SF Mono\", \"Cascadia Code\", \"Fira Code\", \"Consolas\", monospace;\n font-size: 12px;\n background: var(--sp-glass-bg-heavy);\n padding: 2px 6px;\n border-radius: 4px;\n border: 1px solid var(--sp-glass-border-subtle);\n }\n\n .sp-detail-meta-value--secondary {\n color: var(--sp-text-secondary);\n font-size: 12px;\n }\n\n /* ---- Annotation Section ---- */\n\n .sp-detail-annotation {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .sp-detail-annotation-info {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border-subtle);\n }\n\n .sp-detail-annotation-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n }\n\n .sp-detail-annotation-row svg {\n width: 13px;\n height: 13px;\n color: var(--sp-text-tertiary);\n flex-shrink: 0;\n margin-top: 2px;\n }\n\n .sp-detail-annotation-label {\n font-size: 10px;\n font-weight: 600;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n line-height: 1;\n margin-bottom: 3px;\n }\n\n .sp-detail-annotation-value {\n font-size: 12px;\n line-height: 1.4;\n color: var(--sp-text);\n word-break: break-all;\n }\n\n .sp-detail-annotation-value--mono {\n font-family: \"SF Mono\", \"Cascadia Code\", \"Fira Code\", \"Consolas\", monospace;\n font-size: 11px;\n background: var(--sp-bg-hover);\n padding: 2px 6px;\n border-radius: 4px;\n display: inline-block;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-detail-btn-goto {\n width: 100%;\n height: 44px;\n padding: 0 20px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: all 0.25s ease;\n box-shadow: 0 2px 12px var(--sp-accent-glow);\n }\n\n .sp-detail-btn-goto svg {\n width: 16px;\n height: 16px;\n }\n\n .sp-detail-btn-goto:hover {\n box-shadow: 0 4px 20px var(--sp-accent-glow);\n transform: translateY(-2px);\n }\n\n .sp-detail-btn-goto:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n /* ---- Forced Colors / High Contrast ---- */\n\n @media (forced-colors: active) {\n .sp-detail {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-detail-back,\n .sp-detail-btn-goto,\n .sp-detail-btn-resolve,\n .sp-detail-btn-reopen,\n .sp-detail-btn-delete {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-detail-back:focus-visible,\n .sp-detail-btn-goto:focus-visible,\n .sp-detail-btn-resolve:focus-visible,\n .sp-detail-btn-reopen:focus-visible,\n .sp-detail-btn-delete:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-detail-status-pill {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-detail-message {\n border-left: 3px solid ButtonText !important;\n }\n }\n\n /* ---- Reduced Motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-detail {\n transition-duration: 0.01ms !important;\n }\n\n .sp-detail-section {\n animation-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Parse a userAgent string to extract the browser name and version. */\nfunction parseBrowser(ua: string): string {\n // Order matters: Edge includes \"Edg/\", Chrome includes \"Chrome/\", etc.\n if (/Edg\\//i.test(ua)) {\n const m = ua.match(/Edg\\/([\\d.]+)/);\n return m ? `Edge ${m[1]}` : \"Edge\";\n }\n if (/OPR\\//i.test(ua) || /Opera/i.test(ua)) {\n const m = ua.match(/OPR\\/([\\d.]+)/);\n return m ? `Opera ${m[1]}` : \"Opera\";\n }\n if (/Firefox\\//i.test(ua)) {\n const m = ua.match(/Firefox\\/([\\d.]+)/);\n return m ? `Firefox ${m[1]}` : \"Firefox\";\n }\n if (/Chrome\\//i.test(ua) && !/Chromium/i.test(ua)) {\n const m = ua.match(/Chrome\\/([\\d.]+)/);\n return m ? `Chrome ${m[1]}` : \"Chrome\";\n }\n if (/Safari\\//i.test(ua) && !/Chrome/i.test(ua)) {\n const m = ua.match(/Version\\/([\\d.]+)/);\n return m ? `Safari ${m[1]}` : \"Safari\";\n }\n return \"Unknown\";\n}\n\n/** Format an ISO date string to a full locale-aware date/time. */\nfunction formatFullDate(isoString: string, locale: string): string {\n try {\n const d = new Date(isoString);\n return d.toLocaleString(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n } catch {\n return isoString;\n }\n}\n\n/** Extract the pathname from a URL string, falling back to the raw string. */\nfunction extractPathname(url: string): string {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n}\n\n/**\n * Whitelist URL schemes that are safe to use as `<img src>`. Defends against\n * a buggy or compromised `ScreenshotStorage` (or DB) writing a `javascript:`,\n * `data:text/html`, or `data:image/svg+xml` URL — the latter can host\n * external `<image href>` references that exfiltrate IP/UA/Referer when the\n * panel renders. Browsers refuse to execute scripts via `<img>`, but the\n * fetch itself still happens for arbitrary URLs.\n */\nfunction isSafeImageUrl(url: string): boolean {\n // data:image/(jpeg|png|webp) is what the widget produces; SVG is excluded\n // because it can contain external references and is rarely a useful\n // screenshot format.\n if (/^data:image\\/(jpeg|png|webp);/i.test(url)) return true;\n // Remote URLs over https are accepted (S3, R2, etc.). http: is rejected\n // because the panel typically runs over https and mixed-content is blocked\n // anyway — surfacing the issue here is clearer than a silent network error.\n if (/^https:\\/\\//i.test(url)) return true;\n return false;\n}\n\n/** Truncate a string to a max length with ellipsis. */\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"\\u2026\";\n}\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface DetailCallbacks {\n onBack: () => void;\n onResolve: (feedback: FeedbackResponse) => Promise<void>;\n onDelete: (feedback: FeedbackResponse) => Promise<void>;\n onGoToAnnotation: (feedback: FeedbackResponse) => void;\n}\n\n// ---------------------------------------------------------------------------\n// DetailView Class\n// ---------------------------------------------------------------------------\n\nexport class DetailView {\n readonly element: HTMLElement;\n\n private _isVisible = false;\n private currentFeedback: FeedbackResponse | null = null;\n private readonly content: HTMLElement;\n private readonly i18n: DetailI18n;\n private resolveBtn: HTMLButtonElement | null = null;\n private deleteBtn: HTMLButtonElement | null = null;\n private isProcessing = false;\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly callbacks: DetailCallbacks,\n locale: string,\n ) {\n this.i18n = locale.startsWith(\"fr\") ? DETAIL_I18N_FR : DETAIL_I18N_EN;\n\n // Root container\n this.element = el(\"div\", { class: \"sp-detail\" });\n this.element.setAttribute(\"role\", \"dialog\");\n this.element.setAttribute(\"aria-label\", \"Feedback detail\");\n this.element.setAttribute(\"aria-hidden\", \"true\");\n\n // Header (built once, title/badge updated on show())\n const header = el(\"div\", { class: \"sp-detail-header\" });\n\n const backBtn = document.createElement(\"button\");\n backBtn.type = \"button\";\n backBtn.className = \"sp-detail-back\";\n backBtn.setAttribute(\"aria-label\", this.i18n[\"detail.back\"]);\n backBtn.appendChild(parseSvg(ICON_ARROW_LEFT));\n backBtn.addEventListener(\"click\", () => {\n this.hide();\n this.callbacks.onBack();\n });\n\n this.element.appendChild(header);\n header.appendChild(backBtn);\n\n // Title and badge are appended in show()\n\n // Scrollable content area\n this.content = el(\"div\", { class: \"sp-detail-content\" });\n this.element.appendChild(this.content);\n }\n\n /** Show the detail view for a specific feedback. */\n show(feedback: FeedbackResponse, number: number): void {\n this.currentFeedback = feedback;\n this.isProcessing = false;\n\n // ---- Update header ----\n const header = this.element.querySelector<HTMLElement>(\".sp-detail-header\");\n if (!header) return;\n // Remove old title/badge but keep the back button\n const backBtn = header.querySelector<HTMLElement>(\".sp-detail-back\");\n if (!backBtn) return;\n header.replaceChildren(backBtn);\n\n const title = el(\"span\", { class: \"sp-detail-title\" });\n setText(title, this.i18n[\"detail.title\"].replace(\"{number}\", String(number)));\n header.appendChild(title);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n badge.style.background = getTypeBgColor(feedback.type, this.colors);\n badge.style.color = getTypeColor(feedback.type, this.colors);\n setText(badge, feedback.type);\n header.appendChild(badge);\n\n // ---- Build content sections ----\n this.content.replaceChildren();\n\n let sectionIndex = 0;\n\n // Section 1: Status + Actions\n const statusSection = this.buildSection(sectionIndex++);\n this.buildStatusActions(statusSection, feedback);\n this.content.appendChild(statusSection);\n\n // Section 2: Message\n const messageSection = this.buildSection(sectionIndex++);\n const messageSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(messageSectionTitle, this.i18n[\"detail.message\"]);\n messageSection.appendChild(messageSectionTitle);\n\n const messageBlock = el(\"div\", { class: \"sp-detail-message\" });\n messageBlock.style.borderLeftColor = getTypeColor(feedback.type, this.colors);\n setText(messageBlock, feedback.message);\n messageSection.appendChild(messageBlock);\n this.content.appendChild(messageSection);\n\n // Section 2b: Screenshot (when captured)\n if (feedback.screenshotUrl && isSafeImageUrl(feedback.screenshotUrl)) {\n const screenshotSection = this.buildSection(sectionIndex++);\n const screenshotSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(screenshotSectionTitle, this.i18n[\"detail.screenshot\"]);\n screenshotSection.appendChild(screenshotSectionTitle);\n\n const img = document.createElement(\"img\");\n img.className = \"sp-detail-screenshot\";\n img.src = feedback.screenshotUrl;\n img.alt = this.i18n[\"detail.screenshotAlt\"];\n img.loading = \"lazy\";\n // Avoid leaking the panel viewer's referrer to the storage host —\n // a malicious or compromised storage URL could otherwise track which\n // operators view which feedbacks.\n img.referrerPolicy = \"no-referrer\";\n screenshotSection.appendChild(img);\n this.content.appendChild(screenshotSection);\n }\n\n // Section 3: Metadata\n const metaSection = this.buildSection(sectionIndex++);\n const metaSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(metaSectionTitle, this.i18n[\"detail.metadata\"]);\n metaSection.appendChild(metaSectionTitle);\n this.buildMetadata(metaSection, feedback);\n this.content.appendChild(metaSection);\n\n // Section 4: Annotation (if any)\n if (feedback.annotations.length > 0) {\n const annSection = this.buildSection(sectionIndex++);\n const annSectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n annSectionTitle.appendChild(parseSvg(ICON_MAP_PIN));\n const annTitleText = el(\"span\");\n setText(annTitleText, this.i18n[\"detail.annotation\"]);\n annSectionTitle.appendChild(annTitleText);\n annSection.appendChild(annSectionTitle);\n this.buildAnnotation(annSection, feedback);\n this.content.appendChild(annSection);\n }\n\n // ---- Show with animation ----\n this._isVisible = true;\n this.element.setAttribute(\"aria-hidden\", \"false\");\n\n // Force reflow before adding visible class to trigger CSS transition\n void this.element.offsetHeight;\n this.element.classList.add(\"sp-detail--visible\");\n\n // Focus the back button for keyboard users\n requestAnimationFrame(() => {\n backBtn.focus();\n });\n }\n\n /** Hide the detail view with slide-out animation. */\n hide(): void {\n if (!this._isVisible) return;\n this._isVisible = false;\n this.element.classList.remove(\"sp-detail--visible\");\n this.element.setAttribute(\"aria-hidden\", \"true\");\n this.currentFeedback = null;\n this.resolveBtn = null;\n this.deleteBtn = null;\n }\n\n /** Whether the detail view is currently visible. */\n get isVisible(): boolean {\n return this._isVisible;\n }\n\n /** Cleanup all references. */\n destroy(): void {\n this.hide();\n this.element.remove();\n }\n\n // -----------------------------------------------------------------------\n // Private — Section builders\n // -----------------------------------------------------------------------\n\n /** Create a section element with stagger delay. */\n private buildSection(index: number): HTMLElement {\n const section = el(\"div\", { class: \"sp-detail-section\" });\n section.style.animationDelay = `${index * 40}ms`;\n return section;\n }\n\n /** Build Status pill + Resolve/Delete action buttons. */\n private buildStatusActions(container: HTMLElement, feedback: FeedbackResponse): void {\n const isResolved = feedback.status === \"resolved\";\n\n // Section title\n const sectionTitle = el(\"div\", { class: \"sp-detail-section-title\" });\n setText(sectionTitle, this.i18n[\"detail.status\"]);\n container.appendChild(sectionTitle);\n\n // Status pill\n const statusRow = el(\"div\", { class: \"sp-detail-status\" });\n const pill = el(\"span\", {\n class: `sp-detail-status-pill ${isResolved ? \"sp-detail-status-pill--resolved\" : \"sp-detail-status-pill--open\"}`,\n });\n const dot = el(\"span\", { class: \"sp-detail-status-dot\" });\n dot.style.background = isResolved ? \"#9ca3af\" : \"#22c55e\";\n pill.appendChild(dot);\n const pillLabel = el(\"span\");\n setText(pillLabel, isResolved ? this.i18n[\"detail.reopen\"] : this.i18n[\"detail.resolve\"]);\n // Actually label the pill with Open/Resolved\n setText(pillLabel, isResolved ? \"Resolved\" : \"Open\");\n pill.appendChild(pillLabel);\n statusRow.appendChild(pill);\n container.appendChild(statusRow);\n\n // Action buttons\n const actions = el(\"div\", { class: \"sp-detail-actions\" });\n\n // Resolve / Reopen\n this.resolveBtn = document.createElement(\"button\");\n this.resolveBtn.type = \"button\";\n if (isResolved) {\n this.resolveBtn.className = \"sp-detail-btn-reopen\";\n this.resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.reopen\"]);\n this.resolveBtn.appendChild(span);\n } else {\n this.resolveBtn.className = \"sp-detail-btn-resolve\";\n this.resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.resolve\"]);\n this.resolveBtn.appendChild(span);\n }\n this.resolveBtn.addEventListener(\"click\", () => this.handleResolve());\n\n // Delete\n this.deleteBtn = document.createElement(\"button\");\n this.deleteBtn.type = \"button\";\n this.deleteBtn.className = \"sp-detail-btn-delete\";\n this.deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteSpan = document.createElement(\"span\");\n setText(deleteSpan, this.i18n[\"detail.delete\"]);\n this.deleteBtn.appendChild(deleteSpan);\n this.deleteBtn.addEventListener(\"click\", () => this.handleDelete());\n\n actions.appendChild(this.resolveBtn);\n actions.appendChild(this.deleteBtn);\n container.appendChild(actions);\n }\n\n /** Build the metadata grid. */\n private buildMetadata(container: HTMLElement, feedback: FeedbackResponse): void {\n const meta = el(\"div\", { class: \"sp-detail-meta\" });\n\n // Page\n this.addMetaRow(meta, ICON_LINK, this.i18n[\"detail.page\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n const pathname = extractPathname(feedback.url);\n setText(value, truncate(pathname, 60));\n value.title = feedback.url;\n return value;\n });\n\n // Author\n this.addMetaRow(meta, ICON_USER, this.i18n[\"detail.author\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n const name = feedback.authorName || \"Anonymous\";\n const email = feedback.authorEmail;\n setText(value, email ? `${name} (${email})` : name);\n return value;\n });\n\n // Date\n this.addMetaRow(meta, ICON_CALENDAR, this.i18n[\"detail.date\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n setText(value, formatFullDate(feedback.createdAt, this.i18n === DETAIL_I18N_FR ? \"fr\" : \"en\"));\n return value;\n });\n\n // Viewport\n this.addMetaRow(meta, ICON_MONITOR, this.i18n[\"detail.viewport\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value sp-detail-meta-value--mono\" });\n setText(value, feedback.viewport || \"Unknown\");\n return value;\n });\n\n // Browser\n this.addMetaRow(\n meta,\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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 this.i18n[\"detail.browser\"],\n () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value\" });\n setText(value, parseBrowser(feedback.userAgent));\n return value;\n },\n );\n\n // Resolved at (only if resolved)\n if (feedback.resolvedAt) {\n const resolvedDate = feedback.resolvedAt;\n this.addMetaRow(meta, ICON_CHECK, this.i18n[\"detail.resolvedAt\"], () => {\n const value = el(\"div\", { class: \"sp-detail-meta-value sp-detail-meta-value--secondary\" });\n setText(value, formatFullDate(resolvedDate, this.i18n === DETAIL_I18N_FR ? \"fr\" : \"en\"));\n return value;\n });\n }\n\n container.appendChild(meta);\n }\n\n /** Add a single metadata row with icon, label, and custom value element. */\n private addMetaRow(container: HTMLElement, iconSvg: string, label: string, buildValue: () => HTMLElement): void {\n const row = el(\"div\", { class: \"sp-detail-meta-row\" });\n row.appendChild(parseSvg(iconSvg));\n\n const content = el(\"div\", { class: \"sp-detail-meta-content\" });\n const labelEl = el(\"div\", { class: \"sp-detail-meta-label\" });\n setText(labelEl, label);\n content.appendChild(labelEl);\n content.appendChild(buildValue());\n\n row.appendChild(content);\n container.appendChild(row);\n }\n\n /** Build the annotation detail section. */\n private buildAnnotation(container: HTMLElement, feedback: FeedbackResponse): void {\n const ann = feedback.annotations[0];\n if (!ann) return;\n\n const wrapper = el(\"div\", { class: \"sp-detail-annotation\" });\n\n // Info card\n const info = el(\"div\", { class: \"sp-detail-annotation-info\" });\n\n // Element tag\n this.addAnnotationRow(info, ICON_CODE, this.i18n[\"detail.element\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value sp-detail-annotation-value--mono\" });\n const tagDisplay = ann.elementId ? `<${ann.elementTag}#${ann.elementId}>` : `<${ann.elementTag}>`;\n setText(value, tagDisplay);\n return value;\n });\n\n // CSS selector\n this.addAnnotationRow(info, ICON_CROSSHAIR, this.i18n[\"detail.selector\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value sp-detail-annotation-value--mono\" });\n setText(value, truncate(ann.cssSelector, 60));\n value.title = ann.cssSelector;\n return value;\n });\n\n // Position\n this.addAnnotationRow(info, ICON_MAP_PIN, this.i18n[\"detail.position\"], () => {\n const value = el(\"span\", { class: \"sp-detail-annotation-value\" });\n setText(\n value,\n `${ann.xPct.toFixed(1)}%, ${ann.yPct.toFixed(1)}%` +\n (ann.wPct > 0 || ann.hPct > 0 ? ` (${ann.wPct.toFixed(1)}% \\u00d7 ${ann.hPct.toFixed(1)}%)` : \"\"),\n );\n return value;\n });\n\n wrapper.appendChild(info);\n\n // \"Go to annotation\" button\n const gotoBtn = document.createElement(\"button\");\n gotoBtn.type = \"button\";\n gotoBtn.className = \"sp-detail-btn-goto\";\n gotoBtn.appendChild(parseSvg(ICON_MAP_PIN));\n const gotoLabel = document.createElement(\"span\");\n setText(gotoLabel, this.i18n[\"detail.goToAnnotation\"]);\n gotoBtn.appendChild(gotoLabel);\n gotoBtn.addEventListener(\"click\", () => {\n if (this.currentFeedback) {\n this.callbacks.onGoToAnnotation(this.currentFeedback);\n }\n });\n\n wrapper.appendChild(gotoBtn);\n container.appendChild(wrapper);\n }\n\n /** Add a single annotation info row. */\n private addAnnotationRow(\n container: HTMLElement,\n iconSvg: string,\n label: string,\n buildValue: () => HTMLElement,\n ): void {\n const row = el(\"div\", { class: \"sp-detail-annotation-row\" });\n row.appendChild(parseSvg(iconSvg));\n\n const content = el(\"div\", { class: \"sp-detail-meta-content\" });\n const labelEl = el(\"div\", { class: \"sp-detail-annotation-label\" });\n setText(labelEl, label);\n content.appendChild(labelEl);\n content.appendChild(buildValue());\n\n row.appendChild(content);\n container.appendChild(row);\n }\n\n // -----------------------------------------------------------------------\n // Private — Action handlers\n // -----------------------------------------------------------------------\n\n private async handleResolve(): Promise<void> {\n if (this.isProcessing || !this.currentFeedback) return;\n this.isProcessing = true;\n\n if (this.resolveBtn) this.setButtonLoading(this.resolveBtn);\n if (this.deleteBtn) this.deleteBtn.disabled = true;\n\n try {\n await this.callbacks.onResolve(this.currentFeedback);\n // The parent will call hide() or re-show with updated data\n } catch {\n // Restore buttons on error\n this.isProcessing = false;\n if (this.resolveBtn) this.restoreResolveBtn(this.currentFeedback);\n if (this.deleteBtn) this.deleteBtn.disabled = false;\n }\n }\n\n private async handleDelete(): Promise<void> {\n if (this.isProcessing || !this.currentFeedback) return;\n this.isProcessing = true;\n\n if (this.deleteBtn) this.setButtonLoading(this.deleteBtn);\n if (this.resolveBtn) this.resolveBtn.disabled = true;\n\n try {\n await this.callbacks.onDelete(this.currentFeedback);\n // The parent will call hide() after deletion\n } catch {\n this.isProcessing = false;\n if (this.deleteBtn) this.restoreDeleteBtn();\n if (this.resolveBtn) this.resolveBtn.disabled = false;\n }\n }\n\n private setButtonLoading(btn: HTMLButtonElement): void {\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n }\n\n private restoreResolveBtn(feedback: FeedbackResponse): void {\n if (!this.resolveBtn) return;\n this.resolveBtn.disabled = false;\n this.resolveBtn.replaceChildren();\n\n const isResolved = feedback.status === \"resolved\";\n this.resolveBtn.appendChild(parseSvg(isResolved ? ICON_UNDO : ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, isResolved ? this.i18n[\"detail.reopen\"] : this.i18n[\"detail.resolve\"]);\n this.resolveBtn.appendChild(span);\n }\n\n private restoreDeleteBtn(): void {\n if (!this.deleteBtn) return;\n this.deleteBtn.disabled = false;\n this.deleteBtn.replaceChildren();\n this.deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const span = document.createElement(\"span\");\n setText(span, this.i18n[\"detail.delete\"]);\n this.deleteBtn.appendChild(span);\n }\n}\n","/**\n * Sort and group-by-page controls for the feedback panel.\n *\n * Provides:\n * - Sort dropdown (newest, oldest, by-type, open-first)\n * - Group by page toggle (collapsible URL sections)\n * - Pure sort/group utility functions\n *\n * Glassmorphism design — glass surfaces, accent gradients,\n * smooth micro-interactions.\n */\n\nimport type { FeedbackResponse, FeedbackType } from \"@siteping/core\";\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type SortMode = \"newest\" | \"oldest\" | \"by-type\" | \"open-first\";\n\n// ---------------------------------------------------------------------------\n// SVG Icons\n// ---------------------------------------------------------------------------\n\nexport const ICON_SORT = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M11 5h10\"/><path d=\"M11 9h7\"/><path d=\"M11 13h4\"/><path d=\"M3 17l3 3 3-3\"/><path d=\"M6 18V4\"/></svg>`;\n\nexport const ICON_PAGE = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><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\"/><polyline points=\"10 9 9 9 8 9\"/></svg>`;\n\nexport const ICON_CHEVRON = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"9 18 15 12 9 6\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// I18n\n// ---------------------------------------------------------------------------\n\nexport const SORT_I18N_EN = {\n \"sort.newest\": \"Newest first\",\n \"sort.oldest\": \"Oldest first\",\n \"sort.byType\": \"By type\",\n \"sort.openFirst\": \"Open first\",\n \"sort.label\": \"Sort\",\n \"group.byPage\": \"By page\",\n \"group.feedbacks\": \"{count} feedbacks\",\n} as const;\n\nexport const SORT_I18N_FR = {\n \"sort.newest\": \"Plus récents\",\n \"sort.oldest\": \"Plus anciens\",\n \"sort.byType\": \"Par type\",\n \"sort.openFirst\": \"Ouverts d'abord\",\n \"sort.label\": \"Trier\",\n \"group.byPage\": \"Par page\",\n \"group.feedbacks\": \"{count} feedbacks\",\n} as const;\n\nexport type SortI18nKey = keyof typeof SORT_I18N_EN;\nexport type SortI18n = Record<SortI18nKey, string>;\n\n// ---------------------------------------------------------------------------\n// Sort utilities\n// ---------------------------------------------------------------------------\n\n/** Type priority for \"by-type\" sort: question, change, bug, other */\nconst TYPE_ORDER: Record<FeedbackType, number> = {\n question: 0,\n change: 1,\n bug: 2,\n other: 3,\n};\n\n/** Sort feedbacks according to the given mode. Returns a new array. */\nexport function sortFeedbacks(feedbacks: FeedbackResponse[], mode: SortMode): FeedbackResponse[] {\n const sorted = [...feedbacks];\n\n switch (mode) {\n case \"newest\":\n sorted.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n break;\n\n case \"oldest\":\n sorted.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());\n break;\n\n case \"by-type\":\n sorted.sort((a, b) => {\n const typeA = TYPE_ORDER[a.type] ?? 99;\n const typeB = TYPE_ORDER[b.type] ?? 99;\n if (typeA !== typeB) return typeA - typeB;\n // Within same type: newest first\n return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n });\n break;\n\n case \"open-first\":\n sorted.sort((a, b) => {\n // Open (0) before resolved (1)\n const statusA = a.status === \"open\" ? 0 : 1;\n const statusB = b.status === \"open\" ? 0 : 1;\n if (statusA !== statusB) return statusA - statusB;\n // Within same status: newest first\n return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n });\n break;\n }\n\n return sorted;\n}\n\n// ---------------------------------------------------------------------------\n// Group by page\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the pathname from a full URL string.\n * Falls back to the raw string if URL parsing fails.\n */\nfunction extractPathname(url: string): string {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n}\n\n/** Truncate a path string, keeping the beginning and end visible. */\nfunction truncatePath(path: string, maxLength: number): string {\n if (path.length <= maxLength) return path;\n const ellipsis = \"\\u2026\";\n const keep = Math.floor((maxLength - 1) / 2);\n return path.slice(0, keep) + ellipsis + path.slice(-keep);\n}\n\n/**\n * Group feedbacks by URL pathname.\n * Returns a Map sorted by feedback count descending (most feedbacks first).\n * Each group's feedbacks maintain their original order.\n */\nexport function groupFeedbacksByPage(feedbacks: FeedbackResponse[]): Map<string, FeedbackResponse[]> {\n const groups = new Map<string, FeedbackResponse[]>();\n\n for (const fb of feedbacks) {\n const path = extractPathname(fb.url);\n const existing = groups.get(path);\n if (existing) {\n existing.push(fb);\n } else {\n groups.set(path, [fb]);\n }\n }\n\n // Sort by count descending\n const sorted = new Map([...groups.entries()].sort((a, b) => b[1].length - a[1].length));\n\n return sorted;\n}\n\n// ---------------------------------------------------------------------------\n// Page group header\n// ---------------------------------------------------------------------------\n\n/**\n * Create a collapsible page group header element.\n * Click toggles the associated `.sp-group-content` sibling.\n */\nexport function createPageGroupHeader(pagePath: string, count: number, colors: ThemeColors): HTMLElement {\n const header = el(\"div\", { class: \"sp-group-header\" });\n header.setAttribute(\"role\", \"button\");\n header.setAttribute(\"tabindex\", \"0\");\n header.setAttribute(\"aria-expanded\", \"true\");\n header.style.borderBottomColor = colors.border;\n\n // Chevron\n const chevronWrap = el(\"span\", { class: \"sp-group-header-chevron\" });\n chevronWrap.appendChild(parseSvg(ICON_CHEVRON));\n header.appendChild(chevronWrap);\n\n // Page icon\n const pageIcon = el(\"span\", { class: \"sp-group-header-icon\" });\n pageIcon.appendChild(parseSvg(ICON_PAGE));\n header.appendChild(pageIcon);\n\n // Path\n const pathEl = el(\"span\", { class: \"sp-group-header-path\" });\n const displayPath = truncatePath(pagePath, 40);\n setText(pathEl, displayPath);\n if (pagePath.length > 40) {\n pathEl.title = pagePath;\n }\n header.appendChild(pathEl);\n\n // Count badge\n const countEl = el(\"span\", { class: \"sp-group-header-count\" });\n countEl.style.background = colors.accentLight;\n countEl.style.color = colors.accent;\n setText(countEl, String(count));\n header.appendChild(countEl);\n\n // Toggle behavior\n const toggle = () => {\n const isExpanded = header.getAttribute(\"aria-expanded\") === \"true\";\n header.setAttribute(\"aria-expanded\", String(!isExpanded));\n header.classList.toggle(\"sp-group-header--collapsed\", isExpanded);\n\n const content = header.nextElementSibling;\n if (content?.classList.contains(\"sp-group-content\")) {\n content.classList.toggle(\"sp-group-content--collapsed\", isExpanded);\n }\n };\n\n header.addEventListener(\"click\", toggle);\n header.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggle();\n }\n });\n\n return header;\n}\n\n// ---------------------------------------------------------------------------\n// PanelSortControls\n// ---------------------------------------------------------------------------\n\nexport class PanelSortControls {\n readonly element: HTMLElement;\n\n private _sortMode: SortMode = \"newest\";\n private _groupByPage = false;\n private menuEl: HTMLElement | null = null;\n private sortBtn: HTMLButtonElement;\n private groupToggle: HTMLButtonElement;\n private readonly i18n: SortI18n;\n private readonly colors: ThemeColors;\n private readonly onChange: () => void;\n private outsideClickHandler: ((e: MouseEvent) => void) | null = null;\n\n constructor(colors: ThemeColors, onChange: () => void, locale?: string) {\n this.colors = colors;\n this.onChange = onChange;\n this.i18n = locale === \"fr\" ? SORT_I18N_FR : SORT_I18N_EN;\n\n this.element = el(\"div\", { class: \"sp-sort-controls\" });\n\n // Sort button\n this.sortBtn = document.createElement(\"button\");\n this.sortBtn.className = \"sp-sort-btn\";\n this.sortBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.sortBtn.setAttribute(\"aria-expanded\", \"false\");\n this.sortBtn.setAttribute(\"aria-label\", this.i18n[\"sort.label\"]);\n\n const sortIcon = parseSvg(ICON_SORT);\n this.sortBtn.appendChild(sortIcon);\n\n const sortLabel = el(\"span\", { class: \"sp-sort-btn-label\" });\n setText(sortLabel, this.i18n[\"sort.newest\"]);\n this.sortBtn.appendChild(sortLabel);\n\n this.sortBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggleMenu();\n });\n\n // Group by page toggle\n this.groupToggle = document.createElement(\"button\");\n this.groupToggle.className = \"sp-group-toggle\";\n this.groupToggle.setAttribute(\"aria-pressed\", \"false\");\n\n const groupIcon = parseSvg(ICON_PAGE);\n this.groupToggle.appendChild(groupIcon);\n\n const groupLabel = el(\"span\", { class: \"sp-group-toggle-label\" });\n setText(groupLabel, this.i18n[\"group.byPage\"]);\n this.groupToggle.appendChild(groupLabel);\n\n this.groupToggle.addEventListener(\"click\", () => {\n this._groupByPage = !this._groupByPage;\n this.groupToggle.classList.toggle(\"sp-group-toggle--active\", this._groupByPage);\n this.groupToggle.setAttribute(\"aria-pressed\", String(this._groupByPage));\n this.onChange();\n });\n\n this.element.appendChild(this.sortBtn);\n this.element.appendChild(this.groupToggle);\n }\n\n get sortMode(): SortMode {\n return this._sortMode;\n }\n\n get groupByPage(): boolean {\n return this._groupByPage;\n }\n\n private toggleMenu(): void {\n if (this.menuEl) {\n this.closeMenu();\n return;\n }\n this.openMenu();\n }\n\n private openMenu(): void {\n this.menuEl = el(\"div\", { class: \"sp-sort-menu\" });\n this.menuEl.setAttribute(\"role\", \"listbox\");\n this.menuEl.setAttribute(\"aria-label\", this.i18n[\"sort.label\"]);\n this.sortBtn.setAttribute(\"aria-expanded\", \"true\");\n\n const options: { mode: SortMode; label: string }[] = [\n { mode: \"newest\", label: this.i18n[\"sort.newest\"] },\n { mode: \"oldest\", label: this.i18n[\"sort.oldest\"] },\n { mode: \"by-type\", label: this.i18n[\"sort.byType\"] },\n { mode: \"open-first\", label: this.i18n[\"sort.openFirst\"] },\n ];\n\n for (const opt of options) {\n const item = document.createElement(\"button\");\n item.className = `sp-sort-option${opt.mode === this._sortMode ? \" sp-sort-option--active\" : \"\"}`;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(opt.mode === this._sortMode));\n\n if (opt.mode === this._sortMode) {\n item.style.background = this.colors.accentLight;\n item.style.color = this.colors.accent;\n }\n\n setText(item, opt.label);\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this._sortMode = opt.mode;\n this.updateSortLabel();\n this.closeMenu();\n this.onChange();\n });\n\n this.menuEl.appendChild(item);\n }\n\n // Position relative to button\n this.element.appendChild(this.menuEl);\n\n // Close on outside click (next tick to avoid the current click)\n requestAnimationFrame(() => {\n this.outsideClickHandler = (e: MouseEvent) => {\n if (this.menuEl && !this.element.contains(e.target as Node)) {\n this.closeMenu();\n }\n };\n document.addEventListener(\"click\", this.outsideClickHandler, true);\n });\n\n // Close on Escape\n this.menuEl.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeMenu();\n this.sortBtn.focus();\n }\n });\n }\n\n private closeMenu(): void {\n if (this.menuEl) {\n this.menuEl.remove();\n this.menuEl = null;\n }\n this.sortBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.outsideClickHandler) {\n document.removeEventListener(\"click\", this.outsideClickHandler, true);\n this.outsideClickHandler = null;\n }\n }\n\n private updateSortLabel(): void {\n const labelMap: Record<SortMode, string> = {\n newest: this.i18n[\"sort.newest\"],\n oldest: this.i18n[\"sort.oldest\"],\n \"by-type\": this.i18n[\"sort.byType\"],\n \"open-first\": this.i18n[\"sort.openFirst\"],\n };\n const label = this.sortBtn.querySelector(\".sp-sort-btn-label\");\n if (label) setText(label as HTMLElement, labelMap[this._sortMode]);\n }\n\n destroy(): void {\n this.closeMenu();\n }\n}\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const SORT_CSS = `\n /* ============================\n Sort Controls Container\n ============================ */\n\n .sp-sort-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-top: 4px;\n padding-top: 8px;\n border-top: 1px solid var(--sp-border);\n }\n\n /* ============================\n Sort Dropdown Button\n ============================ */\n\n .sp-sort-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .sp-sort-btn svg {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n }\n\n .sp-sort-btn:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-sort-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Sort Floating Menu\n ============================ */\n\n .sp-sort-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n min-width: 170px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-sort-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-sort-menu-in {\n from {\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n /* ============================\n Sort Menu Option\n ============================ */\n\n .sp-sort-option {\n display: block;\n width: 100%;\n padding: 8px 12px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: all 0.15s ease;\n }\n\n .sp-sort-option:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-sort-option--active {\n font-weight: 600;\n }\n\n .sp-sort-option--active:hover {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n }\n\n /* ============================\n Group by Page Toggle\n ============================ */\n\n .sp-group-toggle {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: all 0.2s ease;\n }\n\n .sp-group-toggle svg {\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n }\n\n .sp-group-toggle:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n .sp-group-toggle--active {\n background: var(--sp-accent-gradient);\n border-color: transparent;\n color: #fff;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-group-toggle--active:hover {\n background: var(--sp-accent-gradient);\n border-color: transparent;\n color: #fff;\n }\n\n /* ============================\n Page Group Header\n ============================ */\n\n .sp-group-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: var(--sp-accent-light);\n border-bottom: 1px solid var(--sp-border);\n cursor: pointer;\n user-select: none;\n position: sticky;\n top: 0;\n z-index: 2;\n transition: background 0.2s ease;\n }\n\n .sp-group-header:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-group-header:focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: -2px;\n }\n\n .sp-group-header-chevron {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n transition: transform 0.2s ease;\n transform: rotate(90deg);\n }\n\n .sp-group-header-chevron svg {\n width: 12px;\n height: 12px;\n color: var(--sp-text-tertiary);\n }\n\n .sp-group-header--collapsed .sp-group-header-chevron {\n transform: rotate(0deg);\n }\n\n .sp-group-header-icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .sp-group-header-icon svg {\n width: 14px;\n height: 14px;\n color: var(--sp-text-tertiary);\n }\n\n .sp-group-header-path {\n font-size: 12px;\n font-weight: 600;\n color: var(--sp-text-secondary);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .sp-group-header-count {\n font-size: 11px;\n font-weight: 700;\n padding: 1px 8px;\n border-radius: var(--sp-radius-full);\n flex-shrink: 0;\n font-variant-numeric: tabular-nums;\n }\n\n /* ============================\n Page Group Content\n ============================ */\n\n .sp-group-content {\n overflow: hidden;\n transition: max-height 0.25s ease, opacity 0.2s ease;\n max-height: 5000px;\n opacity: 1;\n }\n\n .sp-group-content--collapsed {\n max-height: 0;\n opacity: 0;\n pointer-events: none;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-sort-btn,\n .sp-group-toggle,\n .sp-sort-option,\n .sp-group-header {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-sort-btn:focus-visible,\n .sp-group-toggle:focus-visible,\n .sp-sort-option:focus-visible,\n .sp-group-header:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-sort-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n }\n\n /* ============================\n Reduced Motion\n ============================ */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-sort-menu {\n animation: none;\n }\n .sp-group-header-chevron {\n transition: none;\n }\n .sp-group-content {\n transition: none;\n }\n }\n`;\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { el, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// i18n — standalone constants, wired into the locale files at integration time\n// ---------------------------------------------------------------------------\n\nexport const STATS_I18N_EN = {\n \"stats.open\": \"Open\",\n \"stats.resolved\": \"Resolved\",\n \"stats.bugs\": \"Bugs\",\n \"stats.progress\": \"{percent}% resolved\",\n};\n\nexport const STATS_I18N_FR = {\n \"stats.open\": \"Ouverts\",\n \"stats.resolved\": \"Résolus\",\n \"stats.bugs\": \"Bugs\",\n \"stats.progress\": \"{percent}% résolus\",\n};\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const STATS_CSS = /* css */ `\n .sp-stats-bar {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 12px 24px;\n border-bottom: 1px solid var(--sp-border);\n user-select: none;\n }\n\n .sp-stats-bar[hidden] {\n display: none;\n }\n\n .sp-stats-row {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .sp-stats-item {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .sp-stats-dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .sp-stats-value {\n font-size: 16px;\n font-weight: 600;\n line-height: 1;\n color: var(--sp-text);\n font-variant-numeric: tabular-nums;\n font-feature-settings: \"tnum\";\n transition: opacity 0.3s ease;\n }\n\n .sp-stats-label {\n font-size: 11px;\n line-height: 1;\n color: var(--sp-text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.04em;\n }\n\n .sp-stats-progress {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-stats-progress-track {\n flex: 1;\n height: 4px;\n border-radius: 2px;\n background: var(--sp-border);\n overflow: hidden;\n }\n\n .sp-stats-progress-fill {\n height: 100%;\n border-radius: 2px;\n background: linear-gradient(90deg, var(--sp-accent), #22c55e);\n width: 0%;\n transition: width 0.5s ease;\n }\n\n .sp-stats-progress-label {\n font-size: 10px;\n line-height: 1;\n color: var(--sp-text-tertiary);\n white-space: nowrap;\n font-variant-numeric: tabular-nums;\n font-feature-settings: \"tnum\";\n min-width: 64px;\n text-align: right;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Compact statistics bar displayed between filters and the feedback list.\n * Shows open/resolved/bug counts and a resolved-percentage progress bar.\n */\ntype StatsI18n = typeof STATS_I18N_EN;\n\nexport class PanelStats {\n readonly element: HTMLElement;\n\n private readonly valueOpen: HTMLElement;\n private readonly valueResolved: HTMLElement;\n private readonly valueBugs: HTMLElement;\n private readonly progressFill: HTMLElement;\n private readonly progressLabel: HTMLElement;\n private readonly i18n: StatsI18n;\n\n constructor(\n private readonly colors: ThemeColors,\n locale?: string,\n ) {\n this.i18n = locale === \"fr\" ? STATS_I18N_FR : STATS_I18N_EN;\n // Container\n this.element = el(\"div\", { class: \"sp-stats-bar\" });\n this.element.setAttribute(\"aria-label\", \"Feedback statistics\");\n this.element.hidden = true;\n\n // --- Stats row ---\n const row = el(\"div\", { class: \"sp-stats-row\" });\n\n // Open\n const itemOpen = el(\"div\", { class: \"sp-stats-item\" });\n const dotOpen = el(\"span\", { class: \"sp-stats-dot\" });\n dotOpen.style.background = \"#22c55e\";\n this.valueOpen = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueOpen, \"0\");\n const labelOpen = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelOpen, this.i18n[\"stats.open\"]);\n itemOpen.appendChild(dotOpen);\n itemOpen.appendChild(this.valueOpen);\n itemOpen.appendChild(labelOpen);\n\n // Resolved\n const itemResolved = el(\"div\", { class: \"sp-stats-item\" });\n const dotResolved = el(\"span\", { class: \"sp-stats-dot\" });\n dotResolved.style.background = \"#9ca3af\";\n this.valueResolved = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueResolved, \"0\");\n const labelResolved = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelResolved, this.i18n[\"stats.resolved\"]);\n itemResolved.appendChild(dotResolved);\n itemResolved.appendChild(this.valueResolved);\n itemResolved.appendChild(labelResolved);\n\n // Bugs\n const itemBugs = el(\"div\", { class: \"sp-stats-item\" });\n const dotBugs = el(\"span\", { class: \"sp-stats-dot\" });\n dotBugs.style.background = this.colors.typeBug;\n this.valueBugs = el(\"span\", { class: \"sp-stats-value\" });\n setText(this.valueBugs, \"0\");\n const labelBugs = el(\"span\", { class: \"sp-stats-label\" });\n setText(labelBugs, this.i18n[\"stats.bugs\"]);\n itemBugs.appendChild(dotBugs);\n itemBugs.appendChild(this.valueBugs);\n itemBugs.appendChild(labelBugs);\n\n row.appendChild(itemOpen);\n row.appendChild(itemResolved);\n row.appendChild(itemBugs);\n\n // --- Progress bar ---\n const progress = el(\"div\", { class: \"sp-stats-progress\" });\n const track = el(\"div\", { class: \"sp-stats-progress-track\" });\n this.progressFill = el(\"div\", { class: \"sp-stats-progress-fill\" });\n track.appendChild(this.progressFill);\n this.progressLabel = el(\"span\", { class: \"sp-stats-progress-label\" });\n setText(this.progressLabel, \"\");\n progress.appendChild(track);\n progress.appendChild(this.progressLabel);\n\n this.element.appendChild(row);\n this.element.appendChild(progress);\n }\n\n /** Update stats from current feedbacks array + total count. */\n update(feedbacks: FeedbackResponse[], total: number): void {\n // Hide when there are no feedbacks at all\n if (total === 0) {\n this.element.hidden = true;\n return;\n }\n this.element.hidden = false;\n\n let openCount = 0;\n let resolvedCount = 0;\n let bugCount = 0;\n\n for (const fb of feedbacks) {\n if (fb.status === \"open\") openCount++;\n if (fb.status === \"resolved\") resolvedCount++;\n if (fb.type === \"bug\") bugCount++;\n }\n\n setText(this.valueOpen, String(openCount));\n setText(this.valueResolved, String(resolvedCount));\n setText(this.valueBugs, String(bugCount));\n\n // Percentage resolved (relative to visible feedbacks, not total)\n const visible = feedbacks.length;\n const pct = visible > 0 ? Math.round((resolvedCount / visible) * 100) : 0;\n\n // Animate fill width via rAF so the transition kicks in after the DOM update\n requestAnimationFrame(() => {\n this.progressFill.style.width = `${pct}%`;\n });\n\n const progressText = this.i18n[\"stats.progress\"].replace(\"{percent}\", String(pct));\n setText(this.progressLabel, progressText);\n }\n}\n","/**\n * Keyboard shortcuts system for the feedback panel.\n *\n * Gmail/GitHub-style single-key shortcuts:\n * J/K — navigate cards, R — resolve, D — delete,\n * F or / — focus search, X — toggle select, ? — help overlay.\n *\n * Active only when the panel is open. Ignores keypresses inside\n * input/textarea elements. Uses a Map<string, handler> for O(1) lookup.\n */\n\nimport { el, parseSvg, setText } from \"./dom-utils.js\";\nimport type { ThemeColors } from \"./styles/theme.js\";\n\n// ---------------------------------------------------------------------------\n// Icon\n// ---------------------------------------------------------------------------\n\nexport const ICON_KEYBOARD = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"2\" y=\"4\" width=\"20\" height=\"16\" rx=\"2\"/><path d=\"M6 8h.01\"/><path d=\"M10 8h.01\"/><path d=\"M14 8h.01\"/><path d=\"M18 8h.01\"/><path d=\"M6 12h.01\"/><path d=\"M18 12h.01\"/><path d=\"M8 16h8\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// i18n\n// ---------------------------------------------------------------------------\n\nexport const SHORTCUTS_I18N_EN = {\n \"shortcuts.title\": \"Keyboard shortcuts\",\n \"shortcuts.navigate\": \"Navigate feedbacks\",\n \"shortcuts.resolve\": \"Resolve / Reopen\",\n \"shortcuts.delete\": \"Delete\",\n \"shortcuts.search\": \"Focus search\",\n \"shortcuts.select\": \"Toggle selection\",\n \"shortcuts.help\": \"Show shortcuts\",\n \"shortcuts.close\": \"Close\",\n \"shortcuts.hint\": \"Keyboard shortcuts\",\n} as const;\n\nexport const SHORTCUTS_I18N_FR = {\n \"shortcuts.title\": \"Raccourcis clavier\",\n \"shortcuts.navigate\": \"Naviguer les feedbacks\",\n \"shortcuts.resolve\": \"Résoudre / Rouvrir\",\n \"shortcuts.delete\": \"Supprimer\",\n \"shortcuts.search\": \"Rechercher\",\n \"shortcuts.select\": \"Sélectionner\",\n \"shortcuts.help\": \"Raccourcis\",\n \"shortcuts.close\": \"Fermer\",\n \"shortcuts.hint\": \"Raccourcis clavier\",\n} as const;\n\nexport type ShortcutsI18n = typeof SHORTCUTS_I18N_EN;\ntype I18nKey = keyof ShortcutsI18n;\n\n// ---------------------------------------------------------------------------\n// Callbacks\n// ---------------------------------------------------------------------------\n\nexport interface ShortcutCallbacks {\n onNavigate: (direction: \"up\" | \"down\") => void;\n onResolve: () => void;\n onDelete: () => void;\n onFocusSearch: () => void;\n onToggleSelect: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Card focus helpers\n// ---------------------------------------------------------------------------\n\n/** Get the currently focused card index from the list container (-1 if none). */\nexport function getFocusedCardIndex(listContainer: HTMLElement): number {\n const cards = listContainer.querySelectorAll<HTMLElement>(\".sp-card\");\n for (let i = 0; i < cards.length; i++) {\n if (cards[i]?.classList.contains(\"sp-card--focused\")) return i;\n }\n return -1;\n}\n\n/** Focus a card by index in the list container. Clamps to valid range. */\nexport function focusCardByIndex(listContainer: HTMLElement, index: number): void {\n const cards = listContainer.querySelectorAll<HTMLElement>(\".sp-card\");\n if (cards.length === 0) return;\n\n // Remove previous focus\n for (const card of cards) {\n card.classList.remove(\"sp-card--focused\");\n }\n\n const clamped = Math.max(0, Math.min(index, cards.length - 1));\n const target = cards[clamped];\n if (!target) return;\n target.classList.add(\"sp-card--focused\");\n target.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n target.focus({ preventScroll: true });\n}\n\n// ---------------------------------------------------------------------------\n// Shortcut definitions (used to build help grid)\n// ---------------------------------------------------------------------------\n\ninterface ShortcutDef {\n keys: string[];\n label: I18nKey;\n}\n\nconst SHORTCUT_DEFS: ShortcutDef[] = [\n { keys: [\"J\", \"K\"], label: \"shortcuts.navigate\" },\n { keys: [\"R\"], label: \"shortcuts.resolve\" },\n { keys: [\"D\"], label: \"shortcuts.delete\" },\n { keys: [\"F\", \"/\"], label: \"shortcuts.search\" },\n { keys: [\"X\"], label: \"shortcuts.select\" },\n { keys: [\"?\"], label: \"shortcuts.help\" },\n { keys: [\"Esc\"], label: \"shortcuts.close\" },\n];\n\n// ---------------------------------------------------------------------------\n// CSS\n// ---------------------------------------------------------------------------\n\nexport const SHORTCUTS_CSS = /* css */ `\n /* ---- Help overlay backdrop ---- */\n\n .sp-shortcuts-overlay {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s ease;\n }\n\n .sp-shortcuts-overlay--visible {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* ---- Glassmorphism card ---- */\n\n .sp-shortcuts-card {\n width: 380px;\n max-width: calc(100vw - 32px);\n padding: 24px 28px 20px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n position: relative;\n transform: scale(0.92) translateY(8px);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-shortcuts-overlay--visible .sp-shortcuts-card {\n transform: scale(1) translateY(0);\n }\n\n /* ---- Title row ---- */\n\n .sp-shortcuts-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 700;\n color: var(--sp-text);\n margin-bottom: 18px;\n }\n\n .sp-shortcuts-title svg {\n width: 18px;\n height: 18px;\n color: var(--sp-text-secondary);\n flex-shrink: 0;\n }\n\n /* ---- Close button ---- */\n\n .sp-shortcuts-close {\n position: absolute;\n top: 16px;\n right: 16px;\n width: 28px;\n height: 28px;\n border-radius: 8px;\n border: none;\n background: transparent;\n color: var(--sp-text-tertiary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .sp-shortcuts-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-shortcuts-close svg {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Two-column grid ---- */\n\n .sp-shortcuts-grid {\n display: flex;\n flex-direction: column;\n gap: 10px;\n }\n\n .sp-shortcuts-row {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .sp-shortcuts-keys {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 80px;\n justify-content: flex-end;\n }\n\n .sp-shortcuts-separator {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n user-select: none;\n }\n\n /* ---- Key badge (<kbd> styling) ---- */\n\n .sp-kbd {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 26px;\n padding: 0 7px;\n border-radius: 6px;\n background: var(--sp-bg-hover);\n border: 1px solid var(--sp-border);\n box-shadow:\n inset 0 -1px 0 rgba(0, 0, 0, 0.08),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n font-family: ui-monospace, \"SF Mono\", \"Cascadia Code\", \"Segoe UI Mono\", Menlo, monospace;\n font-size: 12px;\n font-weight: 600;\n color: var(--sp-text);\n text-align: center;\n line-height: 1;\n user-select: none;\n }\n\n /* ---- Description text ---- */\n\n .sp-shortcuts-desc {\n font-size: 13px;\n color: var(--sp-text-secondary);\n line-height: 1.3;\n }\n\n /* ---- Hint button (bottom-right of panel) ---- */\n\n .sp-shortcuts-hint {\n width: 24px;\n height: 24px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-bg-hover);\n color: var(--sp-text-tertiary);\n font-family: ui-monospace, \"SF Mono\", \"Cascadia Code\", \"Segoe UI Mono\", Menlo, monospace;\n font-size: 12px;\n font-weight: 700;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n position: absolute;\n bottom: 12px;\n right: 12px;\n }\n\n .sp-shortcuts-hint:hover {\n background: var(--sp-accent-light);\n color: var(--sp-accent);\n border-color: var(--sp-accent);\n }\n\n .sp-shortcuts-hint::after {\n content: attr(aria-label);\n position: absolute;\n bottom: calc(100% + 6px);\n right: 0;\n padding: 4px 8px;\n border-radius: 6px;\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transform: translateY(4px);\n transition: opacity 0.15s ease, transform 0.15s ease;\n }\n\n .sp-shortcuts-hint:hover::after {\n opacity: 1;\n transform: translateY(0);\n }\n\n /* ---- Card focus highlight (navigation) ---- */\n\n .sp-card--focused {\n outline: 2px solid var(--sp-accent);\n outline-offset: -2px;\n border-radius: inherit;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n .sp-shortcuts-overlay,\n .sp-shortcuts-card,\n .sp-shortcuts-close,\n .sp-shortcuts-hint,\n .sp-shortcuts-hint::after {\n transition-duration: 0.01ms !important;\n }\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Close icon (small X) — reused from icons.ts pattern\n// ---------------------------------------------------------------------------\n\nconst ICON_CLOSE_SM = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`;\n\n// ---------------------------------------------------------------------------\n// KeyboardShortcuts\n// ---------------------------------------------------------------------------\n\nexport class KeyboardShortcuts {\n /** Help overlay element — append to shadow root. */\n readonly helpOverlay: HTMLElement;\n /** Small \"?\" hint button — append inside the panel. */\n readonly hintButton: HTMLButtonElement;\n\n private readonly keyMap: Map<string, () => void>;\n private readonly boundHandler: (e: KeyboardEvent) => void;\n private shadowRoot: ShadowRoot | HTMLElement | null = null;\n private enabled = false;\n private helpVisible = false;\n private destroyed = false;\n\n constructor(\n _colors: ThemeColors,\n callbacks: ShortcutCallbacks,\n private readonly i18n: ShortcutsI18n = SHORTCUTS_I18N_EN,\n ) {\n // Build key map (O(1) dispatch)\n this.keyMap = new Map<string, () => void>([\n [\"j\", () => callbacks.onNavigate(\"down\")],\n [\"k\", () => callbacks.onNavigate(\"up\")],\n [\"r\", () => callbacks.onResolve()],\n [\"d\", () => callbacks.onDelete()],\n [\"f\", () => callbacks.onFocusSearch()],\n [\"/\", () => callbacks.onFocusSearch()],\n [\"x\", () => callbacks.onToggleSelect()],\n [\"?\", () => this.toggleHelp()],\n ]);\n\n // Build DOM\n this.helpOverlay = this.buildOverlay();\n this.hintButton = this.buildHintButton();\n\n // Bind handler once\n this.boundHandler = (e: KeyboardEvent) => this.handleKeydown(e);\n }\n\n // -------------------------------------------------------------------------\n // Public API\n // -------------------------------------------------------------------------\n\n /** Enable shortcuts. Provide the shadow root (or document) to attach the listener. */\n enable(root?: ShadowRoot | HTMLElement): void {\n if (this.destroyed || this.enabled) return;\n if (root) this.shadowRoot = root;\n const target = this.shadowRoot ?? document;\n target.addEventListener(\"keydown\", this.boundHandler as EventListener);\n this.enabled = true;\n }\n\n /** Disable shortcuts (call when panel closes). */\n disable(): void {\n if (!this.enabled) return;\n const target = this.shadowRoot ?? document;\n target.removeEventListener(\"keydown\", this.boundHandler as EventListener);\n this.enabled = false;\n // Also hide help if visible\n if (this.helpVisible) this.hideHelp();\n }\n\n /** Show/hide help overlay. */\n toggleHelp(): void {\n if (this.helpVisible) {\n this.hideHelp();\n } else {\n this.showHelp();\n }\n }\n\n /** Destroy and clean up all listeners. */\n destroy(): void {\n if (this.destroyed) return;\n this.disable();\n this.helpOverlay.remove();\n this.hintButton.remove();\n this.destroyed = true;\n }\n\n // -------------------------------------------------------------------------\n // Keyboard handler\n // -------------------------------------------------------------------------\n\n private handleKeydown(e: KeyboardEvent): void {\n // Escape closes help overlay only (panel close handled elsewhere)\n if (e.key === \"Escape\") {\n if (this.helpVisible) {\n e.preventDefault();\n e.stopPropagation();\n this.hideHelp();\n }\n return;\n }\n\n // If help overlay is open, block all other shortcuts\n if (this.helpVisible) return;\n\n // Ignore when focus is in an input, textarea, or contenteditable\n const active = e.composedPath()[0] as HTMLElement | undefined;\n if (active) {\n const tag = active.tagName?.toLowerCase();\n if (tag === \"input\" || tag === \"textarea\" || tag === \"select\") return;\n if (active.isContentEditable) return;\n }\n\n // Ignore modified keys (Ctrl, Alt, Meta) — except Shift for \"?\"\n if (e.ctrlKey || e.altKey || e.metaKey) return;\n\n const handler = this.keyMap.get(e.key);\n if (handler) {\n e.preventDefault();\n e.stopPropagation();\n handler();\n }\n }\n\n // -------------------------------------------------------------------------\n // Help overlay visibility\n // -------------------------------------------------------------------------\n\n private showHelp(): void {\n this.helpVisible = true;\n this.helpOverlay.classList.add(\"sp-shortcuts-overlay--visible\");\n\n // Focus the close button for accessibility\n const closeBtn = this.helpOverlay.querySelector<HTMLButtonElement>(\".sp-shortcuts-close\");\n closeBtn?.focus();\n }\n\n private hideHelp(): void {\n this.helpVisible = false;\n this.helpOverlay.classList.remove(\"sp-shortcuts-overlay--visible\");\n }\n\n // -------------------------------------------------------------------------\n // DOM builders\n // -------------------------------------------------------------------------\n\n private buildOverlay(): HTMLElement {\n const overlay = el(\"div\", { class: \"sp-shortcuts-overlay\" });\n overlay.setAttribute(\"role\", \"dialog\");\n overlay.setAttribute(\"aria-modal\", \"true\");\n overlay.setAttribute(\"aria-label\", this.i18n[\"shortcuts.title\"]);\n\n // Click backdrop to close\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) this.hideHelp();\n });\n\n const card = el(\"div\", { class: \"sp-shortcuts-card\" });\n\n // Title\n const title = el(\"div\", { class: \"sp-shortcuts-title\" });\n title.appendChild(parseSvg(ICON_KEYBOARD));\n const titleText = el(\"span\");\n setText(titleText, this.i18n[\"shortcuts.title\"]);\n title.appendChild(titleText);\n card.appendChild(title);\n\n // Close button\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"sp-shortcuts-close\";\n closeBtn.setAttribute(\"aria-label\", this.i18n[\"shortcuts.close\"]);\n closeBtn.appendChild(parseSvg(ICON_CLOSE_SM));\n closeBtn.addEventListener(\"click\", () => this.hideHelp());\n card.appendChild(closeBtn);\n\n // Grid\n const grid = el(\"div\", { class: \"sp-shortcuts-grid\" });\n\n for (const def of SHORTCUT_DEFS) {\n const row = el(\"div\", { class: \"sp-shortcuts-row\" });\n\n const keysWrap = el(\"div\", { class: \"sp-shortcuts-keys\" });\n def.keys.forEach((key, i) => {\n if (i > 0) {\n const sep = el(\"span\", { class: \"sp-shortcuts-separator\" });\n setText(sep, \"/\");\n keysWrap.appendChild(sep);\n }\n const kbd = el(\"span\", { class: \"sp-kbd\" });\n setText(kbd, key);\n keysWrap.appendChild(kbd);\n });\n\n const desc = el(\"span\", { class: \"sp-shortcuts-desc\" });\n setText(desc, this.i18n[def.label]);\n\n row.appendChild(keysWrap);\n row.appendChild(desc);\n grid.appendChild(row);\n }\n\n card.appendChild(grid);\n overlay.appendChild(card);\n\n return overlay;\n }\n\n private buildHintButton(): HTMLButtonElement {\n const btn = document.createElement(\"button\");\n btn.className = \"sp-shortcuts-hint\";\n btn.setAttribute(\"aria-label\", this.i18n[\"shortcuts.hint\"]);\n setText(btn, \"?\");\n btn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.toggleHelp();\n });\n return btn;\n }\n}\n","import type { FeedbackResponse, FeedbackStatus, FeedbackType, PageScope } from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\nimport { PAGE_SIZE } from \"./constants.js\";\nimport { el, formatRelativeDate, parseSvg, setText } from \"./dom-utils.js\";\nimport type { EventBus, WidgetEvents } from \"./events.js\";\nimport { EXPORT_I18N_FR, ExportButton } from \"./export-utils.js\";\nimport { getTypeLabel, type TFunction } from \"./i18n/index.js\";\nimport {\n ICON_BUG,\n ICON_CHANGE,\n ICON_CHECK,\n ICON_CHEVRON_DOWN,\n ICON_CLOSE,\n ICON_DOT_OPEN,\n ICON_LAYERS,\n ICON_OTHER,\n ICON_QUESTION,\n ICON_SEARCH,\n ICON_TRASH,\n ICON_UNDO,\n} from \"./icons.js\";\nimport type { MarkerManager } from \"./markers.js\";\nimport { BULK_I18N_EN, BULK_I18N_FR, BulkActions } from \"./panel-bulk.js\";\nimport { DetailView } from \"./panel-detail.js\";\nimport { createPageGroupHeader, groupFeedbacksByPage, PanelSortControls, sortFeedbacks } from \"./panel-sort.js\";\nimport { PanelStats } from \"./panel-stats.js\";\nimport {\n focusCardByIndex,\n getFocusedCardIndex,\n KeyboardShortcuts,\n SHORTCUTS_I18N_EN,\n SHORTCUTS_I18N_FR,\n} from \"./shortcuts.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\n/**\n * Side panel (400px) with feedback history, filters, search, stats,\n * sort/group, bulk actions, export, detail view, and keyboard shortcuts.\n *\n * Lives inside the Shadow DOM.\n * Glassmorphism: glass background, staggered card animations,\n * loading states, resolve feedback with disabled state.\n */\nexport class Panel {\n private root: HTMLElement;\n private listContainer: HTMLElement;\n private searchInput: HTMLInputElement;\n private closeBtn: HTMLButtonElement;\n private deleteAllBtn: HTMLButtonElement;\n private activeFilters = new Set<string>([\"all\"]);\n private activeStatusFilter: \"all\" | FeedbackStatus = \"all\";\n private typeDropdownBtn!: HTMLButtonElement;\n private typeDropdownContainer!: HTMLElement;\n private typeDropdownMenu: HTMLElement | null = null;\n private typeDropdownOutsideHandler: ((e: MouseEvent) => void) | null = null;\n private statusSegmented!: HTMLElement;\n private typeOptions!: ReadonlyArray<{ value: string; label: string; icon: string; color: string; bg: string }>;\n private statusOptions!: ReadonlyArray<{\n value: \"all\" | FeedbackStatus;\n label: string;\n icon: string;\n color: string;\n bg: string;\n }>;\n private feedbacks: FeedbackResponse[] = [];\n private currentPage = 1;\n private totalFeedbacks = 0;\n private isLoadingMore = false;\n private isOpen = false;\n private searchTimeout: ReturnType<typeof setTimeout> | null = null;\n private loadController: AbortController | null = null;\n /** Tracks feedback IDs with in-flight mutations to prevent spam-click race conditions */\n private pendingMutations = new Set<string>();\n\n // New feature modules\n private readonly stats: PanelStats;\n private readonly sortControls: PanelSortControls;\n private readonly bulk: BulkActions;\n private readonly exportBtn: ExportButton;\n private readonly shortcuts: KeyboardShortcuts;\n private readonly detail: DetailView;\n private readonly shadowRoot: ShadowRoot;\n\n // i18n helpers\n private readonly bulkI18n: typeof BULK_I18N_EN;\n\n // Page scope — supplied by launcher so the panel can scope its results to\n // the current page (or template) and filter markers accordingly.\n private readonly getScope: () => PageScope;\n private readonly scopeAnnotationsByUrl: boolean;\n /** \"this\" = current url, \"template\" = url pattern, \"all\" = no scope filter */\n private activeScopeFilter: \"this\" | \"template\" | \"all\" = \"this\";\n private scopeSegmented!: HTMLElement;\n private scopeOptions!: ReadonlyArray<{ value: \"this\" | \"template\" | \"all\"; label: string }>;\n\n constructor(\n shadowRoot: ShadowRoot,\n private readonly colors: ThemeColors,\n private readonly bus: EventBus<WidgetEvents>,\n private readonly client: WidgetClient,\n private readonly projectName: string,\n private readonly markers: MarkerManager,\n private readonly t: TFunction,\n private readonly locale: string,\n pageScopeOptions?: { getScope: () => PageScope; scopeAnnotationsByUrl: boolean },\n ) {\n this.shadowRoot = shadowRoot;\n this.bulkI18n = locale === \"fr\" ? BULK_I18N_FR : BULK_I18N_EN;\n this.getScope = pageScopeOptions?.getScope ?? (() => ({ url: window.location.pathname, urlPattern: null }));\n this.scopeAnnotationsByUrl = pageScopeOptions?.scopeAnnotationsByUrl ?? true;\n\n this.root = el(\"div\", { class: \"sp-panel\" });\n this.root.setAttribute(\"role\", \"complementary\");\n this.root.setAttribute(\"aria-label\", this.t(\"panel.ariaLabel\"));\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n // --- Header ---\n const header = el(\"div\", { class: \"sp-panel-header\" });\n const title = el(\"span\", { class: \"sp-panel-title\" });\n setText(title, this.t(\"panel.title\"));\n\n this.closeBtn = document.createElement(\"button\");\n this.closeBtn.className = \"sp-panel-close\";\n this.closeBtn.setAttribute(\"aria-label\", this.t(\"panel.close\"));\n this.closeBtn.appendChild(parseSvg(ICON_CLOSE));\n this.closeBtn.addEventListener(\"click\", () => this.close());\n\n this.deleteAllBtn = document.createElement(\"button\");\n this.deleteAllBtn.className = \"sp-btn-delete-all\";\n this.deleteAllBtn.setAttribute(\"aria-label\", this.t(\"panel.deleteAll\"));\n this.deleteAllBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteAllLabel = document.createElement(\"span\");\n setText(deleteAllLabel, ` ${this.t(\"panel.deleteAll\")}`);\n this.deleteAllBtn.appendChild(deleteAllLabel);\n this.deleteAllBtn.addEventListener(\"click\", () => this.confirmDeleteAll());\n\n // Export button\n this.exportBtn = new ExportButton(colors, () => this.feedbacks);\n if (locale === \"fr\") this.exportBtn.setLabels(EXPORT_I18N_FR);\n\n const headerRight = el(\"div\", { class: \"sp-panel-header-right\" });\n headerRight.appendChild(this.exportBtn.element);\n headerRight.appendChild(this.deleteAllBtn);\n headerRight.appendChild(this.closeBtn);\n\n header.appendChild(title);\n header.appendChild(headerRight);\n\n // --- Stats ---\n this.stats = new PanelStats(colors, locale);\n\n // --- Filters ---\n const filters = el(\"div\", { class: \"sp-filters\" });\n\n // Search\n const searchWrap = el(\"div\", { class: \"sp-search-wrap\" });\n const searchIcon = parseSvg(ICON_SEARCH);\n searchIcon.setAttribute(\"class\", \"sp-search-icon\");\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"text\";\n this.searchInput.className = \"sp-search\";\n this.searchInput.placeholder = this.t(\"panel.search\");\n this.searchInput.setAttribute(\"aria-label\", this.t(\"panel.searchAria\"));\n this.searchInput.addEventListener(\"input\", () => {\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.searchTimeout = setTimeout(() => this.loadFeedbacks().catch(() => {}), 200);\n });\n searchWrap.appendChild(searchIcon);\n searchWrap.appendChild(this.searchInput);\n\n // Filter bar (type dropdown + status segmented + scope segmented).\n // The scope control gives users a fast way to widen results to \"this type\n // of page\" or \"all pages\" when the host provides a route template.\n const filterBar = el(\"div\", { class: \"sp-filter-bar\" });\n filterBar.appendChild(this.buildTypeDropdown());\n filterBar.appendChild(this.buildStatusSegmented());\n filterBar.appendChild(this.buildScopeSegmented());\n\n // Sort controls\n this.sortControls = new PanelSortControls(colors, () => this.renderList(), locale);\n\n filters.appendChild(searchWrap);\n filters.appendChild(filterBar);\n filters.appendChild(this.sortControls.element);\n\n // --- List ---\n this.listContainer = el(\"div\", { class: \"sp-list\" });\n this.listContainer.setAttribute(\"role\", \"list\");\n this.listContainer.setAttribute(\"aria-label\", this.t(\"panel.feedbackList\"));\n\n // --- Bulk Actions ---\n this.bulk = new BulkActions(\n colors,\n {\n onResolve: (ids) => this.bulkResolve(ids),\n onDelete: (ids) => this.bulkDelete(ids),\n },\n locale,\n );\n this.bulk.setListContainer(this.listContainer);\n\n // --- Detail View ---\n this.detail = new DetailView(\n colors,\n {\n onBack: () => this.detail.hide(),\n onResolve: async (fb) => {\n const newResolved = fb.status !== \"resolved\";\n await this.client.resolveFeedback(fb.id, newResolved);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onDelete: async (fb) => {\n await this.client.deleteFeedback(fb.id);\n this.bus.emit(\"feedback:deleted\", fb.id);\n await this.loadFeedbacks();\n this.detail.hide();\n },\n onGoToAnnotation: (fb) => {\n if (fb.annotations.length > 0) {\n const ann = fb.annotations[0];\n if (!ann) return;\n window.scrollTo({ left: ann.scrollX, top: ann.scrollY, behavior: \"smooth\" });\n this.markers.pinHighlight(fb);\n }\n },\n },\n locale,\n );\n\n // --- Keyboard Shortcuts ---\n const shortcutsI18n = (locale === \"fr\" ? SHORTCUTS_I18N_FR : SHORTCUTS_I18N_EN) as typeof SHORTCUTS_I18N_EN;\n this.shortcuts = new KeyboardShortcuts(\n colors,\n {\n onNavigate: (dir) => {\n const idx = getFocusedCardIndex(this.listContainer);\n focusCardByIndex(this.listContainer, dir === \"down\" ? idx + 1 : idx - 1);\n },\n onResolve: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"resolve\"]');\n if (btn) this.toggleResolve(fb, btn).catch(() => {});\n }\n },\n onDelete: () => {\n const fb = this.getFocusedFeedback();\n if (fb && !this.pendingMutations.has(fb.id)) {\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${CSS.escape(fb.id)}\"]`);\n const btn = card?.querySelector<HTMLButtonElement>('[data-action=\"delete\"]');\n if (btn) this.deleteFeedback(fb, btn).catch(() => {});\n }\n },\n onFocusSearch: () => this.searchInput.focus(),\n onToggleSelect: () => {\n const fb = this.getFocusedFeedback();\n if (fb) this.bulk.toggle(fb.id);\n },\n },\n shortcutsI18n,\n );\n\n // --- Assemble DOM ---\n this.root.appendChild(header);\n this.root.appendChild(this.stats.element);\n this.root.appendChild(filters);\n this.root.appendChild(this.listContainer);\n this.root.appendChild(this.bulk.barElement);\n this.root.appendChild(this.detail.element);\n this.root.appendChild(this.shortcuts.helpOverlay);\n this.root.appendChild(this.shortcuts.hintButton);\n shadowRoot.appendChild(this.root);\n\n // --- Event delegation on listContainer ---\n\n this.onListClick = (e: Event) => {\n const target = e.target as Element;\n\n // Bulk checkbox clicks are handled by BulkActions, skip\n if (target.closest(\".sp-bulk-checkbox\")) return;\n\n // Action buttons (expand, resolve, delete)\n const actionEl = target.closest<HTMLElement>(\"[data-action]\");\n if (actionEl) {\n e.stopPropagation();\n const card = actionEl.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (!feedback) return;\n\n const action = actionEl.dataset.action;\n if (action === \"expand\") {\n const message = card.querySelector<HTMLElement>(\".sp-card-message\");\n if (!message) return;\n const isExpanded = message.classList.toggle(\"sp-card-message--expanded\");\n setText(actionEl, isExpanded ? this.t(\"panel.showLess\") : this.t(\"panel.showMore\"));\n actionEl.setAttribute(\"aria-expanded\", String(isExpanded));\n } else if (action === \"resolve\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.toggleResolve(feedback, btn).catch(() => {});\n } else if (action === \"delete\") {\n if (this.pendingMutations.has(feedback.id)) return;\n const btn = actionEl as HTMLButtonElement;\n this.deleteFeedback(feedback, btn).catch(() => {});\n }\n return;\n }\n\n // Card click → open detail view\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (card) {\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n }\n };\n this.listContainer.addEventListener(\"click\", this.onListClick);\n\n this.onListKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key !== \"Enter\" && ke.key !== \" \") return;\n const target = ke.target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n // Only activate if the card itself is focused, not a button inside it\n if (!card || target !== card) return;\n ke.preventDefault();\n const feedbackId = card.dataset.feedbackId;\n const feedback = this.feedbacks.find((f) => f.id === feedbackId);\n if (feedback) {\n const number = this.feedbacks.indexOf(feedback) + 1;\n this.detail.show(feedback, number);\n }\n };\n this.listContainer.addEventListener(\"keydown\", this.onListKeydown);\n\n // mouseover/mouseout bubble (unlike mouseenter/mouseleave), enabling delegation\n this.onListMouseover = (e: Event) => {\n const target = (e as MouseEvent).target as Element;\n const card = target.closest<HTMLElement>(\".sp-card\");\n if (!card) return;\n const feedbackId = card.dataset.feedbackId;\n if (feedbackId) this.markers.highlight(feedbackId);\n };\n this.listContainer.addEventListener(\"mouseover\", this.onListMouseover);\n\n this.onListMouseout = (e: Event) => {\n const target = (e as MouseEvent).relatedTarget as Element | null;\n // Only clear highlight when leaving all cards (relatedTarget is outside listContainer)\n if (target && this.listContainer.contains(target)) return;\n this.markers.highlight(\"\");\n };\n this.listContainer.addEventListener(\"mouseout\", this.onListMouseout);\n\n // Events\n this.bus.on(\"panel:toggle\", (open) => {\n open ? this.open() : this.close();\n });\n\n // Keyboard handling: Escape to close + focus trap\n shadowRoot.addEventListener(\"keydown\", (e) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\" && this.isOpen) {\n // If detail view is open, close it instead\n if (this.detail.isVisible) {\n this.detail.hide();\n return;\n }\n this.close();\n return;\n }\n if (ke.key === \"Tab\" && this.isOpen) {\n const focusable = this.root.querySelectorAll<HTMLElement>(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])',\n );\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n if (!first || !last) return;\n const active = (shadowRoot as ShadowRoot).activeElement;\n if (ke.shiftKey && active === first) {\n ke.preventDefault();\n last.focus();\n } else if (!ke.shiftKey && active === last) {\n ke.preventDefault();\n first.focus();\n }\n }\n });\n\n // Listen for marker clicks\n this.onMarkerClick = ((e: CustomEvent) => {\n this.scrollToFeedback(e.detail.feedbackId);\n }) as EventListener;\n document.addEventListener(\"sp-marker-click\", this.onMarkerClick);\n }\n\n private onMarkerClick: EventListener;\n private onListClick: (e: Event) => void;\n private onListKeydown: (e: Event) => void;\n private onListMouseover: (e: Event) => void;\n private onListMouseout: (e: Event) => void;\n\n async open(): Promise<void> {\n if (this.isOpen) return;\n this.isOpen = true;\n this.root.classList.add(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"false\");\n this.bus.emit(\"open\");\n this.shortcuts.enable(this.shadowRoot);\n await this.loadFeedbacks();\n // Move focus into the panel (search input or close button)\n requestAnimationFrame(() => {\n if (this.searchInput) {\n this.searchInput.focus();\n } else {\n this.closeBtn.focus();\n }\n });\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.root.classList.remove(\"sp-panel--open\");\n this.root.setAttribute(\"aria-hidden\", \"true\");\n this.bus.emit(\"close\");\n this.shortcuts.disable();\n this.detail.hide();\n // Restore focus to the FAB\n const fab = (this.root.getRootNode() as ShadowRoot).querySelector<HTMLButtonElement>(\".sp-fab\");\n fab?.focus();\n }\n\n private showLoading(): void {\n this.listContainer.replaceChildren();\n const loading = el(\"div\", { class: \"sp-loading\" });\n loading.setAttribute(\"role\", \"status\");\n loading.setAttribute(\"aria-live\", \"polite\");\n loading.setAttribute(\"aria-label\", this.t(\"panel.loading\"));\n const spinner = el(\"div\", { class: \"sp-spinner\" });\n loading.appendChild(spinner);\n this.listContainer.appendChild(loading);\n }\n\n private showError(): void {\n this.listContainer.replaceChildren();\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const text = el(\"div\", { class: \"sp-empty-text\" });\n setText(text, this.t(\"panel.loadError\"));\n const retryBtn = document.createElement(\"button\");\n retryBtn.className = \"sp-btn-ghost\";\n retryBtn.style.marginTop = \"8px\";\n setText(retryBtn, this.t(\"panel.retry\"));\n retryBtn.addEventListener(\"click\", () => this.loadFeedbacks().catch(() => {}));\n empty.appendChild(text);\n empty.appendChild(retryBtn);\n this.listContainer.appendChild(empty);\n }\n\n private async loadFeedbacks(): Promise<void> {\n // Cancel any in-flight request to prevent stale responses from overwriting newer results\n this.loadController?.abort();\n this.loadController = new AbortController();\n const { signal } = this.loadController;\n\n // Reset to page 1 on fresh load (filter/search change)\n this.currentPage = 1;\n\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const statusFilter = this.activeStatusFilter === \"all\" ? undefined : this.activeStatusFilter;\n\n const scope = this.getScope();\n // Refresh scope-filter button visibility based on current scope (SPA nav).\n this.syncScopeAvailability();\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: 1,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (this.activeScopeFilter === \"this\") {\n options.url = scope.url;\n } else if (this.activeScopeFilter === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Only show spinner on first load (empty list) — otherwise keep current content visible\n const hasContent = this.feedbacks.length > 0;\n if (!hasContent) this.showLoading();\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (signal.aborted) return; // Stale response — a newer request superseded this one\n this.feedbacks = feedbacks;\n this.totalFeedbacks = total;\n this.stats.update(feedbacks, total);\n this.bulk.reset();\n this.renderList();\n // Markers always render only the current-URL slice — even when the panel\n // shows a wider scope (\"template\" or \"all\"), markers stay strictly local\n // so the user never sees out-of-context dots on the page.\n const markerFeedbacks = this.scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (signal.aborted) return; // Expected abort, not a real error\n if (!hasContent) this.showError();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private async loadMoreFeedbacks(): Promise<void> {\n if (this.isLoadingMore) return;\n this.isLoadingMore = true;\n\n // Capture current controller — if loadFeedbacks() runs while we're in-flight,\n // it replaces the controller, signaling that our results are stale.\n const controller = this.loadController;\n\n const nextPage = this.currentPage + 1;\n const search = this.searchInput.value.trim() || undefined;\n const typeFilter = this.activeFilters.has(\"all\") ? undefined : (Array.from(this.activeFilters)[0] as FeedbackType);\n const statusFilter = this.activeStatusFilter === \"all\" ? undefined : this.activeStatusFilter;\n\n const scope = this.getScope();\n const options: GetFeedbacksOptions & { page: number; limit: number } = {\n page: nextPage,\n limit: PAGE_SIZE,\n };\n if (typeFilter) options.type = typeFilter;\n if (statusFilter) options.status = statusFilter;\n if (search) options.search = search;\n if (this.activeScopeFilter === \"this\") {\n options.url = scope.url;\n } else if (this.activeScopeFilter === \"template\" && scope.urlPattern) {\n options.urlPattern = scope.urlPattern;\n }\n\n // Show spinner on the \"Load more\" button\n const loadMoreBtn = this.listContainer.querySelector<HTMLButtonElement>(\".sp-btn-load-more\");\n let restoreBtn: (() => void) | undefined;\n if (loadMoreBtn) restoreBtn = this.setButtonLoading(loadMoreBtn);\n\n try {\n const { feedbacks, total } = await this.client.getFeedbacks(this.projectName, options);\n if (controller !== this.loadController) return; // Filter/search changed — discard stale page\n this.currentPage = nextPage;\n this.totalFeedbacks = total;\n this.feedbacks = [...this.feedbacks, ...feedbacks];\n this.stats.update(this.feedbacks, total);\n this.renderList();\n const markerFeedbacks = this.scopeAnnotationsByUrl\n ? this.feedbacks.filter((f) => f.url === scope.url)\n : this.feedbacks;\n this.markers.render(markerFeedbacks);\n } catch (error) {\n if (restoreBtn) restoreBtn();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.isLoadingMore = false;\n }\n }\n\n private renderList(): void {\n this.listContainer.replaceChildren();\n\n if (this.feedbacks.length === 0) {\n const empty = el(\"div\", { class: \"sp-empty\" });\n empty.setAttribute(\"role\", \"status\");\n empty.setAttribute(\"aria-live\", \"polite\");\n const emptyText = el(\"div\", { class: \"sp-empty-text\" });\n setText(emptyText, this.t(\"panel.empty\"));\n empty.appendChild(emptyText);\n this.listContainer.appendChild(empty);\n return;\n }\n\n // Apply sorting\n const sorted = sortFeedbacks(this.feedbacks, this.sortControls.sortMode);\n\n // Select all bar\n const feedbackIds = sorted.map((f) => f.id);\n const selectAllBar = this.bulk.createSelectAllBar(feedbackIds, this.bulkI18n[\"bulk.selectAll\"]);\n this.listContainer.appendChild(selectAllBar);\n\n if (this.sortControls.groupByPage) {\n // Group by page rendering\n const groups = groupFeedbacksByPage(sorted);\n let globalIndex = 0;\n for (const [pagePath, groupFeedbacks] of groups) {\n const groupHeader = createPageGroupHeader(pagePath, groupFeedbacks.length, this.colors);\n this.listContainer.appendChild(groupHeader);\n\n const groupContent = el(\"div\", { class: \"sp-group-content\" });\n for (const feedback of groupFeedbacks) {\n const card = this.createCard(feedback, globalIndex + 1);\n card.style.setProperty(\"--sp-card-i\", String(globalIndex));\n groupContent.appendChild(card);\n globalIndex++;\n }\n this.listContainer.appendChild(groupContent);\n }\n } else {\n // Flat list rendering\n sorted.forEach((feedback, index) => {\n const card = this.createCard(feedback, index + 1);\n card.style.setProperty(\"--sp-card-i\", String(index));\n this.listContainer.appendChild(card);\n });\n }\n\n // \"Load more\" button when there are remaining feedbacks\n const remaining = this.totalFeedbacks - this.feedbacks.length;\n if (remaining > 0) {\n const loadMoreWrap = el(\"div\", { class: \"sp-load-more-wrap\" });\n const loadMoreBtn = document.createElement(\"button\");\n loadMoreBtn.className = \"sp-btn-ghost sp-btn-load-more\";\n setText(loadMoreBtn, this.t(\"panel.loadMore\").replace(\"{remaining}\", String(remaining)));\n loadMoreBtn.addEventListener(\"click\", () => this.loadMoreFeedbacks().catch(() => {}));\n loadMoreWrap.appendChild(loadMoreBtn);\n this.listContainer.appendChild(loadMoreWrap);\n }\n }\n\n private createCard(feedback: FeedbackResponse, number: number): HTMLElement {\n const isResolved = feedback.status === \"resolved\";\n const typeColor = getTypeColor(feedback.type, this.colors);\n\n const card = el(\"div\", {\n class: `sp-card ${isResolved ? \"sp-card--resolved\" : \"\"}`,\n });\n card.setAttribute(\"role\", \"listitem\");\n card.setAttribute(\"tabindex\", \"0\");\n card.setAttribute(\n \"aria-label\",\n `Feedback #${number}: ${getTypeLabel(feedback.type, this.t)} — ${feedback.message.slice(0, 80)}`,\n );\n card.dataset.feedbackId = feedback.id;\n\n // Color bar\n const bar = el(\"div\", { class: \"sp-card-bar\" });\n bar.style.background = isResolved ? \"#9ca3af\" : typeColor;\n\n // Body\n const body = el(\"div\", { class: \"sp-card-body\" });\n\n // Header: checkbox + #number + badge + date\n const header = el(\"div\", { class: \"sp-card-header\" });\n\n // Bulk checkbox — inline in the header row\n const checkbox = this.bulk.createCheckbox(feedback.id);\n header.appendChild(checkbox);\n\n const num = el(\"span\", { class: \"sp-card-number\" });\n setText(num, `#${number}`);\n\n const badge = el(\"span\", { class: \"sp-badge\" });\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n badge.style.background = typeBg;\n badge.style.color = typeColor;\n setText(badge, getTypeLabel(feedback.type, this.t));\n\n const date = el(\"span\", { class: \"sp-card-date\" });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(num);\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message\n const message = el(\"div\", { class: \"sp-card-message\" });\n setText(message, feedback.message);\n\n // Expand button\n const expandBtn = document.createElement(\"button\");\n expandBtn.className = \"sp-card-expand\";\n expandBtn.dataset.action = \"expand\";\n setText(expandBtn, this.t(\"panel.showMore\"));\n expandBtn.style.display = \"none\";\n expandBtn.setAttribute(\"aria-expanded\", \"false\");\n\n // Check if text is clamped (after render)\n requestAnimationFrame(() => {\n if (message.scrollHeight > message.clientHeight) {\n expandBtn.style.display = \"block\";\n }\n });\n\n // Footer: resolve button\n const footer = el(\"div\", { class: \"sp-card-footer\" });\n\n const resolveBtn = document.createElement(\"button\");\n resolveBtn.className = \"sp-btn-resolve\";\n resolveBtn.dataset.action = \"resolve\";\n if (isResolved) {\n resolveBtn.appendChild(parseSvg(ICON_UNDO));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.reopen\")}`);\n resolveBtn.appendChild(span);\n } else {\n resolveBtn.appendChild(parseSvg(ICON_CHECK));\n const span = document.createElement(\"span\");\n setText(span, ` ${this.t(\"panel.resolve\")}`);\n resolveBtn.appendChild(span);\n }\n\n const deleteBtn = document.createElement(\"button\");\n deleteBtn.className = \"sp-btn-delete\";\n deleteBtn.dataset.action = \"delete\";\n deleteBtn.appendChild(parseSvg(ICON_TRASH));\n const deleteBtnLabel = document.createElement(\"span\");\n setText(deleteBtnLabel, ` ${this.t(\"panel.delete\")}`);\n deleteBtn.appendChild(deleteBtnLabel);\n\n footer.appendChild(resolveBtn);\n footer.appendChild(deleteBtn);\n\n body.appendChild(header);\n body.appendChild(message);\n body.appendChild(expandBtn);\n body.appendChild(footer);\n\n card.appendChild(bar);\n card.appendChild(body);\n\n return card;\n }\n\n // ---------------------------------------------------------------------------\n // Bulk operations\n // ---------------------------------------------------------------------------\n\n private async bulkResolve(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.resolveFeedback(id, true)));\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n private async bulkDelete(ids: string[]): Promise<void> {\n try {\n await Promise.all(ids.map((id) => this.client.deleteFeedback(id)));\n for (const id of ids) this.bus.emit(\"feedback:deleted\", id);\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Existing methods (preserved)\n // ---------------------------------------------------------------------------\n\n private async confirmDeleteAll(): Promise<void> {\n const confirmed = await this.showConfirmDialog(\n this.t(\"panel.deleteAllConfirmTitle\"),\n this.t(\"panel.deleteAllConfirmMessage\"),\n );\n if (!confirmed) return;\n\n this.deleteAllBtn.disabled = true;\n try {\n await this.client.deleteAllFeedbacks(this.projectName);\n this.bus.emit(\"feedback:all-deleted\");\n await this.loadFeedbacks();\n } catch (error) {\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.deleteAllBtn.disabled = false;\n }\n }\n\n private showConfirmDialog(title: string, message: string): Promise<boolean> {\n return new Promise((resolve) => {\n const backdrop = el(\"div\", { class: \"sp-confirm-backdrop\" });\n\n const titleId = `sp-confirm-title-${Date.now()}`;\n const messageId = `sp-confirm-msg-${Date.now()}`;\n\n const dialog = el(\"div\", { class: \"sp-confirm-dialog\" });\n dialog.setAttribute(\"role\", \"alertdialog\");\n dialog.setAttribute(\"aria-modal\", \"true\");\n dialog.setAttribute(\"aria-labelledby\", titleId);\n dialog.setAttribute(\"aria-describedby\", messageId);\n\n const titleEl = el(\"div\", { class: \"sp-confirm-title\" });\n titleEl.id = titleId;\n setText(titleEl, title);\n\n const messageEl = el(\"div\", { class: \"sp-confirm-message\" });\n messageEl.id = messageId;\n setText(messageEl, message);\n\n const btnRow = el(\"div\", { class: \"sp-confirm-actions\" });\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.type = \"button\";\n cancelBtn.className = \"sp-btn-ghost\";\n setText(cancelBtn, this.t(\"panel.cancel\"));\n\n const confirmBtn = document.createElement(\"button\");\n confirmBtn.type = \"button\";\n confirmBtn.className = \"sp-btn-danger\";\n setText(confirmBtn, this.t(\"panel.confirmDelete\"));\n\n let closed = false;\n const close = (result: boolean) => {\n if (closed) return;\n closed = true;\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n dialog.style.transform = \"translateY(8px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n resolve(result);\n }, 200);\n };\n\n // Focus trap: Tab cycles between cancel and confirm\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n close(false);\n return;\n }\n if (ke.key === \"Tab\") {\n ke.preventDefault();\n const active = (backdrop.getRootNode() as ShadowRoot).activeElement;\n if (active === cancelBtn) {\n confirmBtn.focus();\n } else {\n cancelBtn.focus();\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n cancelBtn.addEventListener(\"click\", () => close(false));\n confirmBtn.addEventListener(\"click\", () => close(true));\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) close(false);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(confirmBtn);\n dialog.appendChild(titleEl);\n dialog.appendChild(messageEl);\n dialog.appendChild(btnRow);\n backdrop.appendChild(dialog);\n\n this.root.getRootNode() instanceof ShadowRoot\n ? (this.root.getRootNode() as ShadowRoot).appendChild(backdrop)\n : this.root.appendChild(backdrop);\n\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n dialog.style.transform = \"translateY(0) scale(1)\";\n cancelBtn.focus();\n });\n });\n }\n\n private setButtonLoading(btn: HTMLButtonElement): () => void {\n const snapshot = Array.from(btn.childNodes).map((n) => n.cloneNode(true));\n btn.disabled = true;\n btn.replaceChildren(el(\"div\", { class: \"sp-spinner sp-spinner--sm\" }));\n return () => {\n btn.replaceChildren(...snapshot);\n btn.disabled = false;\n };\n }\n\n private async deleteFeedback(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = this.setButtonLoading(btn);\n try {\n await this.client.deleteFeedback(feedback.id);\n this.bus.emit(\"feedback:deleted\", feedback.id);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private async toggleResolve(feedback: FeedbackResponse, btn: HTMLButtonElement): Promise<void> {\n this.pendingMutations.add(feedback.id);\n const restore = this.setButtonLoading(btn);\n try {\n const newResolved = feedback.status !== \"resolved\";\n await this.client.resolveFeedback(feedback.id, newResolved);\n await this.loadFeedbacks();\n } catch (error) {\n restore();\n this.bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n } finally {\n this.pendingMutations.delete(feedback.id);\n }\n }\n\n private buildTypeDropdown(): HTMLElement {\n this.typeOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.filterAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"question\",\n label: this.t(\"type.question\"),\n icon: ICON_QUESTION,\n color: this.colors.typeQuestion,\n bg: this.colors.typeQuestionBg,\n },\n {\n value: \"change\",\n label: this.t(\"type.change\"),\n icon: ICON_CHANGE,\n color: this.colors.typeChange,\n bg: this.colors.typeChangeBg,\n },\n {\n value: \"bug\",\n label: this.t(\"type.bug\"),\n icon: ICON_BUG,\n color: this.colors.typeBug,\n bg: this.colors.typeBugBg,\n },\n {\n value: \"other\",\n label: this.t(\"type.other\"),\n icon: ICON_OTHER,\n color: this.colors.typeOther,\n bg: this.colors.typeOtherBg,\n },\n ];\n\n this.typeDropdownContainer = el(\"div\", { class: \"sp-filter-dropdown\" });\n\n this.typeDropdownBtn = document.createElement(\"button\");\n this.typeDropdownBtn.type = \"button\";\n this.typeDropdownBtn.className = \"sp-filter-dropdown-btn\";\n this.typeDropdownBtn.setAttribute(\"aria-haspopup\", \"listbox\");\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n this.renderTypeDropdownTrigger();\n\n this.typeDropdownBtn.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n if (this.typeDropdownMenu) this.closeTypeDropdown();\n else this.openTypeDropdown();\n });\n\n this.typeDropdownContainer.appendChild(this.typeDropdownBtn);\n return this.typeDropdownContainer;\n }\n\n private renderTypeDropdownTrigger(): void {\n const active = this.typeOptions.find((o) => this.activeFilters.has(o.value)) ?? this.typeOptions[0];\n if (!active) return;\n\n this.typeDropdownBtn.replaceChildren();\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-color\", active.color);\n this.typeDropdownBtn.style.setProperty(\"--sp-chip-bg\", active.bg);\n this.typeDropdownBtn.dataset.filter = active.value;\n this.typeDropdownBtn.classList.toggle(\"sp-filter-dropdown-btn--filtered\", active.value !== \"all\");\n this.typeDropdownBtn.setAttribute(\"aria-label\", `${this.t(\"type.label\")}: ${active.label}`);\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__icon\" });\n iconWrap.appendChild(parseSvg(active.icon));\n this.typeDropdownBtn.appendChild(iconWrap);\n\n const labelWrap = el(\"span\", { class: \"sp-filter-dropdown-btn__label\" });\n const prefix = el(\"span\", { class: \"sp-filter-dropdown-btn__prefix\" });\n setText(prefix, this.t(\"type.label\"));\n const value = el(\"span\", { class: \"sp-filter-dropdown-btn__value\" });\n setText(value, active.label);\n labelWrap.appendChild(prefix);\n labelWrap.appendChild(value);\n this.typeDropdownBtn.appendChild(labelWrap);\n\n const chevron = el(\"span\", { class: \"sp-filter-dropdown-btn__chevron\" });\n chevron.appendChild(parseSvg(ICON_CHEVRON_DOWN));\n this.typeDropdownBtn.appendChild(chevron);\n }\n\n private openTypeDropdown(): void {\n this.typeDropdownMenu = el(\"div\", { class: \"sp-filter-dropdown-menu\" });\n this.typeDropdownMenu.setAttribute(\"role\", \"listbox\");\n this.typeDropdownMenu.setAttribute(\"aria-label\", this.t(\"type.label\"));\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"true\");\n\n for (const option of this.typeOptions) {\n const item = document.createElement(\"button\");\n item.type = \"button\";\n const isActive = this.activeFilters.has(option.value);\n item.className = `sp-filter-dropdown-option${isActive ? \" sp-filter-dropdown-option--active\" : \"\"}`;\n item.style.setProperty(\"--sp-chip-color\", option.color);\n item.style.setProperty(\"--sp-chip-bg\", option.bg);\n item.dataset.filter = option.value;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"aria-selected\", String(isActive));\n\n const iconWrap = el(\"span\", { class: \"sp-filter-dropdown-option__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n item.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-filter-dropdown-option__label\" });\n setText(labelEl, option.label);\n item.appendChild(labelEl);\n\n if (isActive) {\n const checkWrap = el(\"span\", { class: \"sp-filter-dropdown-option__check\" });\n checkWrap.appendChild(parseSvg(ICON_CHECK));\n item.appendChild(checkWrap);\n }\n\n item.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this.selectTypeFilter(option.value);\n });\n\n this.typeDropdownMenu.appendChild(item);\n }\n\n this.typeDropdownContainer.appendChild(this.typeDropdownMenu);\n\n requestAnimationFrame(() => {\n this.typeDropdownOutsideHandler = (e: MouseEvent) => {\n if (this.typeDropdownMenu && !this.typeDropdownContainer.contains(e.target as Node)) {\n this.closeTypeDropdown();\n }\n };\n document.addEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n });\n\n this.typeDropdownMenu.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.closeTypeDropdown();\n this.typeDropdownBtn.focus();\n }\n });\n }\n\n private closeTypeDropdown(): void {\n if (this.typeDropdownMenu) {\n this.typeDropdownMenu.remove();\n this.typeDropdownMenu = null;\n }\n this.typeDropdownBtn.setAttribute(\"aria-expanded\", \"false\");\n if (this.typeDropdownOutsideHandler) {\n document.removeEventListener(\"click\", this.typeDropdownOutsideHandler, true);\n this.typeDropdownOutsideHandler = null;\n }\n }\n\n private selectTypeFilter(value: string): void {\n this.activeFilters.clear();\n this.activeFilters.add(value);\n this.renderTypeDropdownTrigger();\n this.closeTypeDropdown();\n this.loadFeedbacks().catch(() => {});\n }\n\n private buildStatusSegmented(): HTMLElement {\n this.statusOptions = [\n {\n value: \"all\",\n label: this.t(\"panel.statusAll\"),\n icon: ICON_LAYERS,\n color: this.colors.accent,\n bg: this.colors.accentLight,\n },\n {\n value: \"open\",\n label: this.t(\"panel.statusOpen\"),\n icon: ICON_DOT_OPEN,\n color: this.colors.statusOpen,\n bg: this.colors.statusOpenBg,\n },\n {\n value: \"resolved\",\n label: this.t(\"panel.statusResolved\"),\n icon: ICON_CHECK,\n color: this.colors.statusResolved,\n bg: this.colors.statusResolvedBg,\n },\n ];\n\n this.statusSegmented = el(\"div\", { class: \"sp-segmented\", role: \"radiogroup\" });\n this.statusSegmented.setAttribute(\"aria-label\", this.t(\"status.label\"));\n\n for (const option of this.statusOptions) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = `sp-segmented__btn sp-segmented__btn--${option.value}`;\n btn.dataset.statusFilter = option.value;\n btn.setAttribute(\"role\", \"radio\");\n const isActive = this.activeStatusFilter === option.value;\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n if (isActive) btn.classList.add(\"sp-segmented__btn--active\");\n btn.style.setProperty(\"--sp-chip-color\", option.color);\n btn.style.setProperty(\"--sp-chip-bg\", option.bg);\n\n const iconWrap = el(\"span\", { class: \"sp-segmented__icon\" });\n iconWrap.appendChild(parseSvg(option.icon));\n btn.appendChild(iconWrap);\n\n const labelEl = el(\"span\", { class: \"sp-segmented__label\" });\n setText(labelEl, option.label);\n btn.appendChild(labelEl);\n\n btn.addEventListener(\"click\", () => this.selectStatusFilter(option.value));\n btn.addEventListener(\"keydown\", (e) => this.handleSegmentedKey(e, option.value));\n\n this.statusSegmented.appendChild(btn);\n }\n\n return this.statusSegmented;\n }\n\n private handleSegmentedKey(e: KeyboardEvent, current: \"all\" | FeedbackStatus): void {\n const values = this.statusOptions.map((o) => o.value);\n const idx = values.indexOf(current);\n let nextIdx: number;\n switch (e.key) {\n case \"ArrowLeft\":\n nextIdx = (idx - 1 + values.length) % values.length;\n break;\n case \"ArrowRight\":\n nextIdx = (idx + 1) % values.length;\n break;\n case \"Home\":\n nextIdx = 0;\n break;\n case \"End\":\n nextIdx = values.length - 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n const next = values[nextIdx];\n if (!next) return;\n this.selectStatusFilter(next);\n const btn = this.statusSegmented.querySelector<HTMLButtonElement>(`[data-status-filter=\"${next}\"]`);\n btn?.focus();\n }\n\n private selectStatusFilter(value: \"all\" | FeedbackStatus): void {\n this.activeStatusFilter = value;\n const buttons = this.statusSegmented.querySelectorAll<HTMLButtonElement>(\".sp-segmented__btn\");\n for (const btn of buttons) {\n const isActive = btn.dataset.statusFilter === value;\n btn.classList.toggle(\"sp-segmented__btn--active\", isActive);\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n }\n this.loadFeedbacks().catch(() => {});\n }\n\n /**\n * Build the page-scope segmented control: \"this page / this type / all\".\n * The \"this type\" button is hidden when the current scope has no urlPattern\n * (host did not provide one for this route). Visibility is refreshed on\n * every `loadFeedbacks` so SPA navigation stays consistent.\n */\n private buildScopeSegmented(): HTMLElement {\n this.scopeOptions = [\n { value: \"this\", label: this.t(\"scope.thisPage\") },\n { value: \"template\", label: this.t(\"scope.thisType\") },\n { value: \"all\", label: this.t(\"scope.all\") },\n ];\n\n this.scopeSegmented = el(\"div\", { class: \"sp-segmented sp-segmented--scope\", role: \"radiogroup\" });\n this.scopeSegmented.setAttribute(\"aria-label\", this.t(\"scope.label\"));\n\n for (const option of this.scopeOptions) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = `sp-segmented__btn sp-segmented__btn--scope-${option.value}`;\n btn.dataset.scopeFilter = option.value;\n btn.setAttribute(\"role\", \"radio\");\n const isActive = this.activeScopeFilter === option.value;\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n if (isActive) btn.classList.add(\"sp-segmented__btn--active\");\n\n const labelEl = el(\"span\", { class: \"sp-segmented__label\" });\n setText(labelEl, option.label);\n btn.appendChild(labelEl);\n\n btn.addEventListener(\"click\", () => this.selectScopeFilter(option.value));\n btn.addEventListener(\"keydown\", (e) => this.handleScopeKey(e, option.value));\n\n this.scopeSegmented.appendChild(btn);\n }\n\n // Initial visibility — \"this type\" only meaningful when scope has urlPattern\n this.syncScopeAvailability();\n return this.scopeSegmented;\n }\n\n private handleScopeKey(e: KeyboardEvent, current: \"this\" | \"template\" | \"all\"): void {\n const visibleValues = this.scopeOptions\n .map((o) => o.value)\n .filter((v) => {\n const btn = this.scopeSegmented.querySelector<HTMLButtonElement>(`[data-scope-filter=\"${v}\"]`);\n return btn && btn.style.display !== \"none\";\n });\n const idx = visibleValues.indexOf(current);\n if (idx < 0) return;\n let nextIdx: number;\n switch (e.key) {\n case \"ArrowLeft\":\n nextIdx = (idx - 1 + visibleValues.length) % visibleValues.length;\n break;\n case \"ArrowRight\":\n nextIdx = (idx + 1) % visibleValues.length;\n break;\n case \"Home\":\n nextIdx = 0;\n break;\n case \"End\":\n nextIdx = visibleValues.length - 1;\n break;\n default:\n return;\n }\n e.preventDefault();\n const next = visibleValues[nextIdx];\n if (!next) return;\n this.selectScopeFilter(next);\n const btn = this.scopeSegmented.querySelector<HTMLButtonElement>(`[data-scope-filter=\"${next}\"]`);\n btn?.focus();\n }\n\n private selectScopeFilter(value: \"this\" | \"template\" | \"all\"): void {\n this.activeScopeFilter = value;\n const buttons = this.scopeSegmented.querySelectorAll<HTMLButtonElement>(\".sp-segmented__btn\");\n for (const btn of buttons) {\n const isActive = btn.dataset.scopeFilter === value;\n btn.classList.toggle(\"sp-segmented__btn--active\", isActive);\n btn.setAttribute(\"aria-checked\", String(isActive));\n btn.tabIndex = isActive ? 0 : -1;\n }\n this.loadFeedbacks().catch(() => {});\n }\n\n /**\n * Hide the \"this type\" button when the current scope has no urlPattern, and\n * fall back to \"this page\" if it was the active selection. Called on every\n * `loadFeedbacks` so SPA navigation stays consistent.\n */\n private syncScopeAvailability(): void {\n if (!this.scopeSegmented) return;\n const scope = this.getScope();\n const templateBtn = this.scopeSegmented.querySelector<HTMLButtonElement>(`[data-scope-filter=\"template\"]`);\n if (!templateBtn) return;\n const showTemplate = !!scope.urlPattern;\n templateBtn.style.display = showTemplate ? \"\" : \"none\";\n if (!showTemplate && this.activeScopeFilter === \"template\") {\n this.activeScopeFilter = \"this\";\n this.selectScopeFilter(\"this\");\n }\n }\n\n /** Get the focused feedback (for keyboard shortcuts) */\n private getFocusedFeedback(): FeedbackResponse | undefined {\n const idx = getFocusedCardIndex(this.listContainer);\n if (idx < 0) return undefined;\n const card = this.listContainer.querySelectorAll<HTMLElement>(\".sp-card\")[idx];\n if (!card) return undefined;\n return this.feedbacks.find((f) => f.id === card.dataset.feedbackId);\n }\n\n scrollToFeedback(feedbackId: string): void {\n const escapedId = CSS.escape(feedbackId);\n const card = this.listContainer.querySelector<HTMLElement>(`[data-feedback-id=\"${escapedId}\"]`);\n if (card) {\n card.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n card.classList.add(\"sp-anim-flash\");\n card.addEventListener(\n \"animationend\",\n () => {\n card.classList.remove(\"sp-anim-flash\");\n },\n { once: true },\n );\n }\n }\n\n /** Refresh the panel after a new feedback is submitted */\n async refresh(): Promise<void> {\n if (this.isOpen) {\n await this.loadFeedbacks();\n }\n }\n\n /** Whether the panel is currently open — used by the launcher to coordinate marker refreshes. */\n get isCurrentlyOpen(): boolean {\n return this.isOpen;\n }\n\n destroy(): void {\n this.loadController?.abort();\n if (this.searchTimeout) clearTimeout(this.searchTimeout);\n this.listContainer.removeEventListener(\"click\", this.onListClick);\n this.listContainer.removeEventListener(\"keydown\", this.onListKeydown);\n this.listContainer.removeEventListener(\"mouseover\", this.onListMouseover);\n this.listContainer.removeEventListener(\"mouseout\", this.onListMouseout);\n document.removeEventListener(\"sp-marker-click\", this.onMarkerClick);\n this.closeTypeDropdown();\n this.sortControls.destroy();\n this.bulk.destroy();\n this.exportBtn.destroy();\n this.shortcuts.destroy();\n this.detail.destroy();\n this.root.remove();\n }\n}\n","// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\n/** Configuration options for the Siteping widget. */\nexport interface SitepingConfig {\n /** HTTP endpoint that receives feedbacks (e.g. '/api/siteping'). Required unless `store` is provided. */\n endpoint?: string | undefined;\n /** Required — project identifier used to scope feedbacks */\n projectName: string;\n /** Direct store for client-side mode. When set, bypasses HTTP and uses the store directly in the browser. */\n store?: SitepingStore | undefined;\n /** FAB position — defaults to 'bottom-right' */\n position?: \"bottom-right\" | \"bottom-left\";\n /** Accent color for the widget UI — defaults to '#0066ff' */\n accentColor?: string;\n /** Show the widget even in production — defaults to false */\n forceShow?: boolean;\n /** Enable debug logging of lifecycle events — defaults to false */\n debug?: boolean;\n /** Color theme — defaults to 'light' */\n theme?: \"light\" | \"dark\" | \"auto\";\n /** UI locale — defaults to 'en'. Built-in: en, fr, de, es, it, pt (Brazilian), ru. Any other string falls back to English. */\n locale?: \"en\" | \"fr\" | \"de\" | \"es\" | \"it\" | \"pt\" | \"ru\" | (string & {}) | undefined;\n /**\n * Returns the current page scope for annotations and panel filtering.\n * Called on initial markers load and on `instance.refresh()`.\n *\n * Default: `{ url: window.location.pathname, urlPattern: null }` — annotations\n * are scoped strictly to the current pathname.\n *\n * Apps with parameterized routes (e.g. React Router) should return both the\n * concrete URL and the route template (e.g. `/orders/:orderId`) so the panel\n * can offer a \"this type of page\" filter that groups feedbacks by template.\n */\n getPageScope?: (() => PageScope) | undefined;\n /**\n * When true (default), the widget filters initial markers and panel results\n * by `feedback.url === scope.url`, so annotations created on one page never\n * leak to other pages — even if their CSS selector accidentally matches.\n * Set to `false` to revert to the legacy project-wide behavior.\n */\n scopeAnnotationsByUrl?: boolean | undefined;\n /**\n * Capture a JPEG screenshot of the annotated area on submit. Defaults to\n * `false` — opt-in because:\n *\n * - it adds runtime weight (~40 KB gzip dynamic chunk for html2canvas,\n * loaded only on first capture),\n * - it embeds page content in the feedback (privacy/GDPR consideration —\n * inform end users in your widget host UI when enabling).\n *\n * `html2canvas` ships as a regular dependency of `@siteping/widget` so the\n * dynamic import always resolves; you don't need to install anything extra.\n *\n * **Masking sensitive elements:** add `data-siteping-ignore=\"true\"` to any\n * element you do NOT want captured (password fields, credit-card forms,\n * API tokens shown in the UI, etc.). The capture predicate skips matching\n * elements *and their descendants*. Do this BEFORE turning on screenshots\n * in production — once a feedback is saved, the screenshot is in your DB\n * (or object storage) regardless of what was on the page.\n */\n enableScreenshot?: boolean | undefined;\n /** Called when the widget is skipped (production mode, mobile viewport) */\n onSkip?: (reason: \"production\" | \"mobile\") => void;\n\n // Events\n /** Called when the feedback panel is opened. */\n onOpen?: () => void;\n /** Called when the feedback panel is closed. */\n onClose?: () => void;\n onFeedbackSent?: (feedback: FeedbackResponse) => void;\n onError?: (error: Error) => void;\n /** Called when the user starts drawing an annotation. */\n onAnnotationStart?: () => void;\n /** Called when the user finishes drawing an annotation. */\n onAnnotationEnd?: () => void;\n}\n\n/** Instance returned by initSiteping() with lifecycle methods. */\nexport interface SitepingInstance {\n /** Remove the widget from the DOM and clean up all listeners. */\n destroy: () => void;\n /** Open the panel programmatically */\n open: () => void;\n /** Close the panel */\n close: () => void;\n /** Reload feedbacks from server */\n refresh: () => void;\n /** Subscribe to a public widget event */\n on: <K extends keyof SitepingPublicEvents>(\n event: K,\n listener: (...args: SitepingPublicEvents[K]) => void,\n ) => () => void;\n /** Unsubscribe from a public widget event */\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => void;\n}\n\n/** Events exposed to consumers via SitepingInstance.on / .off */\nexport interface SitepingPublicEvents {\n \"feedback:sent\": [FeedbackResponse];\n \"feedback:deleted\": [string];\n \"panel:open\": [];\n \"panel:close\": [];\n}\n\n// ---------------------------------------------------------------------------\n// Feedback\n// ---------------------------------------------------------------------------\n\n/** Single source of truth for feedback types — used by both TS types and Zod schemas. */\nexport const FEEDBACK_TYPES = [\"question\", \"change\", \"bug\", \"other\"] as const;\nexport type FeedbackType = (typeof FEEDBACK_TYPES)[number];\n\n/** Single source of truth for feedback statuses. */\nexport const FEEDBACK_STATUSES = [\"open\", \"resolved\"] as const;\nexport type FeedbackStatus = (typeof FEEDBACK_STATUSES)[number];\n\n/**\n * Page scope returned by `SitepingConfig.getPageScope()`.\n *\n * - `url`: concrete page identifier — usually `window.location.pathname`,\n * used as the strict scope for marker rendering.\n * - `urlPattern`: optional parameterized template (e.g. `/orders/:orderId`)\n * used by the panel's \"this type of page\" filter to group feedbacks across\n * instances of the same page kind.\n */\nexport interface PageScope {\n url: string;\n urlPattern: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Abstract Store — adapter pattern\n// ---------------------------------------------------------------------------\n\n/** Input for creating a feedback record in the store. */\nexport interface FeedbackCreateInput {\n projectName: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n url: string;\n /**\n * Optional parameterized URL template (e.g. `/orders/:orderId`) for the page\n * where the feedback was created. Allows the panel to filter feedbacks by\n * \"this type of page\" across different instances. Null when the host did not\n * provide a `getPageScope` callback or the route has no template.\n */\n urlPattern?: string | null | undefined;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n clientId: string;\n annotations: AnnotationCreateInput[];\n /**\n * Base64 JPEG `data:` URL captured by the widget at submit time.\n *\n * Adapters with a configured `ScreenshotStorage` are expected to upload\n * this and persist the returned URL on `FeedbackRecord.screenshotUrl`.\n * Adapters without storage may persist the data URL inline (memory /\n * localStorage / dev) — the widget then renders it directly.\n */\n screenshotDataUrl?: string | null | undefined;\n}\n\n/** Input for a single annotation when creating a feedback. */\nexport interface AnnotationCreateInput {\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId?: string | undefined;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n /**\n * Semantic anchor identifier from the closest ancestor's `data-feedback-anchor`\n * attribute. When set, this is the most stable re-anchoring signal because\n * hosts deliberately place these on layout/section roots that survive DOM\n * refactors and viewport changes. Null when no semantic ancestor exists.\n */\n anchorKey?: string | null | undefined;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n}\n\n/** Query parameters for fetching feedbacks. */\nexport interface FeedbackQuery {\n projectName: string;\n type?: FeedbackType | undefined;\n status?: FeedbackStatus | undefined;\n search?: string | undefined;\n page?: number | undefined;\n limit?: number | undefined;\n /**\n * Filter to feedbacks created on this exact URL (path). Used by the panel's\n * \"this page\" filter and by the markers loader to keep page scopes isolated.\n */\n url?: string | undefined;\n /**\n * Filter to feedbacks created on this URL pattern (e.g. `/orders/:orderId`).\n * Used by the panel's \"this type of page\" filter to group feedbacks across\n * different concrete instances of the same template.\n */\n urlPattern?: string | undefined;\n}\n\n/** Update payload for patching a feedback. */\nexport interface FeedbackUpdateInput {\n status: FeedbackStatus;\n resolvedAt: Date | null;\n}\n\n/** A persisted feedback record returned by the store. */\nexport interface FeedbackRecord {\n id: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n projectName: string;\n url: string;\n /**\n * Parameterized URL template the feedback was created on.\n * Null for legacy records or hosts without `getPageScope`.\n */\n urlPattern: string | null;\n authorName: string;\n authorEmail: string;\n viewport: string;\n userAgent: string;\n clientId: string;\n resolvedAt: Date | null;\n createdAt: Date;\n updatedAt: Date;\n annotations: AnnotationRecord[];\n /**\n * URL the widget renders as `<img src>`. Either an `https://...` from a\n * configured `ScreenshotStorage`, or a `data:image/jpeg;base64,...` URL\n * inline-persisted by adapters without storage. Null when no screenshot\n * was captured (legacy records, capture failed, or host disabled it).\n */\n screenshotUrl: string | null;\n}\n\n/** A persisted annotation record returned by the store. */\nexport interface AnnotationRecord {\n id: string;\n feedbackId: string;\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId: string | null;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n /**\n * Semantic anchor identifier from `data-feedback-anchor`. Null for legacy\n * annotations or those drawn outside any anchored region.\n */\n anchorKey: string | null;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n createdAt: Date;\n}\n\n// ---------------------------------------------------------------------------\n// Store errors — throw these from adapter implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Thrown when a record is not found during update or delete.\n *\n * Handlers translate this to HTTP 404. Adapters MUST throw this (not\n * ORM-specific errors) so the handler layer remains ORM-agnostic.\n */\nexport class StoreNotFoundError extends Error {\n readonly code = \"STORE_NOT_FOUND\" as const;\n constructor(message = \"Record not found\") {\n super(message);\n this.name = \"StoreNotFoundError\";\n }\n}\n\n/**\n * Thrown when a unique constraint is violated (e.g. duplicate `clientId`).\n *\n * Handlers use this to return the existing record instead of failing.\n */\nexport class StoreDuplicateError extends Error {\n readonly code = \"STORE_DUPLICATE\" as const;\n constructor(message = \"Duplicate record\") {\n super(message);\n this.name = \"StoreDuplicateError\";\n }\n}\n\n/** Type guard — works for `StoreNotFoundError` and ORM-specific equivalents (e.g. Prisma P2025). */\nexport function isStoreNotFound(error: unknown): boolean {\n if (error instanceof StoreNotFoundError) return true;\n // Backwards compat: Prisma's P2025\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code: string }).code === \"P2025\";\n}\n\n/** Type guard — works for `StoreDuplicateError` and ORM-specific equivalents (e.g. Prisma P2002). */\nexport function isStoreDuplicate(error: unknown): boolean {\n if (error instanceof StoreDuplicateError) return true;\n // Backwards compat: Prisma's P2002\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code: string }).code === \"P2002\";\n}\n\n// ---------------------------------------------------------------------------\n// Store helpers — shared conversion logic for adapters\n// ---------------------------------------------------------------------------\n\n/** Flatten a widget `AnnotationPayload` (nested anchor + rect) into a flat `AnnotationCreateInput`. */\nexport function flattenAnnotation(ann: AnnotationPayload): AnnotationCreateInput {\n return {\n cssSelector: ann.anchor.cssSelector,\n xpath: ann.anchor.xpath,\n textSnippet: ann.anchor.textSnippet,\n elementTag: ann.anchor.elementTag,\n elementId: ann.anchor.elementId,\n textPrefix: ann.anchor.textPrefix,\n textSuffix: ann.anchor.textSuffix,\n fingerprint: ann.anchor.fingerprint,\n neighborText: ann.anchor.neighborText,\n anchorKey: ann.anchor.anchorKey ?? null,\n xPct: ann.rect.xPct,\n yPct: ann.rect.yPct,\n wPct: ann.rect.wPct,\n hPct: ann.rect.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Abstract Store — adapter pattern\n// ---------------------------------------------------------------------------\n\n/**\n * Abstract storage interface for Siteping.\n *\n * Any adapter (Prisma, Drizzle, raw SQL, localStorage, etc.) implements this\n * interface. The HTTP handler and widget `StoreClient` operate against\n * `SitepingStore`, decoupled from the storage backend.\n *\n * ## Error contract\n *\n * - **`updateFeedback` / `deleteFeedback`**: throw `StoreNotFoundError` when\n * the record does not exist.\n * - **`createFeedback`**: either return the existing record on duplicate\n * `clientId` (idempotent) or throw `StoreDuplicateError`. The handler\n * handles both patterns.\n * - Other methods should not throw on empty results — return empty arrays or `null`.\n */\nexport interface SitepingStore {\n /** Create a feedback with its annotations. Idempotent on `clientId` — return existing record on duplicate, or throw `StoreDuplicateError`. */\n createFeedback(data: FeedbackCreateInput): Promise<FeedbackRecord>;\n /** Paginated query with optional filters. Returns empty array (not error) when no results. */\n getFeedbacks(query: FeedbackQuery): Promise<{ feedbacks: FeedbackRecord[]; total: number }>;\n /** Lookup by client-generated UUID. Returns `null` (not error) when not found. */\n findByClientId(clientId: string): Promise<FeedbackRecord | null>;\n /** Update status/resolvedAt. Throws `StoreNotFoundError` if `id` does not exist. */\n updateFeedback(id: string, data: FeedbackUpdateInput): Promise<FeedbackRecord>;\n /** Delete a single record. Throws `StoreNotFoundError` if `id` does not exist. */\n deleteFeedback(id: string): Promise<void>;\n /** Bulk delete all feedbacks for a project. No-op (not error) if none exist. */\n deleteAllFeedbacks(projectName: string): Promise<void>;\n}\n\n/** Payload sent from the widget to the server when submitting feedback. */\nexport interface FeedbackPayload {\n projectName: string;\n type: FeedbackType;\n message: string;\n url: string;\n /**\n * Parameterized URL template (e.g. `/orders/:orderId`) supplied by\n * `SitepingConfig.getPageScope()`. Null when the host did not provide one.\n */\n urlPattern?: string | null | undefined;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n annotations: AnnotationPayload[];\n /** Client-generated UUID for deduplication */\n clientId: string;\n /**\n * Base64 JPEG `data:` URL of the annotated area. Captured by the widget\n * when `enableScreenshot: true` is set in `SitepingConfig`. Null when\n * disabled or when capture failed silently.\n */\n screenshotDataUrl?: string | null | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Annotation — multi-selector anchoring (Hypothesis / W3C Web Annotation)\n// ---------------------------------------------------------------------------\n\n/** DOM anchoring data for re-attaching annotations to page elements. */\nexport interface AnchorData {\n /** CSS selector generated by @medv/finder — primary anchor */\n cssSelector: string;\n /** XPath — fallback 1 */\n xpath: string;\n /** First ~120 chars of element innerText — empty string if none */\n textSnippet: string;\n /** Tag name for validation (e.g. \"DIV\", \"SECTION\") */\n elementTag: string;\n /** Element id attribute if available — most stable */\n elementId?: string | undefined;\n /** ~32 chars of text before this element in document flow (disambiguation) */\n textPrefix: string;\n /** ~32 chars of text after this element in document flow (disambiguation) */\n textSuffix: string;\n /** Structural fingerprint: \"childCount:siblingIdx:attrHash\" */\n fingerprint: string;\n /** Text content of adjacent sibling elements (context) */\n neighborText: string;\n /**\n * Semantic anchor identifier from the closest ancestor's `data-feedback-anchor`\n * attribute. When set, this is the highest-priority re-anchoring signal —\n * hosts deliberately place these on layout/section roots that survive\n * viewport changes and DOM refactors.\n */\n anchorKey?: string | null | undefined;\n}\n\n/** Drawn rectangle coordinates as percentages relative to the anchor element. */\nexport interface RectData {\n /** X offset as fraction of anchor element width — must be in range [0, 1] */\n xPct: number;\n /** Y offset as fraction of anchor element height — must be in range [0, 1] */\n yPct: number;\n /** Width as fraction of anchor element width — must be in range [0, 1] */\n wPct: number;\n /** Height as fraction of anchor element height — must be in range [0, 1] */\n hPct: number;\n}\n\n/** Annotation data sent as part of a feedback submission. */\nexport interface AnnotationPayload {\n anchor: AnchorData;\n rect: RectData;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n}\n\n// ---------------------------------------------------------------------------\n// API responses\n// ---------------------------------------------------------------------------\n\n/** Feedback record as returned by the API (dates serialized as strings). */\nexport interface FeedbackResponse {\n id: string;\n projectName: string;\n type: FeedbackType;\n message: string;\n status: FeedbackStatus;\n url: string;\n /** Parameterized URL template the feedback was created on, or null. */\n urlPattern: string | null;\n viewport: string;\n userAgent: string;\n authorName: string;\n authorEmail: string;\n resolvedAt: string | null;\n createdAt: string;\n updatedAt: string;\n annotations: AnnotationResponse[];\n /** Screenshot URL (data: or http:) — see `FeedbackRecord.screenshotUrl`. */\n screenshotUrl: string | null;\n}\n\n/** Annotation record as returned by the API. */\nexport interface AnnotationResponse {\n id: string;\n feedbackId: string;\n cssSelector: string;\n xpath: string;\n textSnippet: string;\n elementTag: string;\n elementId: string | null;\n textPrefix: string;\n textSuffix: string;\n fingerprint: string;\n neighborText: string;\n /** Semantic anchor identifier from `data-feedback-anchor`, or null. */\n anchorKey: string | null;\n xPct: number;\n yPct: number;\n wPct: number;\n hPct: number;\n scrollX: number;\n scrollY: number;\n viewportW: number;\n viewportH: number;\n devicePixelRatio: number;\n createdAt: string;\n}\n","import {\n type AnnotationRecord,\n type AnnotationResponse,\n type FeedbackPayload,\n type FeedbackRecord,\n type FeedbackResponse,\n flattenAnnotation,\n type SitepingStore,\n} from \"@siteping/core\";\nimport type { GetFeedbacksOptions, WidgetClient } from \"./api-client.js\";\n\n/**\n * `WidgetClient` implementation that delegates directly to a `SitepingStore`.\n *\n * Used in client-side mode — the widget calls the store in-process instead of\n * making HTTP requests. Handles the same conversions the HTTP handler normally\n * performs: flattening annotations and serializing dates.\n */\nexport class StoreClient implements WidgetClient {\n constructor(\n private readonly store: SitepingStore,\n private readonly projectName: string,\n ) {}\n\n async sendFeedback(payload: FeedbackPayload): Promise<FeedbackResponse> {\n const record = await this.store.createFeedback({\n projectName: payload.projectName,\n type: payload.type,\n message: payload.message,\n status: \"open\",\n url: payload.url,\n urlPattern: payload.urlPattern ?? null,\n viewport: payload.viewport,\n userAgent: payload.userAgent,\n authorName: payload.authorName,\n authorEmail: payload.authorEmail,\n clientId: payload.clientId,\n annotations: payload.annotations.map(flattenAnnotation),\n screenshotDataUrl: payload.screenshotDataUrl ?? null,\n });\n\n return toResponse(record);\n }\n\n async getFeedbacks(\n projectName: string,\n options?: GetFeedbacksOptions,\n ): Promise<{ feedbacks: FeedbackResponse[]; total: number }> {\n const { feedbacks, total } = await this.store.getFeedbacks({\n projectName,\n page: options?.page,\n limit: options?.limit,\n type: options?.type,\n status: options?.status,\n search: options?.search,\n url: options?.url,\n urlPattern: options?.urlPattern,\n });\n\n return { feedbacks: feedbacks.map(toResponse), total };\n }\n\n async resolveFeedback(id: string, resolved: boolean): Promise<FeedbackResponse> {\n const record = await this.store.updateFeedback(id, {\n status: resolved ? \"resolved\" : \"open\",\n resolvedAt: resolved ? new Date() : null,\n });\n return toResponse(record);\n }\n\n async deleteFeedback(id: string): Promise<void> {\n await this.store.deleteFeedback(id);\n }\n\n async deleteAllFeedbacks(projectName: string): Promise<void> {\n await this.store.deleteAllFeedbacks(projectName);\n }\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackRecord (Date) → FeedbackResponse (string) serialization\n// ---------------------------------------------------------------------------\n\nfunction toResponse(record: FeedbackRecord): FeedbackResponse {\n return {\n id: record.id,\n projectName: record.projectName,\n type: record.type,\n message: record.message,\n status: record.status,\n url: record.url,\n urlPattern: record.urlPattern ?? null,\n viewport: record.viewport,\n userAgent: record.userAgent,\n authorName: record.authorName,\n authorEmail: record.authorEmail,\n resolvedAt: record.resolvedAt?.toISOString() ?? null,\n createdAt: record.createdAt.toISOString(),\n updatedAt: record.updatedAt.toISOString(),\n annotations: record.annotations.map(toAnnotationResponse),\n screenshotUrl: record.screenshotUrl ?? null,\n };\n}\n\nfunction toAnnotationResponse(ann: AnnotationRecord): AnnotationResponse {\n return {\n id: ann.id,\n feedbackId: ann.feedbackId,\n cssSelector: ann.cssSelector,\n xpath: ann.xpath,\n textSnippet: ann.textSnippet,\n elementTag: ann.elementTag,\n elementId: ann.elementId,\n textPrefix: ann.textPrefix,\n textSuffix: ann.textSuffix,\n fingerprint: ann.fingerprint,\n neighborText: ann.neighborText,\n anchorKey: ann.anchorKey ?? null,\n xPct: ann.xPct,\n yPct: ann.yPct,\n wPct: ann.wPct,\n hPct: ann.hPct,\n scrollX: ann.scrollX,\n scrollY: ann.scrollY,\n viewportW: ann.viewportW,\n viewportH: ann.viewportH,\n devicePixelRatio: ann.devicePixelRatio,\n createdAt: ann.createdAt.toISOString(),\n };\n}\n","/**\n * CSS keyframes and animation utilities — Glassmorphism edition.\n *\n * Uses CSS-only spring animations via linear() timing function\n * and refined easing curves for premium motion design.\n */\n\n// Spring easing — computed from a spring simulation (damping: 15, stiffness: 100)\nconst SPRING_LINEAR = `linear(0, 0.006, 0.025, 0.06, 0.11, 0.17, 0.25, 0.34, 0.45, 0.56, 0.67, 0.78, 0.88, 0.95, 1.01, 1.04, 1.05, 1.04, 1.02, 1, 0.99, 1)`;\n\n// Ease-out-expo — fast start, smooth deceleration\nconst EASE_OUT_EXPO = `cubic-bezier(0.16, 1, 0.3, 1)`;\n\n// Spring overshoot — bouncy entrance\nconst SPRING_OVERSHOOT = `cubic-bezier(0.34, 1.56, 0.64, 1)`;\n\n// Smooth decel — for glass transitions\nconst EASE_OUT_QUART = `cubic-bezier(0.25, 1, 0.5, 1)`;\n\nexport const ANIMATION_CSS = `\n /* ---- Keyframes ---- */\n\n @keyframes sp-fab-in {\n from {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n to {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes sp-fab-glow {\n 0%, 100% { box-shadow: 0 4px 20px var(--sp-accent-glow), 0 2px 8px rgba(0, 0, 0, 0.08); }\n 50% { box-shadow: 0 4px 28px var(--sp-accent-glow), 0 2px 12px rgba(0, 0, 0, 0.1); }\n }\n\n @keyframes sp-marker-in {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 60% {\n transform: scale(1.2);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n }\n }\n\n @keyframes sp-pulse-ring {\n 0% {\n box-shadow: 0 0 0 0 var(--sp-accent-glow);\n }\n 70% {\n box-shadow: 0 0 0 8px transparent;\n }\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n @keyframes sp-flash-bg {\n 0% { background-color: var(--sp-accent-light); }\n 100% { background-color: transparent; }\n }\n\n @keyframes sp-slide-up {\n from {\n transform: translateY(8px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n @keyframes sp-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes sp-shimmer {\n 0% { background-position: -200% 0; }\n 100% { background-position: 200% 0; }\n }\n\n /* ---- Animation classes ---- */\n\n .sp-anim-fab-in {\n animation: sp-fab-in 0.5s ${SPRING_LINEAR} both;\n }\n\n .sp-anim-marker-in {\n animation: sp-marker-in 0.35s ${SPRING_OVERSHOOT} both;\n }\n\n .sp-anim-pulse {\n animation: sp-pulse-ring 0.7s ease-out;\n }\n\n .sp-anim-flash {\n animation: sp-flash-bg 0.5s ${EASE_OUT_QUART};\n }\n\n .sp-anim-slide-up {\n animation: sp-slide-up 0.3s ${EASE_OUT_EXPO} both;\n }\n\n .sp-anim-fade-in {\n animation: sp-fade-in 0.2s ease-out both;\n }\n\n /* ---- Transition utilities ---- */\n\n .sp-panel {\n transform: translateX(110%);\n transition: transform 0.4s ${EASE_OUT_EXPO};\n }\n\n .sp-panel.sp-panel--open {\n transform: translateX(0);\n }\n\n .sp-radial-item {\n opacity: 0;\n pointer-events: none;\n transform: translate(0, 0) scale(0.8);\n transition:\n transform 0.35s ${SPRING_OVERSHOOT},\n opacity 0.2s ease,\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n }\n\n .sp-radial-item.sp-radial-item--open {\n opacity: 1;\n pointer-events: auto;\n }\n\n /* Stagger delay via CSS custom property --sp-i */\n .sp-radial-item {\n transition-delay: calc(var(--sp-i, 0) * 50ms);\n }\n\n /* ---- Card stagger animation ---- */\n\n @keyframes sp-card-in {\n from {\n transform: translateY(12px);\n opacity: 0;\n }\n to {\n transform: translateY(0);\n opacity: 1;\n }\n }\n\n .sp-card {\n animation: sp-card-in 0.35s ${EASE_OUT_EXPO} both;\n animation-delay: calc(var(--sp-card-i, 0) * 40ms);\n }\n\n /* ---- Loading spinner ---- */\n\n @keyframes sp-spin {\n to { transform: rotate(360deg); }\n }\n\n .sp-spinner {\n width: 20px;\n height: 20px;\n border: 2px solid var(--sp-border);\n border-top-color: var(--sp-accent);\n border-radius: 50%;\n animation: sp-spin 0.6s linear infinite;\n }\n\n /* ---- Badge bounce ---- */\n\n @keyframes sp-badge-in {\n 0% { transform: scale(0); }\n 60% { transform: scale(1.3); }\n 100% { transform: scale(1); }\n }\n\n .sp-fab-badge {\n animation: sp-badge-in 0.4s ${SPRING_OVERSHOOT} both;\n }\n\n /* ---- Reduced motion ---- */\n\n @media (prefers-reduced-motion: reduce) {\n *, *::before, *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n\n`;\n","import { Z_INDEX_MAX } from \"../constants.js\";\nimport { EXPORT_CSS } from \"../export-utils.js\";\nimport { BULK_CSS } from \"../panel-bulk.js\";\nimport { DETAIL_CSS } from \"../panel-detail.js\";\nimport { SORT_CSS } from \"../panel-sort.js\";\nimport { STATS_CSS } from \"../panel-stats.js\";\nimport { SHORTCUTS_CSS } from \"../shortcuts.js\";\nimport { ANIMATION_CSS } from \"./animations.js\";\nimport { cssVariables, type ThemeColors } from \"./theme.js\";\n\n/**\n * Build the complete CSS stylesheet for the Shadow DOM.\n *\n * Design: Glassmorphism — frosted glass surfaces, soft depth,\n * accent gradients, premium micro-interactions.\n *\n * Principles:\n * - :host uses `all: initial` to block inherited styles\n * - All classes prefixed with sp- (defense in depth)\n * - CSS custom properties for theming\n * - No external fonts — system-ui stack (Inter if available)\n * - :focus-visible on all interactive elements\n * - prefers-reduced-motion support\n */\nexport function buildStyles(colors: ThemeColors): string {\n return `\n :host {\n all: initial;\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n font-family: var(--sp-font);\n font-size: 14px;\n line-height: 1.5;\n color: var(--sp-text);\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n ${cssVariables(colors)}\n\n /* Identity modal — theme-aware backdrop + panel */\n --sp-identity-bg: ${colors.glassBgHeavy};\n --sp-identity-overlay: ${colors.bg === \"#ffffff\" ? \"rgba(15, 23, 42, 0.2)\" : \"rgba(0, 0, 0, 0.4)\"};\n }\n\n *, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n /* ============================\n Focus visible (accessibility)\n ============================ */\n\n :focus-visible {\n outline: 2px solid var(--sp-accent);\n outline-offset: 2px;\n }\n\n /* ============================\n FAB (Floating Action Button)\n ============================ */\n\n .sp-fab {\n position: fixed;\n width: 52px;\n height: 52px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-accent-gradient);\n color: #fff;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow:\n 0 4px 20px var(--sp-accent-glow),\n 0 2px 8px rgba(0, 0, 0, 0.08);\n transition:\n transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),\n box-shadow 0.3s ease;\n outline: none;\n }\n\n .sp-fab:focus-visible {\n outline: 2px solid #fff;\n outline-offset: 3px;\n }\n\n .sp-fab:hover {\n transform: translateY(-2px) scale(1.05);\n box-shadow:\n 0 8px 28px var(--sp-accent-glow),\n 0 4px 12px rgba(0, 0, 0, 0.1);\n }\n\n .sp-fab:active {\n transform: translateY(0) scale(0.95);\n transition-duration: 0.1s;\n }\n\n .sp-fab--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-fab--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-fab svg {\n width: 22px;\n height: 22px;\n fill: currentColor;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n /* ---- FAB Badge ---- */\n\n .sp-fab-badge {\n position: absolute;\n top: -4px;\n right: -4px;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: var(--sp-radius-full);\n background: #ef4444;\n color: #fff;\n font-size: 11px;\n font-weight: 700;\n display: flex;\n align-items: center;\n justify-content: center;\n border: 2px solid #fff;\n pointer-events: none;\n font-family: var(--sp-font);\n line-height: 1;\n }\n\n /* ============================\n Radial Menu\n ============================ */\n\n .sp-radial {\n position: fixed;\n pointer-events: none;\n width: 52px;\n height: 52px;\n }\n\n .sp-radial--bottom-right {\n bottom: 24px;\n right: 24px;\n }\n\n .sp-radial--bottom-left {\n bottom: 24px;\n left: 24px;\n }\n\n .sp-radial-item {\n position: absolute;\n left: 4px;\n bottom: 4px;\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius-full);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n color: var(--sp-text);\n border: 1px solid var(--sp-glass-border);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: var(--sp-shadow-md);\n font-size: 12px;\n font-weight: 600;\n }\n\n .sp-radial-item:hover,\n .sp-radial-item:focus-visible {\n background: rgba(255, 255, 255, 0.95);\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n box-shadow:\n var(--sp-shadow-md),\n 0 0 0 3px var(--sp-accent-light);\n outline: none;\n }\n\n .sp-radial-item svg {\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n stroke: currentColor;\n fill: none;\n }\n\n .sp-radial-label {\n white-space: nowrap;\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-text);\n pointer-events: none;\n opacity: 0;\n padding: 4px 12px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-sm);\n transform: translateX(4px);\n transition: opacity 0.2s ease, transform 0.2s ease;\n }\n\n .sp-radial-item:hover .sp-radial-label,\n .sp-radial-item:focus-visible .sp-radial-label {\n opacity: 1;\n transform: translateX(0);\n }\n\n /* ============================\n Panel (Side drawer)\n ============================ */\n\n .sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n width: 400px;\n max-width: 100vw;\n height: 100vh;\n height: 100dvh;\n background: var(--sp-glass-bg);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border-left: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n @media (max-width: 480px) {\n .sp-panel {\n width: 100vw;\n border-left: none;\n }\n }\n\n .sp-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 20px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: relative;\n z-index: 2;\n }\n\n .sp-panel-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-panel-close {\n width: 44px;\n height: 44px;\n border-radius: var(--sp-radius);\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--sp-text-tertiary);\n transition: all 0.2s ease;\n }\n\n .sp-panel-close:hover {\n background: var(--sp-bg-hover);\n color: var(--sp-text);\n }\n\n .sp-panel-close svg {\n width: 16px;\n height: 16px;\n }\n\n /* ============================\n Filters & Search\n ============================ */\n\n .sp-filters {\n padding: 16px 24px;\n border-bottom: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .sp-search-wrap {\n position: relative;\n margin-bottom: 12px;\n }\n\n .sp-search {\n width: 100%;\n height: 40px;\n padding: 0 12px 0 38px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 13px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-search::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-search:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: #fff;\n }\n\n .sp-search-icon {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--sp-text-tertiary);\n width: 16px;\n height: 16px;\n transition: color 0.2s ease;\n }\n\n .sp-search:focus ~ .sp-search-icon,\n .sp-search-wrap:focus-within .sp-search-icon {\n color: var(--sp-accent);\n }\n\n /* ============================\n Filter bar (type dropdown + status segmented)\n ============================ */\n\n .sp-filter-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n flex-wrap: wrap;\n }\n\n /* ============================\n Type filter dropdown\n ============================ */\n\n .sp-filter-dropdown {\n position: relative;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .sp-filter-dropdown-btn {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: var(--sp-glass-bg-heavy);\n\n display: inline-flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px 0 10px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-filter-dropdown-btn:hover {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--sp-chip-color) 14%, transparent);\n }\n\n .sp-filter-dropdown-btn--filtered {\n border-color: var(--sp-chip-color);\n background: var(--sp-chip-bg);\n }\n\n .sp-filter-dropdown-btn__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-btn__icon svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-filter-dropdown-btn__label {\n display: inline-flex;\n align-items: baseline;\n gap: 6px;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n }\n\n .sp-filter-dropdown-btn__prefix {\n color: var(--sp-text-tertiary);\n font-weight: 500;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .sp-filter-dropdown-btn__value {\n color: var(--sp-chip-color);\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sp-filter-dropdown-btn__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-text-tertiary);\n transition: transform 0.18s ease, color 0.18s ease;\n }\n\n .sp-filter-dropdown-btn__chevron svg {\n width: 12px;\n height: 12px;\n }\n\n .sp-filter-dropdown-btn[aria-expanded=\"true\"] .sp-filter-dropdown-btn__chevron {\n transform: rotate(180deg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-menu {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n right: 0;\n min-width: 180px;\n padding: 4px;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-md);\n z-index: 10;\n animation: sp-filter-menu-in 0.15s ease-out both;\n }\n\n @keyframes sp-filter-menu-in {\n from { opacity: 0; transform: translateY(-4px) scale(0.98); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n\n .sp-filter-dropdown-option {\n --sp-chip-color: var(--sp-text-secondary);\n --sp-chip-bg: transparent;\n\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n padding: 8px 10px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n text-align: left;\n transition: background 0.12s ease, color 0.12s ease;\n }\n\n .sp-filter-dropdown-option__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n flex-shrink: 0;\n border-radius: 6px;\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option__label {\n flex: 1;\n min-width: 0;\n }\n\n .sp-filter-dropdown-option__check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n }\n\n .sp-filter-dropdown-option__check svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-filter-dropdown-option:hover {\n background: var(--sp-bg-hover);\n }\n\n .sp-filter-dropdown-option--active {\n color: var(--sp-chip-color);\n font-weight: 600;\n }\n\n .sp-filter-dropdown-option--active:hover {\n background: var(--sp-chip-bg);\n }\n\n /* ============================\n Status segmented control\n ============================ */\n\n .sp-segmented {\n display: inline-flex;\n align-items: stretch;\n padding: 2px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n flex-shrink: 0;\n }\n\n .sp-segmented__btn {\n --sp-chip-color: var(--sp-text-tertiary);\n --sp-chip-bg: transparent;\n\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 26px;\n padding: 0 10px;\n border: none;\n border-radius: var(--sp-radius-full);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n white-space: nowrap;\n transition: background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease;\n }\n\n .sp-segmented__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 13px;\n height: 13px;\n flex-shrink: 0;\n color: var(--sp-chip-color);\n transition: color 0.18s ease, transform 0.18s ease;\n }\n\n .sp-segmented__icon svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-segmented__btn:hover {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn:hover .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--active {\n background: var(--sp-chip-bg);\n color: var(--sp-chip-color);\n font-weight: 600;\n box-shadow:\n inset 0 0 0 1px color-mix(in srgb, var(--sp-chip-color) 35%, transparent),\n 0 1px 2px rgba(0, 0, 0, 0.04);\n }\n\n .sp-segmented__btn--active .sp-segmented__icon {\n color: var(--sp-chip-color);\n }\n\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: sp-segmented-pulse 2.4s ease-in-out infinite;\n }\n\n @keyframes sp-segmented-pulse {\n 0%, 100% { transform: scale(1); }\n 50% { transform: scale(0.85); }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .sp-filter-dropdown-btn,\n .sp-filter-dropdown-btn__chevron,\n .sp-filter-dropdown-option,\n .sp-segmented__btn,\n .sp-segmented__icon {\n transition: none;\n }\n .sp-filter-dropdown-menu {\n animation: none;\n }\n .sp-segmented__btn--open.sp-segmented__btn--active .sp-segmented__icon {\n animation: none;\n }\n }\n\n /* ============================\n Feedback Cards\n ============================ */\n\n .sp-list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n }\n\n .sp-list::-webkit-scrollbar {\n width: 6px;\n }\n\n .sp-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .sp-list::-webkit-scrollbar-thumb {\n background: var(--sp-border);\n border-radius: var(--sp-radius-full);\n }\n\n .sp-list::-webkit-scrollbar-thumb:hover {\n background: var(--sp-text-tertiary);\n }\n\n .sp-card {\n display: flex;\n padding: 14px 16px;\n margin-bottom: 6px;\n cursor: pointer;\n border-radius: var(--sp-radius);\n background: var(--sp-glass-bg-heavy);\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xs);\n transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n }\n\n .sp-card:hover {\n background: #fff;\n border-color: var(--sp-border);\n box-shadow: var(--sp-shadow-md);\n transform: translateY(-2px);\n }\n\n .sp-card:active {\n transform: translateY(0) scale(0.99);\n transition-duration: 0.1s;\n }\n\n .sp-card-bar {\n width: 3px;\n border-radius: var(--sp-radius-full);\n margin-right: 14px;\n flex-shrink: 0;\n }\n\n .sp-card-body {\n flex: 1;\n min-width: 0;\n }\n\n .sp-card-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 6px;\n }\n\n .sp-card-number {\n font-size: 12px;\n font-weight: 700;\n color: var(--sp-text-tertiary);\n font-variant-numeric: tabular-nums;\n }\n\n .sp-badge {\n padding: 2px 10px;\n border-radius: var(--sp-radius-full);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n }\n\n .sp-card-date {\n font-size: 11px;\n color: var(--sp-text-tertiary);\n margin-left: auto;\n }\n\n .sp-card-message {\n font-size: 13px;\n line-height: 1.5;\n color: var(--sp-text);\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .sp-card-message--expanded {\n -webkit-line-clamp: unset;\n }\n\n .sp-card-expand {\n font-size: 12px;\n font-weight: 500;\n color: var(--sp-accent);\n cursor: pointer;\n background: none;\n border: none;\n padding: 4px 0;\n font-family: var(--sp-font);\n transition: opacity 0.15s ease;\n }\n\n .sp-card-expand:hover {\n opacity: 0.8;\n }\n\n .sp-card-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 10px;\n }\n\n .sp-btn-resolve,\n .sp-btn-delete {\n padding: 8px 14px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-resolve svg,\n .sp-btn-delete svg {\n width: 14px;\n height: 14px;\n }\n\n .sp-btn-resolve:hover {\n border-color: #22c55e;\n color: #22c55e;\n background: rgba(34, 197, 94, 0.06);\n }\n\n .sp-btn-delete:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-resolve:disabled,\n .sp-btn-delete:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .sp-spinner--sm {\n width: 14px;\n height: 14px;\n }\n\n /* ---- Delete All (header) ---- */\n\n .sp-panel-header-right {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .sp-btn-delete-all {\n padding: 5px 12px;\n border-radius: var(--sp-radius-full);\n border: 1px solid var(--sp-border);\n background: transparent;\n color: var(--sp-text-tertiary);\n font-family: var(--sp-font);\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n }\n\n .sp-btn-delete-all svg {\n width: 13px;\n height: 13px;\n }\n\n .sp-btn-delete-all:hover {\n border-color: #ef4444;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.06);\n }\n\n .sp-btn-delete-all:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ---- Confirm Dialog ---- */\n\n .sp-confirm-backdrop {\n position: fixed;\n inset: 0;\n background: var(--sp-backdrop, rgba(15, 23, 42, 0.2));\n backdrop-filter: blur(var(--sp-blur));\n -webkit-backdrop-filter: blur(var(--sp-blur));\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: ${Z_INDEX_MAX};\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n .sp-confirm-dialog {\n width: 340px;\n padding: 28px;\n border-radius: 20px;\n background: var(--sp-glass-bg-heavy);\n backdrop-filter: blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter: blur(var(--sp-blur-heavy));\n border: 1px solid var(--sp-glass-border);\n box-shadow: var(--sp-shadow-xl);\n font-family: var(--sp-font);\n transform: translateY(8px) scale(0.97);\n transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .sp-confirm-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n margin-bottom: 8px;\n }\n\n .sp-confirm-message {\n font-size: 14px;\n color: var(--sp-text-secondary);\n line-height: 1.5;\n margin-bottom: 20px;\n }\n\n .sp-confirm-actions {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n }\n\n .sp-btn-danger {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: #ef4444;\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.25);\n }\n\n .sp-btn-danger:hover {\n background: #dc2626;\n box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);\n transform: translateY(-1px);\n }\n\n .sp-btn-danger:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-card--resolved {\n opacity: 0.5;\n }\n\n .sp-card--resolved .sp-card-message {\n text-decoration: line-through;\n text-decoration-color: var(--sp-text-tertiary);\n }\n\n /* ============================\n Loading State\n ============================ */\n\n .sp-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n }\n\n /* ============================\n Identity Form\n ============================ */\n\n .sp-identity-title {\n font-size: 17px;\n font-weight: 700;\n color: var(--sp-text);\n letter-spacing: -0.02em;\n }\n\n .sp-input {\n width: 100%;\n height: 42px;\n padding: 0 14px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text);\n font-family: var(--sp-font);\n font-size: 14px;\n outline: none;\n transition: all 0.2s ease;\n }\n\n .sp-input::placeholder {\n color: var(--sp-text-tertiary);\n }\n\n .sp-input:focus {\n border-color: var(--sp-accent);\n box-shadow: 0 0 0 3px var(--sp-accent-light);\n background: #fff;\n }\n\n .sp-input-label {\n font-size: 13px;\n font-weight: 500;\n color: var(--sp-text-secondary);\n margin-bottom: 6px;\n display: block;\n }\n\n /* ============================\n Buttons\n ============================ */\n\n .sp-btn-primary {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: none;\n background: var(--sp-accent-gradient);\n color: #fff;\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 2px 8px var(--sp-accent-glow);\n }\n\n .sp-btn-primary:hover {\n box-shadow: 0 4px 16px var(--sp-accent-glow);\n transform: translateY(-1px);\n }\n\n .sp-btn-primary:active {\n transform: translateY(0) scale(0.98);\n transition-duration: 0.1s;\n }\n\n .sp-btn-primary:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n transform: none;\n box-shadow: none;\n }\n\n .sp-btn-ghost {\n height: 40px;\n padding: 0 22px;\n border-radius: var(--sp-radius);\n border: 1px solid var(--sp-border);\n background: var(--sp-glass-bg-heavy);\n color: var(--sp-text-secondary);\n font-family: var(--sp-font);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n }\n\n .sp-btn-ghost:hover {\n border-color: var(--sp-accent);\n color: var(--sp-accent);\n background: var(--sp-accent-light);\n }\n\n /* ============================\n Empty State\n ============================ */\n\n .sp-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 56px 24px;\n color: var(--sp-text-tertiary);\n text-align: center;\n gap: 8px;\n animation: sp-fade-in 0.3s ease-out both;\n }\n\n .sp-empty-text {\n font-size: 14px;\n font-weight: 500;\n }\n\n /* ============================\n Load More\n ============================ */\n\n .sp-load-more-wrap {\n display: flex;\n justify-content: center;\n padding: 12px 0 4px;\n }\n\n .sp-btn-load-more {\n width: 100%;\n }\n\n /* ============================\n Forced Colors / High Contrast\n ============================ */\n\n @media (forced-colors: active) {\n .sp-fab,\n .sp-radial-item,\n .sp-filter-dropdown-btn,\n .sp-segmented,\n .sp-segmented__btn,\n .sp-card,\n .sp-panel-close,\n .sp-search,\n .sp-btn-resolve,\n .sp-btn-delete,\n .sp-btn-delete-all,\n .sp-btn-primary,\n .sp-btn-ghost,\n .sp-btn-danger,\n .sp-card-expand,\n .sp-input,\n .sp-confirm-dialog {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-segmented__btn--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-filter-dropdown-menu {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n }\n\n .sp-filter-dropdown-option--active {\n background: Highlight !important;\n color: HighlightText !important;\n }\n\n .sp-fab:focus-visible,\n .sp-radial-item:focus-visible,\n .sp-filter-dropdown-btn:focus-visible,\n .sp-segmented__btn:focus-visible,\n .sp-filter-dropdown-option:focus-visible,\n .sp-panel-close:focus-visible,\n .sp-btn-resolve:focus-visible,\n .sp-btn-delete:focus-visible,\n .sp-btn-delete-all:focus-visible,\n .sp-btn-primary:focus-visible,\n .sp-btn-ghost:focus-visible,\n .sp-btn-danger:focus-visible,\n .sp-card-expand:focus-visible,\n .sp-input:focus-visible,\n .sp-search:focus-visible {\n outline: 3px solid Highlight !important;\n }\n\n .sp-panel {\n border: 2px solid ButtonText !important;\n }\n\n .sp-fab-badge {\n border: 2px solid ButtonText !important;\n background: Canvas !important;\n color: ButtonText !important;\n }\n\n .sp-card-bar {\n background: ButtonText !important;\n }\n }\n\n ${ANIMATION_CSS}\n ${STATS_CSS}\n ${SORT_CSS}\n ${BULK_CSS}\n ${EXPORT_CSS}\n ${SHORTCUTS_CSS}\n ${DETAIL_CSS}\n `;\n}\n","import type { FeedbackResponse } from \"@siteping/core\";\nimport { Z_INDEX_MAX } from \"./constants.js\";\nimport { el, formatRelativeDate, setText } from \"./dom-utils.js\";\nimport { createT, getTypeLabel } from \"./i18n/index.js\";\nimport { getTypeBgColor, getTypeColor, type ThemeColors } from \"./styles/theme.js\";\n\nconst SHOW_DELAY = 120;\nconst HIDE_DELAY = 80;\n\n/**\n * Tooltip shown on annotation marker hover.\n *\n * Glassmorphism design: frosted glass with pastel badge,\n * smooth entrance animation, directional arrow.\n * Lives outside Shadow DOM.\n */\nexport class Tooltip {\n private root: HTMLElement;\n private arrow: HTMLElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n private currentFeedbackId: string | null = null;\n\n readonly tooltipId = \"sp-tooltip\";\n\n constructor(\n private readonly colors: ThemeColors,\n private readonly locale: string = \"en\",\n ) {\n this.root = el(\"div\", {\n style: `\n position: fixed;\n z-index: ${Z_INDEX_MAX};\n max-width: 280px;\n padding: 12px 14px;\n border-radius: 14px;\n background: ${this.colors.glassBgHeavy};\n backdrop-filter: blur(24px);\n -webkit-backdrop-filter: blur(24px);\n border: 1px solid ${this.colors.glassBorder};\n box-shadow: 0 8px 32px ${this.colors.shadow}, 0 2px 8px ${this.colors.shadow};\n font-family: \"Inter\", system-ui, -apple-system, sans-serif;\n pointer-events: auto;\n opacity: 0;\n transform: translateY(6px) scale(0.97);\n transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);\n visibility: hidden;\n -webkit-font-smoothing: antialiased;\n `,\n });\n\n this.root.setAttribute(\"role\", \"tooltip\");\n this.root.id = this.tooltipId;\n\n // Arrow element\n this.arrow = el(\"div\", {\n style: `\n position: absolute;\n width: 12px;\n height: 12px;\n background: ${this.colors.glassBgHeavy};\n border: 1px solid ${this.colors.glassBorder};\n transform: rotate(45deg);\n pointer-events: none;\n `,\n });\n this.root.appendChild(this.arrow);\n\n this.root.addEventListener(\"mouseenter\", () => this.cancelHide());\n this.root.addEventListener(\"mouseleave\", () => this.scheduleHide());\n document.body.appendChild(this.root);\n }\n\n show(feedback: FeedbackResponse, anchorRect: DOMRect): void {\n if (this.currentFeedbackId === feedback.id) return;\n this.cancelHide();\n this.cancelShow();\n\n this.showTimer = setTimeout(() => {\n this.currentFeedbackId = feedback.id;\n this.render(feedback);\n this.position(anchorRect);\n\n // Check prefers-reduced-motion live (not cached at construction time)\n const reduceMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n this.root.style.transition = reduceMotion ? \"none\" : \"\";\n\n this.root.style.visibility = \"visible\";\n this.root.style.opacity = \"1\";\n this.root.style.transform = \"translateY(0) scale(1)\";\n }, SHOW_DELAY);\n }\n\n scheduleHide(): void {\n this.cancelHide();\n this.hideTimer = setTimeout(() => this.hide(), HIDE_DELAY);\n }\n\n hide(): void {\n this.cancelShow();\n this.currentFeedbackId = null;\n this.root.style.opacity = \"0\";\n this.root.style.transform = \"translateY(6px) scale(0.97)\";\n setTimeout(() => {\n if (!this.currentFeedbackId) {\n this.root.style.visibility = \"hidden\";\n }\n }, 200);\n }\n\n private cancelShow(): void {\n if (this.showTimer) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n\n private cancelHide(): void {\n if (this.hideTimer) {\n clearTimeout(this.hideTimer);\n this.hideTimer = null;\n }\n }\n\n private render(feedback: FeedbackResponse): void {\n // Clear previous content safely (except arrow)\n const children = Array.from(this.root.children);\n for (const child of children) {\n if (child !== this.arrow) child.remove();\n }\n\n const typeColor = getTypeColor(feedback.type, this.colors);\n const typeBg = getTypeBgColor(feedback.type, this.colors);\n const t = createT(this.locale);\n const typeLabel = getTypeLabel(feedback.type, t);\n\n // Header row: badge + date\n const header = el(\"div\", { style: \"display:flex;align-items:center;gap:8px;margin-bottom:8px;\" });\n\n const badge = el(\"span\", {\n style: `\n padding:3px 10px;border-radius:9999px;\n font-size:11px;font-weight:600;\n color:${typeColor};background:${typeBg};\n letter-spacing:0.02em;\n `,\n });\n setText(badge, typeLabel);\n\n const date = el(\"span\", { style: `font-size:11px;color:${this.colors.textSecondary};margin-left:auto;` });\n setText(date, formatRelativeDate(feedback.createdAt, this.locale));\n\n header.appendChild(badge);\n header.appendChild(date);\n\n // Message body (safe — textContent only)\n const body = el(\"div\", {\n style: `font-size:13px;line-height:1.55;color:${this.colors.text};display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;`,\n });\n setText(body, feedback.message);\n\n // Insert content before arrow\n this.root.insertBefore(header, this.arrow);\n this.root.insertBefore(body, this.arrow);\n }\n\n private position(anchorRect: DOMRect): void {\n const tooltipRect = this.root.getBoundingClientRect();\n const gap = 10;\n\n let top = anchorRect.top - tooltipRect.height - gap;\n let left = anchorRect.left + anchorRect.width / 2 - tooltipRect.width / 2;\n let isAbove = true;\n\n // Flip below if not enough space above\n if (top < 8) {\n top = anchorRect.bottom + gap;\n isAbove = false;\n }\n\n left = Math.max(8, Math.min(left, window.innerWidth - tooltipRect.width - 8));\n\n this.root.style.top = `${top}px`;\n this.root.style.left = `${left}px`;\n\n // Position arrow\n const arrowLeft = Math.max(16, Math.min(anchorRect.left + anchorRect.width / 2 - left - 6, tooltipRect.width - 22));\n\n if (isAbove) {\n // Arrow at bottom, pointing down\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-right:1px solid ${this.colors.glassBorder};\n border-bottom:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n bottom:-6px;\n left:${arrowLeft}px;\n `;\n } else {\n // Arrow at top, pointing up\n this.arrow.style.cssText = `\n position:absolute;\n width:12px;height:12px;\n background:${this.colors.glassBgHeavy};\n border-left:1px solid ${this.colors.glassBorder};\n border-top:1px solid ${this.colors.glassBorder};\n transform:rotate(45deg);\n pointer-events:none;\n top:-6px;\n left:${arrowLeft}px;\n `;\n }\n }\n\n /** Check if a DOM node belongs to this tooltip (for MutationObserver filtering). */\n contains(node: Node): boolean {\n return this.root.contains(node);\n }\n\n destroy(): void {\n this.cancelShow();\n this.cancelHide();\n this.root.remove();\n }\n}\n","import type {\n FeedbackPayload,\n FeedbackResponse,\n PageScope,\n SitepingConfig,\n SitepingInstance,\n SitepingPublicEvents,\n} from \"@siteping/core\";\nimport { Annotator } from \"./annotator.js\";\nimport { ApiClient, flushRetryQueue, type WidgetClient } from \"./api-client.js\";\nimport { MOBILE_BREAKPOINT, PAGE_SIZE, Z_INDEX_MAX } from \"./constants.js\";\nimport { EventBus, type PublicWidgetEvents, type WidgetEvents } from \"./events.js\";\nimport { Fab } from \"./fab.js\";\nimport { createT, type TFunction } from \"./i18n/index.js\";\nimport { getIdentity, type Identity, saveIdentity } from \"./identity.js\";\nimport { MarkerManager } from \"./markers.js\";\nimport { Panel } from \"./panel.js\";\nimport { StoreClient } from \"./store-client.js\";\nimport { buildStyles } from \"./styles/base.js\";\nimport { buildThemeColors } from \"./styles/theme.js\";\nimport { Tooltip } from \"./tooltip.js\";\n\n/** Singleton guard — prevents duplicate widgets from overlapping */\nlet instance: SitepingInstance | null = null;\n\n/** Build a no-op SitepingInstance for when the widget is skipped */\nfunction skippedInstance(): SitepingInstance {\n const noop = () => {};\n return {\n destroy: noop,\n open: noop,\n close: noop,\n refresh: noop,\n on: () => noop,\n off: noop,\n };\n}\n\n/**\n * Main widget launcher — orchestrates all UI components.\n *\n * Architecture:\n * - Creates a <siteping-widget> custom element in the document\n * - Attaches a closed Shadow DOM for CSS isolation\n * - FAB + Panel live inside the Shadow DOM\n * - Overlay, markers, tooltips live outside (appended to document.body)\n */\nexport function launch(config: SitepingConfig): SitepingInstance {\n // Debug helper — only logs when config.debug is true\n const log: (...args: unknown[]) => void = config.debug\n ? (...args: unknown[]) => console.debug(\"[siteping]\", ...args)\n : () => {};\n\n // Guard: prevent duplicate initSiteping() calls\n if (instance) {\n log(\"initSiteping() called more than once — returning existing instance\");\n return instance;\n }\n\n // Guard: only show in development (forceShow bypasses)\n if (!config.forceShow) {\n try {\n // Check for Node/bundler production environment — avoid import.meta\n // which causes \"Critical dependency\" warnings in Next.js webpack builds\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") {\n const reason = \"production\";\n console.info(\"[siteping] Widget not loaded: production mode detected. Use forceShow: true to override.\");\n config.onSkip?.(reason);\n return skippedInstance();\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n }\n\n // Guard: desktop only (< MOBILE_BREAKPOINT = hidden)\n if (window.innerWidth < MOBILE_BREAKPOINT) {\n const reason = \"mobile\";\n console.info(`[siteping] Widget not loaded: viewport width < ${MOBILE_BREAKPOINT}px (mobile not supported).`);\n config.onSkip?.(reason);\n return skippedInstance();\n }\n\n // Guard: validate required config fields\n if (!config.store && (!config.endpoint || typeof config.endpoint !== \"string\")) {\n console.error(\n \"[siteping] Missing 'endpoint' or 'store' in config. Provide an endpoint like '/api/siteping' or a SitepingStore instance.\",\n );\n return skippedInstance();\n }\n if (!config.projectName || typeof config.projectName !== \"string\") {\n console.error(\"[siteping] Missing or invalid 'projectName' in config. Expected a non-empty string.\");\n return skippedInstance();\n }\n\n const locale = config.locale ?? \"en\";\n const t = createT(locale);\n\n // Page scope — concrete URL + optional template, used to keep annotations\n // and panel results scoped to the current page. The widget calls this on\n // every initial markers load and on `instance.refresh()`, so SPA hosts can\n // re-fetch when the route changes.\n const scopeAnnotationsByUrl = config.scopeAnnotationsByUrl ?? true;\n const getScope = (): PageScope => {\n try {\n const result = config.getPageScope?.();\n if (result) return result;\n } catch (e) {\n log(\"getPageScope() threw, falling back to pathname:\", e);\n }\n return { url: window.location.pathname, urlPattern: null };\n };\n\n log(\"Initializing widget\", {\n projectName: config.projectName,\n theme: config.theme ?? \"light\",\n locale,\n scopeAnnotationsByUrl,\n });\n\n const colors = buildThemeColors(config.accentColor, config.theme);\n const bus = new EventBus<WidgetEvents>();\n const publicBus = new EventBus<PublicWidgetEvents>();\n\n // Client-side mode (store) vs HTTP mode (endpoint)\n const client: WidgetClient = config.store\n ? new StoreClient(config.store, config.projectName)\n : new ApiClient(config.endpoint as string, config.projectName);\n\n // Wire config callbacks to event bus\n if (config.onOpen) bus.on(\"open\", config.onOpen);\n if (config.onClose) bus.on(\"close\", config.onClose);\n if (config.onFeedbackSent) bus.on(\"feedback:sent\", config.onFeedbackSent);\n if (config.onError) bus.on(\"feedback:error\", config.onError);\n if (config.onAnnotationStart) bus.on(\"annotation:start\", config.onAnnotationStart);\n if (config.onAnnotationEnd) bus.on(\"annotation:end\", config.onAnnotationEnd);\n\n // Bridge internal events to public bus\n bus.on(\"feedback:sent\", (fb) => publicBus.emit(\"feedback:sent\", fb));\n bus.on(\"feedback:deleted\", (id) => publicBus.emit(\"feedback:deleted\", id));\n bus.on(\"open\", () => publicBus.emit(\"panel:open\"));\n bus.on(\"close\", () => publicBus.emit(\"panel:close\"));\n\n // Debug logging for key lifecycle events\n bus.on(\"open\", () => log(\"Panel opened\"));\n bus.on(\"close\", () => log(\"Panel closed\"));\n bus.on(\"feedback:sent\", (fb) => log(\"Feedback sent\", fb.id));\n bus.on(\"feedback:error\", (err) => log(\"Feedback failed\", err.message));\n bus.on(\"annotation:start\", () => log(\"Annotation started\"));\n bus.on(\"annotation:end\", () => log(\"Annotation ended\"));\n\n // Create host element + Shadow DOM\n const host = document.createElement(\"siteping-widget\");\n host.style.cssText = `position:fixed;z-index:${Z_INDEX_MAX};`;\n // Use open mode only for testing — closed in production for CSS isolation.\n // Shadow DOM mode is determined by environment, never by public config.\n let isTestEnv = false;\n try {\n // Dynamic key prevents bundlers (tsup/esbuild) from statically replacing\n // process.env.NODE_ENV at build time — the widget needs runtime detection\n // so E2E tests can set globalThis.process = { env: { NODE_ENV: 'test' } }\n const envKey = \"NODE_\" + \"ENV\";\n if (typeof process !== \"undefined\" && process.env?.[envKey] === \"test\") {\n isTestEnv = true;\n }\n } catch {\n // Silently ignore — browser or restricted environment\n }\n const shadowMode = isTestEnv ? (\"open\" as const) : (\"closed\" as const);\n const shadow = host.attachShadow({ mode: shadowMode });\n\n // Inject styles into Shadow DOM — adoptedStyleSheets with fallback for Safari < 16.4\n const supportsAdoptedStyleSheets = \"adoptedStyleSheets\" in ShadowRoot.prototype;\n if (supportsAdoptedStyleSheets) {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(buildStyles(colors));\n shadow.adoptedStyleSheets = [sheet];\n } else {\n const style = document.createElement(\"style\");\n style.textContent = buildStyles(colors);\n (shadow as unknown as DocumentFragment).appendChild(style);\n }\n\n document.body.appendChild(host);\n\n // Screen reader live region for feedback submission announcements\n const liveRegion = document.createElement(\"div\");\n liveRegion.setAttribute(\"role\", \"status\");\n liveRegion.setAttribute(\"aria-live\", \"polite\");\n liveRegion.setAttribute(\"aria-atomic\", \"true\");\n liveRegion.style.cssText =\n \"position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;\";\n document.body.appendChild(liveRegion);\n\n // Components outside Shadow DOM\n const tooltip = new Tooltip(colors, locale);\n const markers = new MarkerManager(colors, tooltip, bus, t);\n\n // Components inside Shadow DOM\n const fab = new Fab(shadow, config, bus, t);\n const panel = new Panel(shadow, colors, bus, client, config.projectName, markers, t, locale, {\n getScope,\n scopeAnnotationsByUrl,\n });\n const annotator = new Annotator(colors, bus, t, config.enableScreenshot ?? false);\n\n // Handle annotation completion via event bus (not DOM events)\n // Concurrency guard: prevent duplicate submissions if user draws two annotations quickly\n let submitting = false;\n const unsubAnnotation = bus.on(\"annotation:complete\", async (data) => {\n if (submitting) return;\n submitting = true;\n try {\n const { annotation, type, message, screenshotDataUrl } = data;\n\n // Ensure identity\n let identity = getIdentity();\n if (!identity) {\n identity = await promptIdentity(shadow, t);\n if (!identity) return; // User cancelled\n saveIdentity(identity);\n }\n\n // crypto.randomUUID() throws in non-secure contexts (plain HTTP)\n const clientId = (() => {\n try {\n return crypto.randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n })();\n\n // Use scope.url as the single source of truth — same identifier the\n // panel filter and marker filter use. If we stored full URLs here while\n // filtering by pathname, freshly-created feedbacks would never match\n // their own scope filter and would vanish from the UI immediately.\n // Default scope.url is `window.location.pathname` (no query string,\n // so token/key/secret query params can't leak by construction). Hosts\n // that need origin or query in the identifier override `getPageScope`.\n const scope = getScope();\n const payload: FeedbackPayload = {\n projectName: config.projectName,\n type,\n message,\n url: scope.url,\n urlPattern: scope.urlPattern,\n viewport: `${window.innerWidth}x${window.innerHeight}`,\n userAgent: navigator.userAgent,\n authorName: identity.name,\n authorEmail: identity.email,\n annotations: [annotation],\n clientId,\n screenshotDataUrl: screenshotDataUrl ?? null,\n };\n\n try {\n const response = await client.sendFeedback(payload);\n bus.emit(\"feedback:sent\", response);\n // Compare against the scope captured before submit (route may have\n // changed during the network round-trip — re-reading scope here\n // would race with SPA navigation).\n if (!scopeAnnotationsByUrl || response.url === scope.url) {\n markers.addFeedback(response, markers.count + 1);\n }\n liveRegion.textContent = t(\"feedback.sent.confirmation\");\n await panel.refresh();\n } catch (error) {\n bus.emit(\"feedback:error\", error instanceof Error ? error : new Error(String(error)));\n liveRegion.textContent = t(\"feedback.error.message\");\n }\n } finally {\n submitting = false;\n }\n });\n\n // Load markers immediately on page load. We always pass the current page URL\n // when scopeAnnotationsByUrl is enabled so the server narrows results to the\n // current page — preventing annotations from one page accidentally rendering\n // on another (when CSS selectors happen to match unrelated elements).\n const initialScope = getScope();\n const initialOptions = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: initialScope.url } : { limit: PAGE_SIZE };\n client\n .getFeedbacks(config.projectName, initialOptions)\n .then(({ feedbacks }: { feedbacks: FeedbackResponse[] }) => {\n // Defensive client-side filter — backend may not yet support the `url` query.\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === initialScope.url) : feedbacks;\n markers.render(visible);\n })\n .catch((err) => {\n log(\"Failed to load initial markers:\", err);\n });\n\n // Flush retry queue on load (HTTP mode only — store mode has no retry queue)\n if (config.endpoint) {\n flushRetryQueue(config.endpoint)\n .then(() => log(\"Retry queue flushed\"))\n .catch(() => {});\n }\n\n instance = {\n destroy: () => {\n log(\"Destroying widget\");\n unsubAnnotation();\n fab.destroy();\n panel.destroy();\n annotator.destroy();\n markers.destroy();\n tooltip.destroy();\n bus.removeAll();\n publicBus.removeAll();\n liveRegion.remove();\n host.remove();\n instance = null;\n },\n open: () => {\n panel.open();\n },\n close: () => {\n panel.close();\n },\n refresh: () => {\n // When the panel is open, its `refresh()` already runs `loadFeedbacks()`\n // which renders markers. Doing a second fetch here would race with that\n // one — the loser overwrites the winner's markers, off by a generation.\n // So: when the panel is open, delegate. When it's closed, fetch markers\n // ourselves (the panel won't, but SPA hosts still need the new page's\n // markers after a route change).\n if (panel.isCurrentlyOpen) {\n panel.refresh();\n return;\n }\n\n const scope = getScope();\n const opts = scopeAnnotationsByUrl ? { limit: PAGE_SIZE, url: scope.url } : { limit: PAGE_SIZE };\n client\n .getFeedbacks(config.projectName, opts)\n .then(({ feedbacks }: { feedbacks: FeedbackResponse[] }) => {\n const visible = scopeAnnotationsByUrl ? feedbacks.filter((f) => f.url === scope.url) : feedbacks;\n markers.render(visible);\n })\n .catch(() => {});\n },\n on: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => {\n // Safe cast: SitepingPublicEvents and PublicWidgetEvents have identical keys and value types\n type TargetKey = K & keyof PublicWidgetEvents;\n return publicBus.on(event as TargetKey, listener as unknown as (...args: PublicWidgetEvents[TargetKey]) => void);\n },\n off: <K extends keyof SitepingPublicEvents>(event: K, listener: (...args: SitepingPublicEvents[K]) => void) => {\n // Safe cast: SitepingPublicEvents and PublicWidgetEvents have identical keys and value types\n type TargetKey = K & keyof PublicWidgetEvents;\n publicBus.off(event as TargetKey, listener as unknown as (...args: PublicWidgetEvents[TargetKey]) => void);\n },\n };\n\n return instance;\n}\n\n/**\n * Show a modal identity form inside the Shadow DOM.\n * Glassmorphism: frosted backdrop, glass modal, gradient CTA.\n * Returns null if the user cancels.\n */\nfunction promptIdentity(shadowRoot: ShadowRoot, t: TFunction): Promise<Identity | null> {\n return new Promise((resolve) => {\n // Save the currently focused element to restore on close\n const previouslyFocused = (shadowRoot.activeElement ?? document.activeElement) as HTMLElement | null;\n\n const backdrop = document.createElement(\"div\");\n backdrop.style.cssText = `\n position:fixed;inset:0;\n background:var(--sp-identity-overlay);\n backdrop-filter:blur(8px);\n -webkit-backdrop-filter:blur(8px);\n display:flex;align-items:center;justify-content:center;\n z-index:${Z_INDEX_MAX};\n opacity:0;transition:opacity 0.25s ease;\n `;\n\n const modal = document.createElement(\"div\");\n modal.style.cssText = `\n width:340px;padding:28px;border-radius:var(--sp-radius-xl);\n background:var(--sp-identity-bg);\n backdrop-filter:blur(var(--sp-blur-heavy));\n -webkit-backdrop-filter:blur(var(--sp-blur-heavy));\n border:1px solid var(--sp-glass-border);\n box-shadow:0 16px 48px var(--sp-shadow), 0 8px 16px var(--sp-shadow);\n font-family:var(--sp-font, \"Inter\",system-ui,-apple-system,sans-serif);\n color:var(--sp-text);\n transform:translateY(12px) scale(0.97);\n transition:transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n -webkit-font-smoothing:antialiased;\n `;\n\n const titleId = `sp-identity-title-${Date.now()}`;\n modal.setAttribute(\"role\", \"dialog\");\n modal.setAttribute(\"aria-modal\", \"true\");\n modal.setAttribute(\"aria-labelledby\", titleId);\n\n const title = document.createElement(\"div\");\n title.className = \"sp-identity-title\";\n title.id = titleId;\n title.textContent = t(\"identity.title\");\n title.style.marginBottom = \"20px\";\n\n const nameInputId = `sp-identity-name-${Date.now()}`;\n const emailInputId = `sp-identity-email-${Date.now()}`;\n\n const nameLabel = document.createElement(\"label\");\n nameLabel.className = \"sp-input-label\";\n nameLabel.textContent = t(\"identity.nameLabel\");\n nameLabel.setAttribute(\"for\", nameInputId);\n const nameInput = document.createElement(\"input\");\n nameInput.className = \"sp-input\";\n nameInput.id = nameInputId;\n nameInput.type = \"text\";\n nameInput.placeholder = t(\"identity.namePlaceholder\");\n nameInput.style.marginBottom = \"14px\";\n\n const emailLabel = document.createElement(\"label\");\n emailLabel.className = \"sp-input-label\";\n emailLabel.textContent = t(\"identity.emailLabel\");\n emailLabel.setAttribute(\"for\", emailInputId);\n const emailInput = document.createElement(\"input\");\n emailInput.className = \"sp-input\";\n emailInput.id = emailInputId;\n emailInput.type = \"email\";\n emailInput.placeholder = t(\"identity.emailPlaceholder\");\n\n const btnRow = document.createElement(\"div\");\n btnRow.style.cssText = \"display:flex;gap:8px;justify-content:flex-end;margin-top:20px;\";\n\n const closeModal = (result: Identity | null) => {\n backdrop.removeEventListener(\"keydown\", onKeydown);\n backdrop.style.opacity = \"0\";\n modal.style.transform = \"translateY(12px) scale(0.97)\";\n setTimeout(() => {\n backdrop.remove();\n previouslyFocused?.focus();\n resolve(result);\n }, 250);\n };\n\n const cancelBtn = document.createElement(\"button\");\n cancelBtn.className = \"sp-btn-ghost\";\n cancelBtn.textContent = t(\"identity.cancel\");\n cancelBtn.addEventListener(\"click\", () => closeModal(null));\n\n const submitBtn = document.createElement(\"button\");\n submitBtn.className = \"sp-btn-primary\";\n submitBtn.textContent = t(\"identity.submit\");\n submitBtn.addEventListener(\"click\", () => {\n const name = nameInput.value.trim();\n const email = emailInput.value.trim();\n if (!name || !email) return;\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n emailInput.style.borderColor = \"var(--sp-type-bug, #ef4444)\";\n return;\n }\n closeModal({ name, email });\n });\n\n // Focus trap: cycle Tab/Shift+Tab within the modal\n const focusableSelectors = 'input, button, [tabindex]:not([tabindex=\"-1\"])';\n const onKeydown = (e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === \"Escape\") {\n closeModal(null);\n return;\n }\n if (ke.key === \"Tab\") {\n const focusableEls = Array.from(modal.querySelectorAll<HTMLElement>(focusableSelectors));\n if (focusableEls.length === 0) return;\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n if (!first || !last) return;\n const active = shadowRoot.activeElement as HTMLElement | null;\n if (ke.shiftKey) {\n if (active === first || !modal.contains(active)) {\n ke.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !modal.contains(active)) {\n ke.preventDefault();\n first.focus();\n }\n }\n }\n };\n backdrop.addEventListener(\"keydown\", onKeydown);\n\n // Close on backdrop click\n backdrop.addEventListener(\"click\", (e) => {\n if (e.target === backdrop) closeModal(null);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(submitBtn);\n\n modal.appendChild(title);\n modal.appendChild(nameLabel);\n modal.appendChild(nameInput);\n modal.appendChild(emailLabel);\n modal.appendChild(emailInput);\n modal.appendChild(btnRow);\n backdrop.appendChild(modal);\n\n shadowRoot.appendChild(backdrop);\n\n // Animate in\n requestAnimationFrame(() => {\n backdrop.style.opacity = \"1\";\n modal.style.transform = \"translateY(0) scale(1)\";\n nameInput.focus();\n });\n });\n}\n"],"mappings":"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SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,WAIFC,GAAyB,CAC3B,SAAU,CACN,IAAO,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAC7G,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAEpD,OAAQ,CACJ,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,eACA,eACA,eACA,eACA,eACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,WAIFC,GAA2B,CAC7B,SAAU,CACN,IAAO,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAC1G,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAE5D,OAAQ,CACJ,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,SACA,WAIFC,GAAwB,SAC1B9sB,EACA+sB,EACAhW,EACAiW,EACAC,EACAC,EAAc,CAEd,OAAIltB,EAAQ+sB,GAAO/sB,EAAQ+W,EAChBoW,GAAkBntB,EAAOitB,EAAUC,EAAO,OAAS,CAAC,EAI3DF,EAAQ,SAAS,OAAO,SAACI,EAAQC,EAASnqB,EAAK,CAC3C,KAAOlD,GAASqtB,GACZrtB,GAASqtB,EACTD,GAAUJ,EA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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAggBpC,SAASC,GAAaC,EAAoB,CAExC,GAAI,SAAS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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAw1BtF,UAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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":["extendStatics","d","b","p","__extends","__","__assign","t","s","i","__awaiter","thisArg","_arguments","P","generator","adopt","value","resolve","reject","fulfilled","step","e","rejected","result","__generator","body","_","f","y","g","verb","n","v","op","__spreadArray","to","from","pack","l","ar","Bounds","left","top","width","height","x","w","h","context","clientRect","domRectList","domRect","rect","parseBounds","node","parseDocumentSize","document","documentElement","toCodePoints","str","codePoints","length","extra","fromCodePoint","_i","codeUnits","index","codePoint","chars","lookup","decode","base64","bufferLength","len","encoded1","encoded2","encoded3","encoded4","buffer","bytes","polyUint16Array","polyUint32Array","UTRIE2_SHIFT_2","UTRIE2_SHIFT_1","UTRIE2_INDEX_SHIFT","UTRIE2_SHIFT_1_2","UTRIE2_LSCP_INDEX_2_OFFSET","UTRIE2_DATA_BLOCK_LENGTH","UTRIE2_DATA_MASK","UTRIE2_LSCP_INDEX_2_LENGTH","UTRIE2_INDEX_2_BMP_LENGTH","UTRIE2_UTF8_2B_INDEX_2_OFFSET","UTRIE2_UTF8_2B_INDEX_2_LENGTH","UTRIE2_INDEX_1_OFFSET","UTRIE2_OMITTED_BMP_INDEX_1_LENGTH","UTRIE2_INDEX_2_BLOCK_LENGTH","UTRIE2_INDEX_2_MASK","slice16","view","start","end","slice32","createTrieFromBase64","_byteLength","view32","view16","headerLength","data","Trie","initialValue","errorValue","highStart","highValueIndex","ix","LETTER_NUMBER_MODIFIER","BK","CR","LF","CM","NL","WJ","ZW","GL","SP","ZWJ","B2","BA","BB","HY","CB","CL","CP","EX","IN","NS","OP","QU","IS","NU","PO","PR","SY","AI","AL","CJ","EB","EM","H2","H3","HL","ID","JL","JV","JT","RI","SA","XX","ea_OP","BREAK_MANDATORY","BREAK_NOT_ALLOWED","BREAK_ALLOWED","UnicodeTrie","ALPHABETICS","HARD_LINE_BREAKS","SPACE","PREFIX_POSTFIX","LINE_BREAKS","KOREAN_SYLLABLE_BLOCK","HYPHEN","codePointsToCharacterClasses","lineBreak","types","indices","categories","classType","prev","isAdjacentWithSpaceIgnored","a","currentIndex","classTypes","current","next","previousNonSpaceClassType","type","_lineBreakAtIndex","indicies","forbiddenBreaks","beforeIndex","afterIndex","before","prevIndex","count","cssFormattedClasses","options","_a","isLetterNumber","forbiddenBreakpoints","letterNumber","Break","LineBreaker","lastEnd","nextIndex","FLAG_UNRESTRICTED","FLAG_ID","FLAG_INTEGER","FLAG_NUMBER","LINE_FEED","SOLIDUS","REVERSE_SOLIDUS","CHARACTER_TABULATION","QUOTATION_MARK","EQUALS_SIGN","NUMBER_SIGN","DOLLAR_SIGN","PERCENTAGE_SIGN","APOSTROPHE","LEFT_PARENTHESIS","RIGHT_PARENTHESIS","LOW_LINE","HYPHEN_MINUS","EXCLAMATION_MARK","LESS_THAN_SIGN","GREATER_THAN_SIGN","COMMERCIAL_AT","LEFT_SQUARE_BRACKET","RIGHT_SQUARE_BRACKET","CIRCUMFLEX_ACCENT","LEFT_CURLY_BRACKET","QUESTION_MARK","RIGHT_CURLY_BRACKET","VERTICAL_LINE","TILDE","CONTROL","REPLACEMENT_CHARACTER","ASTERISK","PLUS_SIGN","COMMA","COLON","SEMICOLON","FULL_STOP","NULL","BACKSPACE","LINE_TABULATION","SHIFT_OUT","INFORMATION_SEPARATOR_ONE","DELETE","EOF","ZERO","u","z","A","E","F","U","Z","isDigit","isSurrogateCodePoint","isHex","isLowerCaseLetter","isUpperCaseLetter","isLetter","isNonASCIICodePoint","isWhiteSpace","isNameStartCodePoint","isNameCodePoint","isNonPrintableCodePoint","isValidEscape","c1","c2","isIdentifierStart","c3","isNumberStart","stringToNumber","c","sign","integers","int","fraction","fracd","frac","expsign","exponent","exp","LEFT_PARENTHESIS_TOKEN","RIGHT_PARENTHESIS_TOKEN","COMMA_TOKEN","SUFFIX_MATCH_TOKEN","PREFIX_MATCH_TOKEN","COLUMN_TOKEN","DASH_MATCH_TOKEN","INCLUDE_MATCH_TOKEN","LEFT_CURLY_BRACKET_TOKEN","RIGHT_CURLY_BRACKET_TOKEN","SUBSTRING_MATCH_TOKEN","BAD_URL_TOKEN","BAD_STRING_TOKEN","CDO_TOKEN","CDC_TOKEN","COLON_TOKEN","SEMICOLON_TOKEN","LEFT_SQUARE_BRACKET_TOKEN","RIGHT_SQUARE_BRACKET_TOKEN","WHITESPACE_TOKEN","EOF_TOKEN","Tokenizer","chunk","tokens","token","flags","e1","e2","e3","a1","a2","a3","u1","u2","delta","digits","questionMarks","start_1","digit","endDigits","stringToken","SLICE_STACK_SIZE","amount","endingCodePoint","repr","number","unit","hex","hexCodePoint","Parser","tokenizer","values","block","isEndingTokenFor","functionToken","cssFunction","isDimensionToken","isNumberToken","isIdentToken","isStringToken","isIdentWithValue","nonWhiteSpace","nonFunctionArgSeparator","parseFunctionArgs","args","arg","isLength","isLengthPercentage","parseLengthPercentageTuple","ZERO_LENGTH","FIFTY_PERCENT","HUNDRED_PERCENT","getAbsoluteValueForTuple","tuple","getAbsoluteValue","parent","DEG","GRAD","RAD","TURN","angle","_context","isAngle","parseNamedSide","sideOrCorner","ident","deg","color","colorFunction","SUPPORTED_COLOR_FUNCTIONS","r","namedColor","COLORS","isTransparent","asString","alpha","blue","green","red","getTokenColorValue","max","rgb","_b","hue2rgb","t1","t2","hue","hsl","saturation","lightness","parseColor","backgroundClip","backgroundColor","parseColorStop","colorType","stop","processColorStops","stops","lineLength","first","last","processStops","previous","stop_1","absoluteValue","gapBegin","stop_2","gapLength","beforeGap","gapValue","getAngleFromCorner","corner","centerX","centerY","calculateGradientDirection","radian","halfWidth","halfHeight","halfLineLength","yDiff","xDiff","distance","findCorner","closest","corners","stat","cx","cy","calculateRadius","gradient","rx","ry","linearGradient","firstToken","angleType","colorStop","angle$1","prefixLinearGradient","webkitGradient","shape","size","position","CLOSEST_SIDE","FARTHEST_SIDE","CLOSEST_CORNER","FARTHEST_CORNER","CIRCLE","ELLIPSE","COVER","CONTAIN","radialGradient","isColorStop","isAtPosition_1","acc","prefixRadialGradient","isLinearGradient","background","isRadialGradient","image","image_1","imageFunction","SUPPORTED_IMAGE_FUNCTIONS","isSupportedImage","backgroundImage","backgroundOrigin","backgroundPosition","backgroundRepeat","parseBackgroundRepeat","BACKGROUND_SIZE","backgroundSize","isBackgroundSizeInfoToken","borderColorForSide","side","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","borderRadiusForSide","borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius","borderStyleForSide","style","borderTopStyle","borderRightStyle","borderBottomStyle","borderLeftStyle","borderWidthForSide","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","direction","display","bit","parseDisplayValue","float","letterSpacing","LINE_BREAK","lineHeight","computeLineHeight","fontSize","listStyleImage","listStylePosition","listStyleType","marginForSide","marginTop","marginRight","marginBottom","marginLeft","overflow","overflowWrap","paddingForSide","paddingTop","paddingRight","paddingBottom","paddingLeft","textAlign","textShadow","shadow","textTransform","transform","transformFunction","SUPPORTED_TRANSFORM_FUNCTIONS","matrix","matrix3d","b1","b2","a4","b4","DEFAULT_VALUE","DEFAULT","transformOrigin","origins","visibility","WORD_BREAK","wordBreak","zIndex","time","opacity","textDecorationColor","textDecorationLine","line","fontFamily","accumulator","results","fontWeight","fontVariant","fontStyle","contains","content","counterIncrement","increments","filtered","counter","increment","counterReset","resets","reset","duration","quotes","open_1","close_1","getQuote","depth","open","quote","boxShadow","paintOrder","layers","webkitTextStrokeColor","webkitTextStrokeWidth","CSSParsedDeclaration","declaration","parse","overflowTuple","CSSParsedPseudoDeclaration","CSSParsedCounterDeclaration","descriptor","parser","length_1","value_1","elementDebuggerAttribute","getElementDebugType","element","attribute","isDebugging","elementType","ElementContainer","isHTMLElementNode","Prepend","Control","Extend","SpacingMark","L","V","T","LV","LVT","Extended_Pictographic","codePointToClass","_graphemeBreakAtIndex","_codePoints","countRI","GraphemeBreaker","graphemeBreak","splitGraphemes","breaker","graphemes","bk","testRangeBounds","TEST_HEIGHT","range","testElement","rangeBounds","rangeHeight","testIOSLineBreak","textList","offset","supports","text","boundAhead","testCORS","testResponseType","testSVG","img","canvas","ctx","isGreenPixel","testForeignObject","greenImageSrc","svg","createForeignObjectSVG","loadSerializedSVG","xmlns","foreignObject","FEATURES","TextBounds","bounds","parseTextBounds","styles","breakText","textBounds","clientRects","createRange","subSegments","segmentGraphemes","subOffset_1","subSegment","replacementNode","getWrapperBounds","ownerDocument","wrapper","parentNode","segmenter","segment","segmentWords","breakWords","wordSeparators","words","word_1","TextContainer","CAPITALIZE","capitalize","m","p1","p2","ImageElementContainer","_super","_this","CanvasElementContainer","SVGElementContainer","LIElementContainer","OLElementContainer","CHECKBOX_BORDER_RADIUS","RADIO_BORDER_RADIUS","reformatInputBounds","getInputValue","PASSWORD","CHECKBOX","RADIO","INPUT_COLOR","InputElementContainer","input","SelectElementContainer","option","TextareaElementContainer","IFrameElementContainer","iframe","parseTree","documentBackgroundColor","bodyBackgroundColor","LIST_OWNERS","parseNodeTree","root","childNode","nextNode","isTextNode","isElementNode","isSlotElement","container","createContainer","createsRealStackingContext","createsStackingContext","isTextareaElement","isSVGElement","isSelectElement","isImageElement","isCanvasElement","isLIElement","isOLElement","isInputElement","isIFrameElement","isBodyElement","isSVGElementNode","isHTMLElement","isVideoElement","isStyleElement","isScriptElement","isCustomElement","CounterState","name","counters","canReset","entry","counterNames","ROMAN_UPPER","ARMENIAN","HEBREW","GEORGIAN","createAdditiveCounter","min","symbols","fallback","suffix","createCounterText","string","integer","createCounterStyleWithSymbolResolver","codePointRangeLength","isNumeric","resolver","createCounterStyleFromRange","codePointRangeStart","codePointRangeEnd","createCounterStyleFromSymbols","CJK_ZEROS","CJK_TEN_COEFFICIENTS","CJK_TEN_HIGH_COEFFICIENTS","CJK_HUNDRED_COEFFICIENTS","createCJKCounter","numbers","multipliers","negativeSign","tmp","coefficient","CHINESE_INFORMAL_MULTIPLIERS","CHINESE_FORMAL_MULTIPLIERS","JAPANESE_NEGATIVE","KOREAN_NEGATIVE","appendSuffix","defaultSuffix","cjkSuffix","koreanSuffix","spaceSuffix","IGNORE_ATTRIBUTE","DocumentCloner","windowSize","createIFrameContainer","scrollX","scrollY","cloneWindow","documentClone","iframeLoad","iframeLoader","restoreNodeScroll","onclone","referenceElement","imagesReady","serializeDoctype","restoreOwnerScroll","clone","copyCSSStyles","sheet","css","rule","clonedCanvas","clonedCtx","gl","attribs","video","blankCanvas","child","copyStyles","assignedNodes","assignedNode","window","styleBefore","styleAfter","createPseudoHideStyles","PseudoElementType","after","pseudoElt","anonymousReplacedElement","attr","counterStyle","counterState","counterType","delim","counterStates","counterType_1","separator","PSEUDO_HIDE_ELEMENT_CLASS_BEFORE","PSEUDO_HIDE_ELEMENT_CLASS_AFTER","newClassName","cloneIframeContainer","imageReady","interval","ignoredStyleProperties","target","property","doctype","PSEUDO_BEFORE","PSEUDO_AFTER","PSEUDO_HIDE_ELEMENT_STYLE","createStyles","CacheStorage","url","link","src","Cache","_options","isBlobImage","isRenderable","key","isSameOrigin","useCORS","isInlineImage","useProxy","isInlineBase64Image","proxy","responseType","xhr","reader_1","queryString","timeout_1","INLINE_SVG","INLINE_BASE64","INLINE_IMG","isSVG","Vector","deltaX","deltaY","lerp","BezierCurve","startControl","endControl","firstHalf","ab","bc","cd","abbc","bccd","dest","isBezierCurve","path","BoundCurves","tlh","tlv","trh","trv","_c","brh","brv","_d","blh","blv","factors","maxFactor","topWidth","rightHeight","bottomWidth","leftHeight","getCurvePoints","CORNER","r1","r2","kappa","ox","oy","xm","ym","calculateBorderBoxPath","curves","calculateContentBoxPath","calculatePaddingBoxPath","TransformEffect","offsetX","offsetY","ClipEffect","OpacityEffect","isTransformEffect","effect","isClipEffect","isOpacityEffect","equalPath","transformPath","deltaW","deltaH","point","StackingContext","ElementPaint","borderBox","paddingBox","inFlow","effects","croplessEffects","parseStackTree","stackingContext","realStackingContext","listItems","treatAsRealStackingContext","paintContainer","listOwnerItems","parentStack","stack","order_1","index_1","index_2","processListItems","owner","elements","numbering","reversed","item","parseStackingContexts","parsePathForBorder","borderSide","createPathFromCurves","parsePathForBorderDoubleOuter","parsePathForBorderDoubleInner","parsePathForBorderStroke","createStrokePathFromCurves","outer1","outer2","inner1","inner2","contentBox","calculateBackgroundPositioningArea","calculateBackgroundPaintingArea","calculateBackgroundRendering","intrinsicSize","backgroundPositioningArea","getBackgroundValueForIndex","backgroundPaintingArea","backgroundImageSize","calculateBackgroundSize","sizeWidth","sizeHeight","calculateBackgroundRepeatPath","isAuto","hasIntrinsicValue","intrinsicWidth","intrinsicHeight","intrinsicProportion","second","hasIntrinsicProportion","targetRatio","hasIntrinsicWidth","hasIntrinsicHeight","hasIntrinsicDimensions","width_1","height_1","width_2","height_2","width_3","height_3","repeat","SMALL_IMAGE","SAMPLE_TEXT","FontMetrics","span","baseline","middle","Renderer","MASK_OFFSET","CanvasRenderer","paint","letters","letter","variant","fixIOSSystemFonts","font","paintOrderLayer","textShadows","box","iframeRenderer","isTextInputElement","canvasTextAlign","_p","_e","_g","_f","_j","_h","_l","_k","_o","_m","paths","pattern","this_1","x0","x1","y0","y1","gradient_1","top_1","radialGradient_1","midX","midY","invF","curvePoints","outerPaths","innerPaths","hasBackground","borders","calculateBackgroundCurvedPaintingArea","borderBoxArea","maskOffset","shadowPaintingArea","borders_1","border","strokePaths","boxPaths","startX","startY","endX","endY","dashLength","spaceLength","useLineDash","multiplier","numberOfDashes","minSpace","maxSpace","path1","path2","clip","iOSBrokenFonts","fontFamilies","ForeignObjectRenderer","Logger","id","enabled","Context","windowBounds","html2canvas","renderElement","opts","defaultView","resourceOptions","contextOptions","windowOptions","foreignObjectRendering","cloneOptions","documentCloner","clonedElement","_u","parseBackgroundColor","renderOptions","_q","_r","_s","renderer","_t","backgroundColorOverride","defaultBackgroundColor","index_exports","__export","initSiteping","config","rootDocument","start","finder","input","options","defaults","name","value","findRootDocument","path","bottomUpSearch","optimized","sort","optimize","selector","rootNode","limit","fallback","stack","current","i","elapsedTime","level","maybe","id","attr","classNames","tagName","any","nth","index","dispensableNth","node","nthChild","findUniquePath","paths","combinations","candidate","unique","query","penalty","acc","css","elementId","parent","child","list","notEmpty","a","b","scope","newPath","newPathKey","same","STABLE_ATTRS","djb2","str","hash","generateFingerprint","element","childCount","siblingIdx","parent","child","attrs","attr","val","attrHash","scoreFingerprint","candidate","storedFingerprint","parts","storedChildren","storedSibIdx","storedAttrHash","storedChildCount","storedSibIndex","candidateFp","candChildren","candSibIdx","candAttrHash","score","childDiff","sibDiff","adjacentText","element","direction","prop","sibling","attempts","text","neighborText","prev","next","generateXPath","element","safeId","segments","current","tag","parent","position","sibling","ANCHOR_KEY_ATTR","generateAnchor","element","cssSelector","finder","name","xpath","generateXPath","textSnippet","textPrefix","adjacentText","textSuffix","fingerprint","generateFingerprint","neighbor","neighborText","anchorKey","containsRect","el","rect","b","findAnchorElement","root","centerX","centerY","elementAtCenter","current","rectToPercentages","anchorBounds","parseSvg","svgString","svg","attr","el","tag","attrs","element","key","value","setText","text","formatRelativeDate","isoString","locale","diff","seconds","rtf","minutes","hours","days","ICON_SITEPING","ICON_CHAT","ICON_ANNOTATE","ICON_EYE","ICON_EYE_OFF","ICON_CLOSE","ICON_SEARCH","ICON_CHECK","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","ICON_LAYERS","ICON_DOT_OPEN","ICON_CHEVRON_DOWN","ICON_UNDO","ICON_TRASH","DEFAULT_ACCENT","HEX6_RE","HEX3_RE","HEX8_RE","normalizeHex","raw","short","darkenHex","hex","amount","r","g","b","prefersDark","resolveTheme","theme","buildThemeColors","accent","dark","getTypeColor","type","colors","getTypeBgColor","cssVariables","Popup","colors","t","el","typeOptions","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","typeRow","option","btn","icon","parseSvg","labelSpan","setText","bgColor","getTypeBgColor","getTypeColor","hint","uaData","isMac","e","btnRow","cancelBtn","rectBounds","resolve","popupH","popupW","top","left","aboveTop","focusableEls","first","last","reduceMotion","type","container","buttons","isActive","color","enabled","cachedHtml2Canvas","warnedAboutMissingDep","loadHtml2Canvas","mod","err","captureScreenshot","rect","options","html2canvas","quality","maxWidth","canvas","element","ratio","targetW","targetH","scaled","ctx","Annotator","colors","bus","t","enableScreenshot","Popup","rect","captureScreenshot","el","dot","style","instruction","setText","cancelBtn","e","target","bounds","rectBounds","result","annotation","generateAnchor","screenshotDataUrl","touch","clientX","clientY","source","evt","x","y","w","anchorElement","findAnchorElement","anchor","anchorBounds","rectToPercentages","RETRY_QUEUE_KEY","resilientFetch","url","init","retries","attempt","controller","timeout","response","error","baseDelay","jitter","r","LOCK_NAME","withRetryLock","callback","queueForRetry","endpoint","payload","raw","RETRY_QUEUE_KEY","parsed","queue","flushRetryQueue","toRetry","e","failed","entry","remaining","ApiClient","projectName","text","options","params","id","resolved","EventBus","event","listener","set","args","fn","err","ITEM_GAP","Fab","shadowRoot","config","bus","t","position","isRight","ICON_CHAT","ICON_ANNOTATE","ICON_EYE","ICON_EYE_OFF","parseSvg","ICON_SITEPING","i","item","btn","e","label","host","handleEscape","items","activeEl","currentIndex","nextIndex","count","displayText","setText","ICON_CLOSE","y","svgStr","badge","id","de","en","es","fr","it","pt","ru","LOCALES","de","en","es","fr","it","pt","ru","createT","locale","lang","LOCALES","dict","key","getTypeLabel","type","t","STORAGE_KEY","getIdentity","raw","parsed","identity","saveIdentity","editDistance","a","b","t","aLen","bLen","prev","k","curr","j","i","prevDiag","tmp","similarity","maxLen","fuzzyIncludes","haystack","needle","minScore","nLen","score","best","capped","limit","window","MAX_SCAN_CANDIDATES","TEXT_MATCH_THRESHOLD","textMatches","el","anchor","text","fuzzyIncludes","resolveAnchor","escaped","ANCHOR_KEY_ATTR","smartScan","tag","candidates","bestElement","bestScore","limit","i","score","scoreCandidate","candidate","totalWeight","candidateText","scoreFingerprint","contextScore","contextParts","prevText","adjacentText","similarity","nextText","candidateNeighbor","neighborText","resolveAnnotation","rect","resolution","bounds","absoluteRect","toAnchorData","a","toRectData","MARKER_OFFSET","markerPosition","rect","clusterMarker","cluster","i","entry","elIdx","HIGHLIGHT_FADE","REPOSITION_DEBOUNCE","LOW_CONFIDENCE_THRESHOLD","CLUSTER_DISTANCE","FAN_SPACING","MarkerManager","colors","tooltip","bus","t","el","visible","mutations","hasRelevantMutation","m","e","validKeys","markerEl","annotation","cacheKey","cachedEl","resolved","anchorRect","r","resolveAnnotation","pos","key","feedbacks","feedback","index","marker","badge","allItems","used","itemI","j","itemJ","b","first","baseTop","baseLeft","isSolo","count","totalWidth","startLeft","topMarker","setText","confidence","isResolved","number","typeColor","getTypeColor","truncatedMessage","ariaLabel","getTypeLabel","activateMarker","feedbackId","highlight","h","ICON_EXPORT","ICON_CSV","ICON_JSON","EXPORT_I18N_EN","EXPORT_I18N_FR","EXPORT_CSS","CSV_COLUMNS","escapeCsvField","value","feedbacksToCsv","feedbacks","header","rows","fb","col","raw","feedbacksToJson","downloadFile","content","filename","mimeType","blob","url","anchor","ExportButton","_colors","getFeedbacks","el","btn","parseSvg","label","setText","e","csvOption","jsonOption","labels","span","options","iconSvg","labelText","onClick","option","iconWrap","labelEl","format","projectName","date","safeName","ICON_CHECKBOX","ICON_CHECKBOX_CHECKED","BULK_I18N_EN","BULK_I18N_FR","BULK_CSS","BulkActions","_colors","callbacks","locale","el","setText","actions","deselectBtn","parseSvg","feedbackId","wrapper","e","feedbackIds","label","checkbox","labelEl","container","id","prevSelected","count","visible","resolveLabel","deleteLabel","isChecked","allSelected","escapedId","card","btn","snapshot","n","ids","restoreResolve","restoreDelete","ICON_ARROW_LEFT","ICON_MAP_PIN","ICON_LINK","ICON_USER","ICON_CALENDAR","ICON_MONITOR","ICON_CHECK","ICON_UNDO","ICON_TRASH","ICON_CODE","ICON_CROSSHAIR","DETAIL_I18N_EN","DETAIL_I18N_FR","DETAIL_CSS","parseBrowser","ua","m","formatFullDate","isoString","locale","extractPathname","url","isSafeImageUrl","truncate","str","max","DetailView","colors","callbacks","el","header","backBtn","parseSvg","feedback","number","title","setText","badge","getTypeBgColor","getTypeColor","sectionIndex","statusSection","messageSection","messageSectionTitle","messageBlock","screenshotSection","screenshotSectionTitle","img","metaSection","metaSectionTitle","annSection","annSectionTitle","annTitleText","index","section","container","isResolved","sectionTitle","statusRow","pill","dot","pillLabel","actions","span","deleteSpan","meta","value","pathname","name","email","resolvedDate","iconSvg","label","buildValue","row","content","labelEl","ann","wrapper","info","tagDisplay","gotoBtn","gotoLabel","btn","ICON_SORT","ICON_PAGE","ICON_CHEVRON","SORT_I18N_EN","SORT_I18N_FR","TYPE_ORDER","sortFeedbacks","feedbacks","mode","sorted","a","b","typeA","typeB","statusA","statusB","extractPathname","url","truncatePath","path","maxLength","ellipsis","keep","groupFeedbacksByPage","groups","fb","existing","createPageGroupHeader","pagePath","count","colors","header","el","chevronWrap","parseSvg","pageIcon","pathEl","displayPath","setText","countEl","toggle","isExpanded","content","e","PanelSortControls","onChange","locale","sortIcon","sortLabel","groupIcon","groupLabel","options","opt","item","labelMap","label","SORT_CSS","STATS_I18N_EN","STATS_I18N_FR","STATS_CSS","PanelStats","colors","locale","el","row","itemOpen","dotOpen","setText","labelOpen","itemResolved","dotResolved","labelResolved","itemBugs","dotBugs","labelBugs","progress","track","feedbacks","total","openCount","resolvedCount","bugCount","fb","visible","pct","progressText","ICON_KEYBOARD","SHORTCUTS_I18N_EN","SHORTCUTS_I18N_FR","getFocusedCardIndex","listContainer","cards","focusCardByIndex","index","card","clamped","target","SHORTCUT_DEFS","SHORTCUTS_CSS","ICON_CLOSE_SM","KeyboardShortcuts","_colors","callbacks","i18n","e","root","active","tag","handler","overlay","el","title","parseSvg","titleText","setText","closeBtn","grid","def","row","keysWrap","key","i","sep","kbd","desc","btn","Panel","shadowRoot","colors","bus","client","projectName","markers","t","locale","pageScopeOptions","BULK_I18N_FR","BULK_I18N_EN","el","header","title","setText","parseSvg","ICON_CLOSE","ICON_TRASH","deleteAllLabel","ExportButton","EXPORT_I18N_FR","headerRight","PanelStats","filters","searchWrap","searchIcon","ICON_SEARCH","filterBar","PanelSortControls","BulkActions","ids","DetailView","fb","newResolved","ann","shortcutsI18n","SHORTCUTS_I18N_FR","SHORTCUTS_I18N_EN","KeyboardShortcuts","dir","idx","getFocusedCardIndex","focusCardByIndex","btn","e","target","actionEl","card","feedbackId","feedback","f","action","message","isExpanded","number","ke","open","focusable","first","last","active","loading","spinner","empty","text","retryBtn","signal","search","typeFilter","statusFilter","scope","options","hasContent","feedbacks","total","markerFeedbacks","error","controller","nextPage","loadMoreBtn","restoreBtn","emptyText","sorted","sortFeedbacks","feedbackIds","selectAllBar","groups","groupFeedbacksByPage","globalIndex","pagePath","groupFeedbacks","groupHeader","createPageGroupHeader","groupContent","index","remaining","loadMoreWrap","isResolved","typeColor","getTypeColor","getTypeLabel","bar","body","checkbox","num","badge","typeBg","getTypeBgColor","date","formatRelativeDate","expandBtn","footer","resolveBtn","ICON_UNDO","span","ICON_CHECK","deleteBtn","deleteBtnLabel","id","resolve","backdrop","titleId","messageId","dialog","titleEl","messageEl","btnRow","cancelBtn","confirmBtn","closed","close","result","onKeydown","snapshot","n","restore","ICON_LAYERS","ICON_QUESTION","ICON_CHANGE","ICON_BUG","ICON_OTHER","o","iconWrap","labelWrap","prefix","value","chevron","ICON_CHEVRON_DOWN","option","item","isActive","labelEl","checkWrap","ICON_DOT_OPEN","current","values","nextIdx","next","buttons","visibleValues","v","templateBtn","showTemplate","escapedId","flattenAnnotation","ann","StoreClient","store","projectName","payload","record","flattenAnnotation","toResponse","options","feedbacks","total","id","resolved","toAnnotationResponse","ann","SPRING_LINEAR","EASE_OUT_EXPO","SPRING_OVERSHOOT","EASE_OUT_QUART","ANIMATION_CSS","buildStyles","colors","cssVariables","ANIMATION_CSS","STATS_CSS","SORT_CSS","BULK_CSS","EXPORT_CSS","SHORTCUTS_CSS","DETAIL_CSS","SHOW_DELAY","HIDE_DELAY","Tooltip","colors","locale","el","feedback","anchorRect","reduceMotion","children","child","typeColor","getTypeColor","typeBg","getTypeBgColor","t","createT","typeLabel","getTypeLabel","header","badge","setText","date","formatRelativeDate","body","tooltipRect","gap","top","left","isAbove","arrowLeft","node","instance","skippedInstance","noop","launch","config","log","args","reason","locale","t","createT","scopeAnnotationsByUrl","getScope","result","e","colors","buildThemeColors","bus","EventBus","publicBus","client","StoreClient","ApiClient","fb","id","err","host","isTestEnv","shadowMode","shadow","sheet","buildStyles","style","liveRegion","tooltip","Tooltip","markers","MarkerManager","fab","Fab","panel","Panel","annotator","Annotator","submitting","unsubAnnotation","data","annotation","type","message","screenshotDataUrl","identity","getIdentity","promptIdentity","saveIdentity","clientId","scope","payload","response","error","initialScope","initialOptions","feedbacks","visible","f","flushRetryQueue","opts","event","listener","shadowRoot","resolve","previouslyFocused","backdrop","modal","titleId","title","nameInputId","emailInputId","nameLabel","nameInput","emailLabel","emailInput","btnRow","closeModal","onKeydown","cancelBtn","submitBtn","name","email","focusableSelectors","ke","focusableEls","first","last","active","initSiteping","config","launch"]}