@pie-players/pie-assessment-toolkit 0.3.51 → 0.3.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightCoordinator.js","sourceRoot":"","sources":["../../src/services/HighlightCoordinator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HighlightCoordinator\n *\n * Manages separate highlight layers for TTS (temporary) and annotations (persistent).\n * Uses CSS Custom Highlight API - zero DOM mutation, preserves accessibility.\n *\n * Features:\n * - Separate layers prevent TTS clearing from removing student annotations\n * - CSS Custom Highlight API (no DOM mutation)\n * - Full accessibility support (screen readers see original text)\n * - Configurable colors and styles\n * - Annotation persistence via RangeSerializer\n *\n * Part of PIE Assessment Toolkit.\n *\n * Browser Support:\n * - Chrome/Edge 105+\n * - Safari 17.2+\n * - Firefox: Behind flag (not recommended for production)\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API\n */\n\nimport type { HighlightCoordinatorApi } from \"./interfaces.js\";\nimport { RangeSerializer, type SerializedRange } from \"./RangeSerializer.js\";\n\n/**\n * Highlight types\n */\nexport enum HighlightType {\n\tTTS_WORD = \"tts-word\",\n\tTTS_SENTENCE = \"tts-sentence\",\n\tANNOTATION = \"annotation\",\n}\n\n/**\n * Highlight colors for annotations\n */\nexport enum HighlightColor {\n\tYELLOW = \"yellow\",\n\tGREEN = \"green\",\n\tBLUE = \"blue\",\n\tPINK = \"pink\",\n\tORANGE = \"orange\",\n\tUNDERLINE = \"underline\",\n}\n\n/**\n * Annotation data\n */\nexport interface Annotation {\n\tid: string;\n\trange: Range;\n\ttype: HighlightType.ANNOTATION;\n\tcolor: HighlightColor;\n\ttimestamp: number;\n}\n\n/**\n * Configuration for HighlightCoordinator\n * Currently empty but allows future extension without breaking changes\n */\nexport type HighlightCoordinatorConfig = Record<string, never>;\n\nexport class HighlightCoordinator implements HighlightCoordinatorApi {\n\tprivate config: HighlightCoordinatorConfig;\n\tprivate ttsWordHighlight: Highlight | null = null;\n\tprivate ttsSentenceHighlight: Highlight | null = null;\n\tprivate ttsWordElementHighlights = new Set<Element>();\n\tprivate ttsSentenceElementHighlights = new Set<Element>();\n\tprivate annotations = new Map<string, Annotation>();\n\t// Shared highlights per color (one Highlight object per color, contains all ranges)\n\tprivate colorHighlights = new Map<HighlightColor, Highlight>();\n\tprivate nextAnnotationId = 1;\n\tprivate supported = false;\n\tprivate rangeSerializer: RangeSerializer;\n\tprivate themeObserver: MutationObserver | null = null;\n\tprivate explicitTTSColorOverride: { color: string; opacity: number } | null =\n\t\tnull;\n\n\tconstructor(config: HighlightCoordinatorConfig = {}) {\n\t\tthis.config = config;\n\t\tthis.rangeSerializer = new RangeSerializer();\n\n\t\t// SSR guard\n\t\tif (typeof CSS === \"undefined\" || !(\"highlights\" in CSS)) {\n\t\t\tconsole.warn(\n\t\t\t\t\"CSS Custom Highlight API not supported (SSR or unsupported browser)\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.supported = true;\n\t\tthis.initializeHighlights();\n\t\tthis.registerStyles();\n\t\tthis.applyAdaptiveTTSStyle();\n\t\tthis.setupThemeObservation();\n\t}\n\n\tprivate setupThemeObservation(): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tif (typeof MutationObserver === \"undefined\") return;\n\n\t\tconst refresh = () => this.applyAdaptiveTTSStyle();\n\t\tthis.themeObserver = new MutationObserver(refresh);\n\n\t\tthis.themeObserver.observe(document.documentElement, {\n\t\t\tattributes: true,\n\t\t\tattributeFilter: [\"style\", \"data-theme\", \"data-color-scheme\", \"class\"],\n\t\t});\n\n\t\tfor (const host of document.querySelectorAll(\"pie-theme\")) {\n\t\t\tthis.themeObserver.observe(host, {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: [\n\t\t\t\t\t\"theme\",\n\t\t\t\t\t\"scheme\",\n\t\t\t\t\t\"provider\",\n\t\t\t\t\t\"variables\",\n\t\t\t\t\t\"style\",\n\t\t\t\t\t\"data-theme\",\n\t\t\t\t\t\"data-color-scheme\",\n\t\t\t\t],\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseColor(\n\t\tinput: string | null | undefined,\n\t): [number, number, number] | null {\n\t\tif (!input) return null;\n\t\tconst value = input.trim();\n\t\tif (!value) return null;\n\n\t\tconst hexMatch = /^#([a-f\\d]{3}|[a-f\\d]{6})$/i.exec(value);\n\t\tif (hexMatch) {\n\t\t\tconst hex = hexMatch[1];\n\t\t\tif (hex.length === 3) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt(hex[0] + hex[0], 16),\n\t\t\t\t\tparseInt(hex[1] + hex[1], 16),\n\t\t\t\t\tparseInt(hex[2] + hex[2], 16),\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn [\n\t\t\t\tparseInt(hex.slice(0, 2), 16),\n\t\t\t\tparseInt(hex.slice(2, 4), 16),\n\t\t\t\tparseInt(hex.slice(4, 6), 16),\n\t\t\t];\n\t\t}\n\n\t\tconst rgbMatch = /^rgba?\\((.+)\\)$/i.exec(value);\n\t\tif (rgbMatch) {\n\t\t\tconst normalized = rgbMatch[1].replace(/\\//g, \",\");\n\t\t\tconst parts = normalized\n\t\t\t\t.split(/[,\\s]+/)\n\t\t\t\t.map((part) => part.trim())\n\t\t\t\t.filter(Boolean);\n\t\t\tconst r = Number(parts[0]);\n\t\t\tconst g = Number(parts[1]);\n\t\t\tconst b = Number(parts[2]);\n\t\t\tif (Number.isFinite(r) && Number.isFinite(g) && Number.isFinite(b)) {\n\t\t\t\treturn [r, g, b];\n\t\t\t}\n\t\t}\n\n\t\t// Browser parser fallback (covers formats like oklch()).\n\t\tif (typeof document !== \"undefined\") {\n\t\t\tconst parserEl = document.createElement(\"span\");\n\t\t\tparserEl.style.color = value;\n\t\t\tif (typeof parserEl.style.color === \"string\" && parserEl.style.color) {\n\t\t\t\tdocument.body?.appendChild(parserEl);\n\t\t\t\tconst resolved =\n\t\t\t\t\ttypeof getComputedStyle === \"function\"\n\t\t\t\t\t\t? getComputedStyle(parserEl).color\n\t\t\t\t\t\t: \"\";\n\t\t\t\tparserEl.remove();\n\t\t\t\tconst normalizedResolved = resolved.trim();\n\t\t\t\t// Guard against recursive loops when computed style returns the same\n\t\t\t\t// unresolved function syntax (observed with certain color formats).\n\t\t\t\tif (normalizedResolved && normalizedResolved !== value) {\n\t\t\t\t\treturn this.parseColor(resolved);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate relativeLuminance([r, g, b]: [number, number, number]): number {\n\t\tconst toLinear = (channel: number) => {\n\t\t\tconst n = channel / 255;\n\t\t\treturn n <= 0.03928 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;\n\t\t};\n\t\tconst lr = toLinear(r);\n\t\tconst lg = toLinear(g);\n\t\tconst lb = toLinear(b);\n\t\treturn 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;\n\t}\n\n\tprivate contrastRatio(\n\t\ta: [number, number, number],\n\t\tb: [number, number, number],\n\t): number {\n\t\tconst la = this.relativeLuminance(a);\n\t\tconst lb = this.relativeLuminance(b);\n\t\tconst lighter = Math.max(la, lb);\n\t\tconst darker = Math.min(la, lb);\n\t\treturn (lighter + 0.05) / (darker + 0.05);\n\t}\n\n\tprivate blend(\n\t\tfg: [number, number, number],\n\t\tbg: [number, number, number],\n\t\talpha: number,\n\t): [number, number, number] {\n\t\treturn [\n\t\t\tMath.round(fg[0] * alpha + bg[0] * (1 - alpha)),\n\t\t\tMath.round(fg[1] * alpha + bg[1] * (1 - alpha)),\n\t\t\tMath.round(fg[2] * alpha + bg[2] * (1 - alpha)),\n\t\t];\n\t}\n\n\tprivate resolveAdaptiveTTSStyle(sourceEl?: Element | null): {\n\t\twordHighlight: string;\n\t\tsentenceHighlight: string;\n\t\twordUnderline: string;\n\t\twordShadow: string;\n\t} {\n\t\tconst fallbackMissing: [number, number, number] = [255, 235, 59];\n\t\tconst fallbackText: [number, number, number] = [17, 24, 39];\n\t\tconst fallbackBackground: [number, number, number] = [255, 255, 255];\n\n\t\tconst target =\n\t\t\tsourceEl ||\n\t\t\t(typeof document !== \"undefined\" ? document.documentElement : null);\n\t\tconst computed =\n\t\t\ttarget && typeof getComputedStyle === \"function\"\n\t\t\t\t? getComputedStyle(target)\n\t\t\t\t: null;\n\n\t\tconst background =\n\t\t\tthis.parseColor(\n\t\t\t\tcomputed?.getPropertyValue(\"--pie-background\") ||\n\t\t\t\t\tcomputed?.backgroundColor,\n\t\t\t) || fallbackBackground;\n\t\tconst text =\n\t\t\tthis.parseColor(computed?.getPropertyValue(\"--pie-text\")) || fallbackText;\n\t\tconst accent = this.explicitTTSColorOverride\n\t\t\t? this.parseColor(this.explicitTTSColorOverride.color) || fallbackMissing\n\t\t\t: this.parseColor(computed?.getPropertyValue(\"--pie-missing\")) ||\n\t\t\t\tfallbackMissing;\n\n\t\tconst opacityCandidates = this.explicitTTSColorOverride\n\t\t\t? [Math.max(0.3, Math.min(0.95, this.explicitTTSColorOverride.opacity))]\n\t\t\t: [0.8, 0.72, 0.68, 0.62, 0.56, 0.5];\n\n\t\tlet selectedOpacity = opacityCandidates[opacityCandidates.length - 1];\n\t\tlet bestScore = -Infinity;\n\n\t\tfor (const opacity of opacityCandidates) {\n\t\t\tconst blended = this.blend(accent, background, opacity);\n\t\t\tconst backgroundDelta = this.contrastRatio(blended, background);\n\t\t\tconst textContrast = this.contrastRatio(blended, text);\n\t\t\tconst score = backgroundDelta * 1.2 + textContrast * 0.8;\n\t\t\tif (backgroundDelta >= 1.25 && textContrast >= 2.4) {\n\t\t\t\tselectedOpacity = opacity;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (score > bestScore) {\n\t\t\t\tbestScore = score;\n\t\t\t\tselectedOpacity = opacity;\n\t\t\t}\n\t\t}\n\n\t\tconst sentenceOpacity = Math.max(\n\t\t\t0.24,\n\t\t\tMath.min(0.85, selectedOpacity * 0.55),\n\t\t);\n\t\tconst underlineOpacity = Math.max(\n\t\t\t0.55,\n\t\t\tMath.min(0.95, selectedOpacity + 0.2),\n\t\t);\n\t\tconst shadowOpacity = Math.max(0.22, Math.min(0.6, selectedOpacity * 0.45));\n\n\t\tconst underlineColor = text;\n\t\tconst underlineBlend = this.blend(\n\t\t\tunderlineColor,\n\t\t\tbackground,\n\t\t\tunderlineOpacity,\n\t\t);\n\t\tconst underlineDelta = this.contrastRatio(underlineBlend, background);\n\t\tconst fallbackUnderline: [number, number, number] =\n\t\t\tthis.relativeLuminance(background) > 0.45 ? [0, 0, 0] : [255, 255, 255];\n\t\tconst finalUnderline =\n\t\t\tunderlineDelta >= 1.35 ? underlineColor : fallbackUnderline;\n\n\t\tconst wordHighlight = `rgba(${accent[0]}, ${accent[1]}, ${accent[2]}, ${selectedOpacity})`;\n\t\tconst sentenceHighlight = `rgba(${accent[0]}, ${accent[1]}, ${accent[2]}, ${sentenceOpacity})`;\n\t\tconst wordUnderline = `rgba(${finalUnderline[0]}, ${finalUnderline[1]}, ${finalUnderline[2]}, ${underlineOpacity})`;\n\t\tconst wordShadow = `rgba(${finalUnderline[0]}, ${finalUnderline[1]}, ${finalUnderline[2]}, ${shadowOpacity})`;\n\n\t\treturn {\n\t\t\twordHighlight,\n\t\t\tsentenceHighlight,\n\t\t\twordUnderline,\n\t\t\twordShadow,\n\t\t};\n\t}\n\n\tprivate applyAdaptiveTTSStyle(sourceEl?: Element | null): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tconst vars = this.resolveAdaptiveTTSStyle(sourceEl);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-highlight\",\n\t\t\tvars.wordHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-sentence-highlight\",\n\t\t\tvars.sentenceHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-line-highlight\",\n\t\t\tvars.sentenceHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-underline\",\n\t\t\tvars.wordUnderline,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-shadow\",\n\t\t\tvars.wordShadow,\n\t\t);\n\t}\n\n\t/**\n\t * Initialize CSS Custom Highlights\n\t */\n\tprivate initializeHighlights(): void {\n\t\tif (!this.supported) return;\n\n\t\t// Create highlight registries for TTS\n\t\tthis.ttsWordHighlight = new Highlight();\n\t\tthis.ttsSentenceHighlight = new Highlight();\n\n\t\t// Register TTS highlights with CSS\n\t\tCSS.highlights.set(\"tts-word\", this.ttsWordHighlight);\n\t\tCSS.highlights.set(\"tts-sentence\", this.ttsSentenceHighlight);\n\n\t\t// Create shared highlights for each annotation color\n\t\tfor (const color of Object.values(HighlightColor)) {\n\t\t\tconst highlight = new Highlight();\n\t\t\tthis.colorHighlights.set(color, highlight);\n\t\t\tCSS.highlights.set(`annotation-${color}`, highlight);\n\t\t}\n\t}\n\n\t/**\n\t * Register CSS styles for highlights\n\t */\n\tprivate registerStyles(): void {\n\t\tif (!this.supported) return;\n\t\tif (typeof document === \"undefined\") return; // SSR guard\n\n\t\t// Check if styles already exist\n\t\tif (document.getElementById(\"pie-highlight-styles\")) return;\n\n\t\tconst style = document.createElement(\"style\");\n\t\tstyle.id = \"pie-highlight-styles\";\n\t\tstyle.textContent = `\n /* TTS highlights - temporary */\n ::highlight(tts-word) {\n background-color: var(--pie-tts-word-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 68%, transparent));\n text-decoration: underline 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n text-underline-offset: 2px;\n text-shadow: 0 0 1px var(--pie-tts-word-shadow, color-mix(in srgb, var(--pie-text, #111827) 35%, transparent));\n color: inherit;\n }\n\n /* tts-sentence registry id: coarse read-along band (visual line boxes in layout) */\n ::highlight(tts-sentence) {\n background-color: var(--pie-tts-line-highlight, var(--pie-tts-sentence-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 38%, transparent)));\n color: inherit;\n }\n\n [data-pie-tts-sentence-element=\"true\"] {\n background-color: var(--pie-tts-line-highlight, var(--pie-tts-sentence-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 38%, transparent)));\n border-radius: 0.12em;\n box-decoration-break: clone;\n -webkit-box-decoration-break: clone;\n }\n\n [data-pie-tts-word-element=\"true\"] {\n background-color: var(--pie-tts-word-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 68%, transparent));\n text-decoration: underline 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n text-underline-offset: 2px;\n text-shadow: 0 0 1px var(--pie-tts-word-shadow, color-mix(in srgb, var(--pie-text, #111827) 35%, transparent));\n border-bottom: 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n padding-bottom: 1px;\n border-radius: 0.12em;\n box-decoration-break: clone;\n -webkit-box-decoration-break: clone;\n }\n\n /* Annotation highlights - persistent */\n ::highlight(annotation-yellow) {\n background-color: color-mix(in srgb, var(--pie-missing, #ffff00) 35%, transparent);\n color: inherit;\n }\n\n ::highlight(annotation-green) {\n background-color: color-mix(in srgb, var(--pie-correct, #90ee90) 35%, transparent);\n color: inherit;\n }\n\n ::highlight(annotation-blue) {\n background-color: color-mix(in srgb, var(--pie-tertiary, #add8e6) 35%, transparent);\n color: inherit;\n }\n\n ::highlight(annotation-pink) {\n background-color: color-mix(in srgb, var(--pie-secondary-light, #ffb6c1) 35%, transparent);\n color: inherit;\n }\n\n ::highlight(annotation-orange) {\n background-color: color-mix(in srgb, var(--pie-incorrect, #ffa500) 35%, transparent);\n color: inherit;\n }\n\n ::highlight(annotation-underline) {\n background-color: transparent;\n text-decoration: underline 2px solid var(--pie-primary, #0066cc);\n text-underline-offset: 2px;\n color: inherit;\n }\n `;\n\t\tdocument.head.appendChild(style);\n\t}\n\n\t/**\n\t * Highlight a word for TTS (temporary)\n\t *\n\t * @param textNode Text node containing the word\n\t * @param startOffset Start position in text node\n\t * @param endOffset End position in text node\n\t */\n\thighlightTTSWord(\n\t\ttextNode: Text,\n\t\tstartOffset: number,\n\t\tendOffset: number,\n\t): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.applyAdaptiveTTSStyle(textNode.parentElement);\n\n\t\t// Clear previous word highlight\n\t\tthis.clearTTSWord();\n\n\t\t// Create range for word\n\t\tconst range = document.createRange();\n\t\trange.setStart(textNode, startOffset);\n\t\trange.setEnd(textNode, endOffset);\n\n\t\t// Add to highlight\n\t\tthis.ttsWordHighlight.add(range);\n\t}\n\n\t/**\n\t * Highlight a single element as the active TTS word (temporary).\n\t *\n\t * Unlike {@link highlightTTSWord} (which paints a CSS range over a text node)\n\t * this marks the element itself via `data-pie-tts-word-element`. It is used\n\t * for atomic targets that have no direct text node to range over — most\n\t * notably MathJax CHTML tokens (e.g. `<mjx-mi><mjx-c/></mjx-mi>`, whose glyph\n\t * lives in a font-driven pseudo-element a CSS range cannot paint) and\n\t * whole-expression fallbacks.\n\t *\n\t * The supplied element is painted exactly; we deliberately do NOT walk up to\n\t * a containing `<math>` / `<mjx-container>`. That escalation is what made\n\t * MathJax-rendered math highlight as a full block while native MathML tracked\n\t * per-token: a resolved single token must paint as a token, and only a\n\t * genuine expression fallback (where the element already is the container)\n\t * should paint the whole expression.\n\t */\n\thighlightTTSWordElement(element: Element): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.applyAdaptiveTTSStyle(element);\n\n\t\t// Clear previous word highlight (CSS range and any element attributes)\n\t\tthis.clearTTSWord();\n\n\t\telement.setAttribute(\"data-pie-tts-word-element\", \"true\");\n\t\tthis.ttsWordElementHighlights.add(element);\n\t}\n\n\t/**\n\t * Highlight the coarse TTS read-along band (temporary).\n\t * Usually one Range per visual line; CSS layer `tts-sentence` for compatibility.\n\t *\n\t * @param ranges Line (or sentence) ranges to paint with `--pie-tts-line-highlight`\n\t */\n\thighlightTTSSentence(ranges: Range[]): void {\n\t\tif (!this.ttsSentenceHighlight) return;\n\t\tconst source = ranges[0]?.startContainer;\n\t\tconst sourceElement =\n\t\t\tsource?.nodeType === Node.ELEMENT_NODE\n\t\t\t\t? (source as Element)\n\t\t\t\t: source?.parentElement;\n\t\tthis.applyAdaptiveTTSStyle(sourceElement);\n\n\t\t// Clear previous sentence highlight\n\t\tthis.clearTTSSentence();\n\n\t\t// Add all ranges\n\t\tfor (const range of ranges) {\n\t\t\tthis.ttsSentenceHighlight.add(range);\n\t\t}\n\t\tthis.highlightTTSElementFallbacks(ranges);\n\t}\n\n\t// The read-along (sentence) band legitimately covers whole equations and\n\t// replaced elements, so it escalates to them.\n\tprivate static readonly SENTENCE_FALLBACK_SELECTOR =\n\t\t\"math, mjx-container, svg, img, canvas, [role='img']\";\n\n\t// The word layer must NOT escalate a multi-node range to the enclosing\n\t// `<math>` / `<mjx-container>`: that is what made an equation flash as a\n\t// whole block whenever a spoken word's visible range crossed several math\n\t// glyph nodes. Math is tracked per token (or held / region) by the highlight\n\t// pipeline instead. Replaced elements (svg/img/canvas) still need the element\n\t// fallback because a CSS range cannot paint them.\n\tprivate static readonly WORD_FALLBACK_SELECTOR =\n\t\t\"svg, img, canvas, [role='img']\";\n\n\tprivate highlightTTSElementFallbacks(ranges: Range[]): void {\n\t\tif (typeof Element === \"undefined\") return;\n\t\tthis.highlightElementFallbacks(\n\t\t\tranges,\n\t\t\t\"data-pie-tts-sentence-element\",\n\t\t\tthis.ttsSentenceElementHighlights,\n\t\t\tHighlightCoordinator.SENTENCE_FALLBACK_SELECTOR,\n\t\t);\n\t}\n\n\tprivate highlightTTSWordElementFallbacks(ranges: Range[]): void {\n\t\tif (typeof Element === \"undefined\") return;\n\t\tthis.highlightElementFallbacks(\n\t\t\tranges,\n\t\t\t\"data-pie-tts-word-element\",\n\t\t\tthis.ttsWordElementHighlights,\n\t\t\tHighlightCoordinator.WORD_FALLBACK_SELECTOR,\n\t\t);\n\t}\n\n\tprivate highlightElementFallbacks(\n\t\tranges: Range[],\n\t\tattributeName: string,\n\t\ttrackedElements: Set<Element>,\n\t\tselector: string,\n\t): void {\n\t\tfor (const range of ranges) {\n\t\t\tconst root =\n\t\t\t\trange.commonAncestorContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.commonAncestorContainer as Element)\n\t\t\t\t\t: range.commonAncestorContainer.parentElement;\n\t\t\tif (!root) continue;\n\t\t\tconst candidates: Element[] = [];\n\t\t\tconst rangeStartElement =\n\t\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.startContainer as Element)\n\t\t\t\t\t: range.startContainer.parentElement;\n\t\t\tconst rangeEndElement =\n\t\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.endContainer as Element)\n\t\t\t\t\t: range.endContainer.parentElement;\n\t\t\tfor (const element of [rangeStartElement, rangeEndElement]) {\n\t\t\t\tlet current: Element | null = element;\n\t\t\t\twhile (current) {\n\t\t\t\t\tif (current.matches?.(selector)) candidates.push(current);\n\t\t\t\t\tcurrent = current.parentElement;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (root.matches?.(selector)) {\n\t\t\t\tcandidates.push(root);\n\t\t\t}\n\t\t\tcandidates.push(...Array.from(root.querySelectorAll(selector)));\n\t\t\tfor (const element of new Set(candidates)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!range.intersectsNode(element) &&\n\t\t\t\t\t\t!element.contains(rangeStartElement) &&\n\t\t\t\t\t\t!element.contains(rangeEndElement)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telement.setAttribute(attributeName, \"true\");\n\t\t\t\ttrackedElements.add(element);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear TTS word highlight\n\t */\n\tclearTTSWord(): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.ttsWordHighlight.clear();\n\t\tfor (const element of this.ttsWordElementHighlights) {\n\t\t\telement.removeAttribute(\"data-pie-tts-word-element\");\n\t\t}\n\t\tthis.ttsWordElementHighlights.clear();\n\t}\n\n\t/**\n\t * Clear TTS sentence highlight\n\t */\n\tclearTTSSentence(): void {\n\t\tif (!this.ttsSentenceHighlight) return;\n\t\tthis.ttsSentenceHighlight.clear();\n\t\tfor (const element of this.ttsSentenceElementHighlights) {\n\t\t\telement.removeAttribute(\"data-pie-tts-sentence-element\");\n\t\t}\n\t\tthis.ttsSentenceElementHighlights.clear();\n\t}\n\n\t/**\n\t * Clear all TTS highlights\n\t */\n\tclearTTS(): void {\n\t\tthis.clearTTSWord();\n\t\tthis.clearTTSSentence();\n\t}\n\n\t/**\n\t * Add an annotation highlight (persistent)\n\t *\n\t * @param range Text range to annotate\n\t * @param color Highlight color\n\t * @returns Annotation ID for later removal\n\t */\n\taddAnnotation(\n\t\trange: Range,\n\t\tcolor: HighlightColor = HighlightColor.YELLOW,\n\t): string {\n\t\tconst id = `annotation-${this.nextAnnotationId++}`;\n\n\t\t// Clone the range to store\n\t\tconst clonedRange = range.cloneRange();\n\n\t\t// Store annotation data\n\t\tconst annotation: Annotation = {\n\t\t\tid,\n\t\t\trange: clonedRange,\n\t\t\ttype: HighlightType.ANNOTATION,\n\t\t\tcolor,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\t\tthis.annotations.set(id, annotation);\n\n\t\t// Add the SAME range object to the shared color highlight\n\t\t// This ensures we can later delete it by reference\n\t\tconst colorHighlight = this.colorHighlights.get(color);\n\t\tif (colorHighlight) {\n\t\t\tcolorHighlight.add(clonedRange);\n\t\t}\n\n\t\treturn id;\n\t}\n\n\t/**\n\t * Remove an annotation\n\t *\n\t * @param id Annotation ID\n\t */\n\tremoveAnnotation(id: string): void {\n\t\tconst annotation = this.annotations.get(id);\n\t\tif (!annotation) {\n\t\t\tconsole.warn(`[HighlightCoordinator] Annotation ${id} not found`);\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`[HighlightCoordinator] Removing annotation ${id} (color: ${annotation.color})`,\n\t\t);\n\n\t\t// Remove range from the shared color highlight\n\t\tconst colorHighlight = this.colorHighlights.get(annotation.color);\n\t\tif (colorHighlight) {\n\t\t\tconst deleted = colorHighlight.delete(annotation.range);\n\t\t\tconsole.log(\n\t\t\t\t`[HighlightCoordinator] Highlight.delete() returned:`,\n\t\t\t\tdeleted,\n\t\t\t);\n\t\t}\n\n\t\t// Clean up\n\t\tthis.annotations.delete(id);\n\t\tconsole.log(\n\t\t\t`[HighlightCoordinator] Annotation ${id} removed from map. Remaining:`,\n\t\t\tthis.annotations.size,\n\t\t);\n\t}\n\n\t/**\n\t * Remove all annotations\n\t */\n\tclearAnnotations(): void {\n\t\t// Clear all color highlights\n\t\tfor (const colorHighlight of this.colorHighlights.values()) {\n\t\t\tcolorHighlight.clear();\n\t\t}\n\n\t\t// Clear annotation data\n\t\tthis.annotations.clear();\n\t}\n\n\t/**\n\t * Get all annotations\n\t */\n\tgetAnnotations(): Annotation[] {\n\t\treturn Array.from(this.annotations.values());\n\t}\n\n\t/**\n\t * Get annotation by ID\n\t */\n\tgetAnnotation(id: string): Annotation | null {\n\t\treturn this.annotations.get(id) ?? null;\n\t}\n\n\t/**\n\t * Change annotation color\n\t *\n\t * @param id Annotation ID\n\t * @param newColor New color\n\t */\n\tchangeAnnotationColor(id: string, newColor: HighlightColor): void {\n\t\tconst annotation = this.annotations.get(id);\n\t\tif (!annotation) return;\n\n\t\tconst oldColor = annotation.color;\n\t\tif (oldColor === newColor) return;\n\n\t\t// Remove from old color highlight\n\t\tconst oldColorHighlight = this.colorHighlights.get(oldColor);\n\t\tif (oldColorHighlight) {\n\t\t\toldColorHighlight.delete(annotation.range);\n\t\t}\n\n\t\t// Update color\n\t\tannotation.color = newColor;\n\n\t\t// Add to new color highlight\n\t\tconst newColorHighlight = this.colorHighlights.get(newColor);\n\t\tif (newColorHighlight) {\n\t\t\tnewColorHighlight.add(annotation.range);\n\t\t}\n\t}\n\n\t/**\n\t * Export annotations as serializable data for persistence.\n\t * Uses RangeSerializer for robust DOM range serialization.\n\t *\n\t * @param root Root element for serialization (typically document.body or content container)\n\t * @returns Array of serialized annotations\n\t */\n\texportAnnotations(\n\t\troot: Element = document.body,\n\t): Array<\n\t\tSerializedRange & { id: string; color: HighlightColor; timestamp: number }\n\t> {\n\t\treturn this.getAnnotations().map((annotation) => ({\n\t\t\t...this.rangeSerializer.serialize(annotation.range, root),\n\t\t\tid: annotation.id,\n\t\t\tcolor: annotation.color,\n\t\t\ttimestamp: annotation.timestamp,\n\t\t}));\n\t}\n\n\t/**\n\t * Import annotations from serialized data.\n\t * Restores annotations after page navigation or refresh.\n\t *\n\t * @param data Array of serialized annotations\n\t * @param root Root element for deserialization (same as used in export)\n\t * @returns Number of successfully restored annotations\n\t */\n\timportAnnotations(\n\t\tdata: Array<\n\t\t\tSerializedRange & {\n\t\t\t\tid?: string;\n\t\t\t\tcolor: HighlightColor;\n\t\t\t\ttimestamp?: number;\n\t\t\t}\n\t\t>,\n\t\troot: Element = document.body,\n\t): number {\n\t\tlet restored = 0;\n\n\t\tfor (const item of data) {\n\t\t\tconst range = this.rangeSerializer.deserialize(item, root);\n\t\t\tif (range) {\n\t\t\t\tthis.addAnnotation(range, item.color);\n\t\t\t\trestored++;\n\t\t\t}\n\t\t}\n\n\t\treturn restored;\n\t}\n\n\t// ============================================================================\n\t// HighlightCoordinatorApi interface implementation\n\t// ============================================================================\n\n\t/**\n\t * Highlight a text range (interface method)\n\t *\n\t * Generic method that adapts to the specific highlight type.\n\t * For more control, use the specific methods like highlightTTSWord().\n\t */\n\thighlightRange(\n\t\trange: Range,\n\t\ttype: HighlightType,\n\t\tcolor: HighlightColor = HighlightColor.YELLOW,\n\t): void {\n\t\tif (!this.supported) return;\n\n\t\tswitch (type) {\n\t\t\tcase HighlightType.TTS_WORD:\n\t\t\tcase HighlightType.TTS_SENTENCE: {\n\t\t\t\t// For TTS, add to appropriate highlight\n\t\t\t\tconst highlight =\n\t\t\t\t\ttype === HighlightType.TTS_WORD\n\t\t\t\t\t\t? this.ttsWordHighlight\n\t\t\t\t\t\t: this.ttsSentenceHighlight;\n\t\t\t\tif (highlight) {\n\t\t\t\t\thighlight.clear();\n\t\t\t\t\thighlight.add(range);\n\t\t\t\t\tif (type === HighlightType.TTS_WORD) {\n\t\t\t\t\t\tfor (const element of this.ttsWordElementHighlights) {\n\t\t\t\t\t\t\telement.removeAttribute(\"data-pie-tts-word-element\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.ttsWordElementHighlights.clear();\n\t\t\t\t\t\tthis.highlightTTSWordElementFallbacks([range]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase HighlightType.ANNOTATION:\n\t\t\t\t// For annotations, use the existing method\n\t\t\t\tthis.addAnnotation(range, color);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Clear highlights of a specific type (interface method)\n\t */\n\tclearHighlights(type: HighlightType): void {\n\t\tif (!this.supported) return;\n\n\t\tswitch (type) {\n\t\t\tcase HighlightType.TTS_WORD:\n\t\t\t\tthis.clearTTSWord();\n\t\t\t\tbreak;\n\t\t\tcase HighlightType.TTS_SENTENCE:\n\t\t\t\tthis.clearTTSSentence();\n\t\t\t\tbreak;\n\t\t\tcase HighlightType.ANNOTATION:\n\t\t\t\tthis.clearAnnotations();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Clear all highlights (interface method)\n\t */\n\tclearAll(): void {\n\t\tif (!this.supported) return;\n\t\tthis.clearTTS();\n\t\tthis.clearAnnotations();\n\t}\n\n\t/**\n\t * Check if CSS Highlight API is supported (interface method)\n\t */\n\tisSupported(): boolean {\n\t\treturn this.supported;\n\t}\n\n\t/**\n\t * Update TTS highlight style dynamically\n\t *\n\t * @param color CSS color value (e.g., '#ffeb3b')\n\t * @param opacity Opacity value (0.0 to 1.0)\n\t */\n\tupdateTTSHighlightStyle(color: string, opacity: number): void {\n\t\tif (!this.supported) return;\n\t\tif (typeof document === \"undefined\") return;\n\n\t\tconst styleEl = document.getElementById(\"pie-highlight-styles\");\n\t\tif (!styleEl) return;\n\n\t\t// Convert hex to rgba\n\t\tconst hexToRgb = (hex: string) => {\n\t\t\tconst result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\t\t\treturn result\n\t\t\t\t? {\n\t\t\t\t\t\tr: parseInt(result[1], 16),\n\t\t\t\t\t\tg: parseInt(result[2], 16),\n\t\t\t\t\t\tb: parseInt(result[3], 16),\n\t\t\t\t\t}\n\t\t\t\t: null;\n\t\t};\n\n\t\tconst rgb = hexToRgb(color);\n\t\tif (!rgb) return;\n\n\t\tthis.explicitTTSColorOverride = {\n\t\t\tcolor: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`,\n\t\t\topacity: Math.max(0.2, Math.min(0.95, opacity)),\n\t\t};\n\t\tthis.applyAdaptiveTTSStyle();\n\t}\n\n\t/**\n\t * Cleanup - remove all highlights\n\t */\n\tdestroy(): void {\n\t\tif (!this.supported) return;\n\n\t\tthis.clearTTS();\n\t\tthis.clearAnnotations();\n\n\t\t// Remove style element\n\t\tif (typeof document !== \"undefined\") {\n\t\t\tconst styleEl = document.getElementById(\"pie-highlight-styles\");\n\t\t\tif (styleEl) {\n\t\t\t\tstyleEl.remove();\n\t\t\t}\n\t\t}\n\t\tthis.themeObserver?.disconnect();\n\t\tthis.themeObserver = null;\n\t}\n}\n"]}
1
+ {"version":3,"file":"HighlightCoordinator.js","sourceRoot":"","sources":["../../src/services/HighlightCoordinator.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HighlightCoordinator\n *\n * Manages separate highlight layers for TTS (temporary) and annotations (persistent).\n * Uses CSS Custom Highlight API - zero DOM mutation, preserves accessibility.\n *\n * Features:\n * - Separate layers prevent TTS clearing from removing student annotations\n * - CSS Custom Highlight API (no DOM mutation)\n * - Full accessibility support (screen readers see original text)\n * - Configurable colors and styles\n * - Annotation persistence via RangeSerializer\n *\n * Part of PIE Assessment Toolkit.\n *\n * Browser Support:\n * - Chrome/Edge 105+\n * - Safari 17.2+\n * - Firefox: Behind flag (not recommended for production)\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/CSS_Custom_Highlight_API\n */\n\nimport type { HighlightCoordinatorApi } from \"./interfaces.js\";\nimport { RangeSerializer, type SerializedRange } from \"./RangeSerializer.js\";\n\n/**\n * Highlight types\n */\nexport enum HighlightType {\n\tTTS_WORD = \"tts-word\",\n\tTTS_SENTENCE = \"tts-sentence\",\n\tANNOTATION = \"annotation\",\n}\n\n/**\n * Highlight colors for annotations\n */\nexport enum HighlightColor {\n\tYELLOW = \"yellow\",\n\tGREEN = \"green\",\n\tBLUE = \"blue\",\n\tPINK = \"pink\",\n\tORANGE = \"orange\",\n\tUNDERLINE = \"underline\",\n}\n\n/**\n * Annotation data\n */\nexport interface Annotation {\n\tid: string;\n\trange: Range;\n\ttype: HighlightType.ANNOTATION;\n\tcolor: HighlightColor;\n\ttimestamp: number;\n}\n\n/**\n * Configuration for HighlightCoordinator\n * Currently empty but allows future extension without breaking changes\n */\nexport type HighlightCoordinatorConfig = Record<string, never>;\n\nexport class HighlightCoordinator implements HighlightCoordinatorApi {\n\tprivate config: HighlightCoordinatorConfig;\n\tprivate ttsWordHighlight: Highlight | null = null;\n\tprivate ttsSentenceHighlight: Highlight | null = null;\n\tprivate ttsWordElementHighlights = new Set<Element>();\n\tprivate ttsSentenceElementHighlights = new Set<Element>();\n\tprivate annotations = new Map<string, Annotation>();\n\t// Shared highlights per color (one Highlight object per color, contains all ranges)\n\tprivate colorHighlights = new Map<HighlightColor, Highlight>();\n\tprivate nextAnnotationId = 1;\n\tprivate supported = false;\n\tprivate rangeSerializer: RangeSerializer;\n\tprivate themeObserver: MutationObserver | null = null;\n\tprivate explicitTTSColorOverride: { color: string; opacity: number } | null =\n\t\tnull;\n\n\tconstructor(config: HighlightCoordinatorConfig = {}) {\n\t\tthis.config = config;\n\t\tthis.rangeSerializer = new RangeSerializer();\n\n\t\t// SSR guard\n\t\tif (typeof CSS === \"undefined\" || !(\"highlights\" in CSS)) {\n\t\t\tconsole.warn(\n\t\t\t\t\"CSS Custom Highlight API not supported (SSR or unsupported browser)\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.supported = true;\n\t\tthis.initializeHighlights();\n\t\tthis.registerStyles();\n\t\tthis.applyAdaptiveTTSStyle();\n\t\tthis.setupThemeObservation();\n\t}\n\n\tprivate setupThemeObservation(): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tif (typeof MutationObserver === \"undefined\") return;\n\n\t\tconst refresh = () => this.applyAdaptiveTTSStyle();\n\t\tthis.themeObserver = new MutationObserver(refresh);\n\n\t\tthis.themeObserver.observe(document.documentElement, {\n\t\t\tattributes: true,\n\t\t\tattributeFilter: [\"style\", \"data-theme\", \"data-color-scheme\", \"class\"],\n\t\t});\n\n\t\tfor (const host of document.querySelectorAll(\"pie-theme\")) {\n\t\t\tthis.themeObserver.observe(host, {\n\t\t\t\tattributes: true,\n\t\t\t\tattributeFilter: [\n\t\t\t\t\t\"theme\",\n\t\t\t\t\t\"scheme\",\n\t\t\t\t\t\"provider\",\n\t\t\t\t\t\"variables\",\n\t\t\t\t\t\"style\",\n\t\t\t\t\t\"data-theme\",\n\t\t\t\t\t\"data-color-scheme\",\n\t\t\t\t],\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate parseColor(\n\t\tinput: string | null | undefined,\n\t): [number, number, number] | null {\n\t\tif (!input) return null;\n\t\tconst value = input.trim();\n\t\tif (!value) return null;\n\n\t\tconst hexMatch = /^#([a-f\\d]{3}|[a-f\\d]{6})$/i.exec(value);\n\t\tif (hexMatch) {\n\t\t\tconst hex = hexMatch[1];\n\t\t\tif (hex.length === 3) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt(hex[0] + hex[0], 16),\n\t\t\t\t\tparseInt(hex[1] + hex[1], 16),\n\t\t\t\t\tparseInt(hex[2] + hex[2], 16),\n\t\t\t\t];\n\t\t\t}\n\t\t\treturn [\n\t\t\t\tparseInt(hex.slice(0, 2), 16),\n\t\t\t\tparseInt(hex.slice(2, 4), 16),\n\t\t\t\tparseInt(hex.slice(4, 6), 16),\n\t\t\t];\n\t\t}\n\n\t\tconst rgbMatch = /^rgba?\\((.+)\\)$/i.exec(value);\n\t\tif (rgbMatch) {\n\t\t\tconst normalized = rgbMatch[1].replace(/\\//g, \",\");\n\t\t\tconst parts = normalized\n\t\t\t\t.split(/[,\\s]+/)\n\t\t\t\t.map((part) => part.trim())\n\t\t\t\t.filter(Boolean);\n\t\t\tconst r = Number(parts[0]);\n\t\t\tconst g = Number(parts[1]);\n\t\t\tconst b = Number(parts[2]);\n\t\t\tif (Number.isFinite(r) && Number.isFinite(g) && Number.isFinite(b)) {\n\t\t\t\treturn [r, g, b];\n\t\t\t}\n\t\t}\n\n\t\t// Browser parser fallback (covers formats like oklch()).\n\t\tif (typeof document !== \"undefined\") {\n\t\t\tconst parserEl = document.createElement(\"span\");\n\t\t\tparserEl.style.color = value;\n\t\t\tif (typeof parserEl.style.color === \"string\" && parserEl.style.color) {\n\t\t\t\tdocument.body?.appendChild(parserEl);\n\t\t\t\tconst resolved =\n\t\t\t\t\ttypeof getComputedStyle === \"function\"\n\t\t\t\t\t\t? getComputedStyle(parserEl).color\n\t\t\t\t\t\t: \"\";\n\t\t\t\tparserEl.remove();\n\t\t\t\tconst normalizedResolved = resolved.trim();\n\t\t\t\t// Guard against recursive loops when computed style returns the same\n\t\t\t\t// unresolved function syntax (observed with certain color formats).\n\t\t\t\tif (normalizedResolved && normalizedResolved !== value) {\n\t\t\t\t\treturn this.parseColor(resolved);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate relativeLuminance([r, g, b]: [number, number, number]): number {\n\t\tconst toLinear = (channel: number) => {\n\t\t\tconst n = channel / 255;\n\t\t\treturn n <= 0.03928 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;\n\t\t};\n\t\tconst lr = toLinear(r);\n\t\tconst lg = toLinear(g);\n\t\tconst lb = toLinear(b);\n\t\treturn 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;\n\t}\n\n\tprivate contrastRatio(\n\t\ta: [number, number, number],\n\t\tb: [number, number, number],\n\t): number {\n\t\tconst la = this.relativeLuminance(a);\n\t\tconst lb = this.relativeLuminance(b);\n\t\tconst lighter = Math.max(la, lb);\n\t\tconst darker = Math.min(la, lb);\n\t\treturn (lighter + 0.05) / (darker + 0.05);\n\t}\n\n\tprivate blend(\n\t\tfg: [number, number, number],\n\t\tbg: [number, number, number],\n\t\talpha: number,\n\t): [number, number, number] {\n\t\treturn [\n\t\t\tMath.round(fg[0] * alpha + bg[0] * (1 - alpha)),\n\t\t\tMath.round(fg[1] * alpha + bg[1] * (1 - alpha)),\n\t\t\tMath.round(fg[2] * alpha + bg[2] * (1 - alpha)),\n\t\t];\n\t}\n\n\tprivate resolveAdaptiveTTSStyle(sourceEl?: Element | null): {\n\t\twordHighlight: string;\n\t\tsentenceHighlight: string;\n\t\twordUnderline: string;\n\t\twordShadow: string;\n\t} {\n\t\tconst fallbackMissing: [number, number, number] = [255, 235, 59];\n\t\tconst fallbackText: [number, number, number] = [17, 24, 39];\n\t\tconst fallbackBackground: [number, number, number] = [255, 255, 255];\n\n\t\tconst target =\n\t\t\tsourceEl ||\n\t\t\t(typeof document !== \"undefined\" ? document.documentElement : null);\n\t\tconst computed =\n\t\t\ttarget && typeof getComputedStyle === \"function\"\n\t\t\t\t? getComputedStyle(target)\n\t\t\t\t: null;\n\n\t\tconst background =\n\t\t\tthis.parseColor(\n\t\t\t\tcomputed?.getPropertyValue(\"--pie-background\") ||\n\t\t\t\t\tcomputed?.backgroundColor,\n\t\t\t) || fallbackBackground;\n\t\tconst text =\n\t\t\tthis.parseColor(computed?.getPropertyValue(\"--pie-text\")) || fallbackText;\n\t\tconst accent = this.explicitTTSColorOverride\n\t\t\t? this.parseColor(this.explicitTTSColorOverride.color) || fallbackMissing\n\t\t\t: this.parseColor(computed?.getPropertyValue(\"--pie-missing\")) ||\n\t\t\t\tfallbackMissing;\n\n\t\tconst opacityCandidates = this.explicitTTSColorOverride\n\t\t\t? [Math.max(0.3, Math.min(0.95, this.explicitTTSColorOverride.opacity))]\n\t\t\t: [0.8, 0.72, 0.68, 0.62, 0.56, 0.5];\n\n\t\tlet selectedOpacity = opacityCandidates[opacityCandidates.length - 1];\n\t\tlet bestScore = -Infinity;\n\n\t\tfor (const opacity of opacityCandidates) {\n\t\t\tconst blended = this.blend(accent, background, opacity);\n\t\t\tconst backgroundDelta = this.contrastRatio(blended, background);\n\t\t\tconst textContrast = this.contrastRatio(blended, text);\n\t\t\tconst score = backgroundDelta * 1.2 + textContrast * 0.8;\n\t\t\tif (backgroundDelta >= 1.25 && textContrast >= 2.4) {\n\t\t\t\tselectedOpacity = opacity;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (score > bestScore) {\n\t\t\t\tbestScore = score;\n\t\t\t\tselectedOpacity = opacity;\n\t\t\t}\n\t\t}\n\n\t\tconst sentenceOpacity = Math.max(\n\t\t\t0.24,\n\t\t\tMath.min(0.85, selectedOpacity * 0.55),\n\t\t);\n\t\tconst underlineOpacity = Math.max(\n\t\t\t0.55,\n\t\t\tMath.min(0.95, selectedOpacity + 0.2),\n\t\t);\n\t\tconst shadowOpacity = Math.max(0.22, Math.min(0.6, selectedOpacity * 0.45));\n\n\t\tconst underlineColor = text;\n\t\tconst underlineBlend = this.blend(\n\t\t\tunderlineColor,\n\t\t\tbackground,\n\t\t\tunderlineOpacity,\n\t\t);\n\t\tconst underlineDelta = this.contrastRatio(underlineBlend, background);\n\t\tconst fallbackUnderline: [number, number, number] =\n\t\t\tthis.relativeLuminance(background) > 0.45 ? [0, 0, 0] : [255, 255, 255];\n\t\tconst finalUnderline =\n\t\t\tunderlineDelta >= 1.35 ? underlineColor : fallbackUnderline;\n\n\t\tconst wordHighlight = `rgba(${accent[0]}, ${accent[1]}, ${accent[2]}, ${selectedOpacity})`;\n\t\tconst sentenceHighlight = `rgba(${accent[0]}, ${accent[1]}, ${accent[2]}, ${sentenceOpacity})`;\n\t\tconst wordUnderline = `rgba(${finalUnderline[0]}, ${finalUnderline[1]}, ${finalUnderline[2]}, ${underlineOpacity})`;\n\t\tconst wordShadow = `rgba(${finalUnderline[0]}, ${finalUnderline[1]}, ${finalUnderline[2]}, ${shadowOpacity})`;\n\n\t\treturn {\n\t\t\twordHighlight,\n\t\t\tsentenceHighlight,\n\t\t\twordUnderline,\n\t\t\twordShadow,\n\t\t};\n\t}\n\n\tprivate applyAdaptiveTTSStyle(sourceEl?: Element | null): void {\n\t\tif (typeof document === \"undefined\") return;\n\t\tconst vars = this.resolveAdaptiveTTSStyle(sourceEl);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-highlight\",\n\t\t\tvars.wordHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-sentence-highlight\",\n\t\t\tvars.sentenceHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-line-highlight\",\n\t\t\tvars.sentenceHighlight,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-underline\",\n\t\t\tvars.wordUnderline,\n\t\t);\n\t\tdocument.documentElement.style.setProperty(\n\t\t\t\"--pie-tts-word-shadow\",\n\t\t\tvars.wordShadow,\n\t\t);\n\t}\n\n\t/**\n\t * Initialize CSS Custom Highlights\n\t */\n\tprivate initializeHighlights(): void {\n\t\tif (!this.supported) return;\n\n\t\t// Create highlight registries for TTS\n\t\tthis.ttsWordHighlight = new Highlight();\n\t\tthis.ttsSentenceHighlight = new Highlight();\n\n\t\t// Register TTS highlights with CSS\n\t\tCSS.highlights.set(\"tts-word\", this.ttsWordHighlight);\n\t\tCSS.highlights.set(\"tts-sentence\", this.ttsSentenceHighlight);\n\n\t\t// Create shared highlights for each annotation color\n\t\tfor (const color of Object.values(HighlightColor)) {\n\t\t\tconst highlight = new Highlight();\n\t\t\tthis.colorHighlights.set(color, highlight);\n\t\t\tCSS.highlights.set(`annotation-${color}`, highlight);\n\t\t}\n\t}\n\n\t/**\n\t * Register CSS styles for highlights\n\t */\n\tprivate registerStyles(): void {\n\t\tif (!this.supported) return;\n\t\tif (typeof document === \"undefined\") return; // SSR guard\n\n\t\t// Check if styles already exist\n\t\tif (document.getElementById(\"pie-highlight-styles\")) return;\n\n\t\tconst style = document.createElement(\"style\");\n\t\tstyle.id = \"pie-highlight-styles\";\n\t\tstyle.textContent = `\n /* TTS highlights - temporary */\n ::highlight(tts-word) {\n background-color: var(--pie-tts-word-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 68%, transparent));\n text-decoration: underline 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n text-underline-offset: 2px;\n text-shadow: 0 0 1px var(--pie-tts-word-shadow, color-mix(in srgb, var(--pie-text, #111827) 35%, transparent));\n color: inherit;\n }\n\n /* tts-sentence registry id: coarse read-along band (visual line boxes in layout) */\n ::highlight(tts-sentence) {\n background-color: var(--pie-tts-line-highlight, var(--pie-tts-sentence-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 38%, transparent)));\n color: inherit;\n }\n\n [data-pie-tts-sentence-element=\"true\"] {\n background-color: var(--pie-tts-line-highlight, var(--pie-tts-sentence-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 38%, transparent)));\n border-radius: 0.12em;\n box-decoration-break: clone;\n -webkit-box-decoration-break: clone;\n }\n\n [data-pie-tts-word-element=\"true\"] {\n background-color: var(--pie-tts-word-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 68%, transparent));\n text-decoration: underline 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n text-underline-offset: 2px;\n text-shadow: 0 0 1px var(--pie-tts-word-shadow, color-mix(in srgb, var(--pie-text, #111827) 35%, transparent));\n border-bottom: 2px solid var(--pie-tts-word-underline, color-mix(in srgb, var(--pie-text, #111827) 70%, transparent));\n padding-bottom: 1px;\n border-radius: 0.12em;\n box-decoration-break: clone;\n -webkit-box-decoration-break: clone;\n }\n\n /* Annotation highlights - persistent */\n ::highlight(annotation-yellow) {\n background-color: var(--pie-annotation-yellow-highlight, rgba(253, 233, 149, 0.5));\n color: inherit;\n }\n\n ::highlight(annotation-green) {\n background-color: var(--pie-annotation-green-highlight, rgba(166, 225, 197, 0.5));\n color: inherit;\n }\n\n ::highlight(annotation-blue) {\n background-color: var(--pie-annotation-blue-highlight, rgba(167, 224, 246, 0.5));\n color: inherit;\n }\n\n ::highlight(annotation-pink) {\n background-color: var(--pie-annotation-pink-highlight, rgba(255, 159, 174, 0.5));\n color: inherit;\n }\n\n ::highlight(annotation-orange) {\n background-color: var(--pie-annotation-orange-highlight, rgba(255, 165, 0, 0.5));\n color: inherit;\n }\n\n ::highlight(annotation-underline) {\n background-color: transparent;\n text-decoration: underline 2px solid var(--pie-primary, #0066cc);\n text-underline-offset: 2px;\n color: inherit;\n }\n `;\n\t\tdocument.head.appendChild(style);\n\t}\n\n\t/**\n\t * Highlight a word for TTS (temporary)\n\t *\n\t * @param textNode Text node containing the word\n\t * @param startOffset Start position in text node\n\t * @param endOffset End position in text node\n\t */\n\thighlightTTSWord(\n\t\ttextNode: Text,\n\t\tstartOffset: number,\n\t\tendOffset: number,\n\t): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.applyAdaptiveTTSStyle(textNode.parentElement);\n\n\t\t// Clear previous word highlight\n\t\tthis.clearTTSWord();\n\n\t\t// Create range for word\n\t\tconst range = document.createRange();\n\t\trange.setStart(textNode, startOffset);\n\t\trange.setEnd(textNode, endOffset);\n\n\t\t// Add to highlight\n\t\tthis.ttsWordHighlight.add(range);\n\t}\n\n\t/**\n\t * Highlight a single element as the active TTS word (temporary).\n\t *\n\t * Unlike {@link highlightTTSWord} (which paints a CSS range over a text node)\n\t * this marks the element itself via `data-pie-tts-word-element`. It is used\n\t * for atomic targets that have no direct text node to range over — most\n\t * notably MathJax CHTML tokens (e.g. `<mjx-mi><mjx-c/></mjx-mi>`, whose glyph\n\t * lives in a font-driven pseudo-element a CSS range cannot paint) and\n\t * whole-expression fallbacks.\n\t *\n\t * The supplied element is painted exactly; we deliberately do NOT walk up to\n\t * a containing `<math>` / `<mjx-container>`. That escalation is what made\n\t * MathJax-rendered math highlight as a full block while native MathML tracked\n\t * per-token: a resolved single token must paint as a token, and only a\n\t * genuine expression fallback (where the element already is the container)\n\t * should paint the whole expression.\n\t */\n\thighlightTTSWordElement(element: Element): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.applyAdaptiveTTSStyle(element);\n\n\t\t// Clear previous word highlight (CSS range and any element attributes)\n\t\tthis.clearTTSWord();\n\n\t\telement.setAttribute(\"data-pie-tts-word-element\", \"true\");\n\t\tthis.ttsWordElementHighlights.add(element);\n\t}\n\n\t/**\n\t * Highlight the coarse TTS read-along band (temporary).\n\t * Usually one Range per visual line; CSS layer `tts-sentence` for compatibility.\n\t *\n\t * @param ranges Line (or sentence) ranges to paint with `--pie-tts-line-highlight`\n\t */\n\thighlightTTSSentence(ranges: Range[]): void {\n\t\tif (!this.ttsSentenceHighlight) return;\n\t\tconst source = ranges[0]?.startContainer;\n\t\tconst sourceElement =\n\t\t\tsource?.nodeType === Node.ELEMENT_NODE\n\t\t\t\t? (source as Element)\n\t\t\t\t: source?.parentElement;\n\t\tthis.applyAdaptiveTTSStyle(sourceElement);\n\n\t\t// Clear previous sentence highlight\n\t\tthis.clearTTSSentence();\n\n\t\t// Add all ranges\n\t\tfor (const range of ranges) {\n\t\t\tthis.ttsSentenceHighlight.add(range);\n\t\t}\n\t\tthis.highlightTTSElementFallbacks(ranges);\n\t}\n\n\t/**\n\t * Highlight sentence/block elements for TTS (background layer).\n\t *\n\t * @param elements Visible elements to paint with `--pie-tts-line-highlight`\n\t */\n\thighlightTTSSentenceElements(elements: Element[]): void {\n\t\tif (!this.ttsSentenceHighlight) return;\n\t\tthis.applyAdaptiveTTSStyle(elements[0] || null);\n\n\t\tthis.clearTTSSentence();\n\n\t\tfor (const element of elements) {\n\t\t\telement.setAttribute(\"data-pie-tts-sentence-element\", \"true\");\n\t\t\tthis.ttsSentenceElementHighlights.add(element);\n\t\t}\n\t}\n\n\t// The read-along (sentence) band legitimately covers whole equations and\n\t// replaced elements, so it escalates to them.\n\tprivate static readonly SENTENCE_FALLBACK_SELECTOR =\n\t\t\"math, mjx-container, svg, img, canvas, [role='img']\";\n\n\t// The word layer must NOT escalate a multi-node range to the enclosing\n\t// `<math>` / `<mjx-container>`: that is what made an equation flash as a\n\t// whole block whenever a spoken word's visible range crossed several math\n\t// glyph nodes. Math is tracked per token (or held / region) by the highlight\n\t// pipeline instead. Replaced elements (svg/img/canvas) still need the element\n\t// fallback because a CSS range cannot paint them.\n\tprivate static readonly WORD_FALLBACK_SELECTOR =\n\t\t\"svg, img, canvas, [role='img']\";\n\n\tprivate highlightTTSElementFallbacks(ranges: Range[]): void {\n\t\tif (typeof Element === \"undefined\") return;\n\t\tthis.highlightElementFallbacks(\n\t\t\tranges,\n\t\t\t\"data-pie-tts-sentence-element\",\n\t\t\tthis.ttsSentenceElementHighlights,\n\t\t\tHighlightCoordinator.SENTENCE_FALLBACK_SELECTOR,\n\t\t);\n\t}\n\n\tprivate highlightTTSWordElementFallbacks(ranges: Range[]): void {\n\t\tif (typeof Element === \"undefined\") return;\n\t\tthis.highlightElementFallbacks(\n\t\t\tranges,\n\t\t\t\"data-pie-tts-word-element\",\n\t\t\tthis.ttsWordElementHighlights,\n\t\t\tHighlightCoordinator.WORD_FALLBACK_SELECTOR,\n\t\t);\n\t}\n\n\tprivate highlightElementFallbacks(\n\t\tranges: Range[],\n\t\tattributeName: string,\n\t\ttrackedElements: Set<Element>,\n\t\tselector: string,\n\t): void {\n\t\tfor (const range of ranges) {\n\t\t\tconst root =\n\t\t\t\trange.commonAncestorContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.commonAncestorContainer as Element)\n\t\t\t\t\t: range.commonAncestorContainer.parentElement;\n\t\t\tif (!root) continue;\n\t\t\tconst candidates: Element[] = [];\n\t\t\tconst rangeStartElement =\n\t\t\t\trange.startContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.startContainer as Element)\n\t\t\t\t\t: range.startContainer.parentElement;\n\t\t\tconst rangeEndElement =\n\t\t\t\trange.endContainer.nodeType === Node.ELEMENT_NODE\n\t\t\t\t\t? (range.endContainer as Element)\n\t\t\t\t\t: range.endContainer.parentElement;\n\t\t\tfor (const element of [rangeStartElement, rangeEndElement]) {\n\t\t\t\tlet current: Element | null = element;\n\t\t\t\twhile (current) {\n\t\t\t\t\tif (current.matches?.(selector)) candidates.push(current);\n\t\t\t\t\tcurrent = current.parentElement;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (root.matches?.(selector)) {\n\t\t\t\tcandidates.push(root);\n\t\t\t}\n\t\t\tcandidates.push(...Array.from(root.querySelectorAll(selector)));\n\t\t\tfor (const element of new Set(candidates)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!range.intersectsNode(element) &&\n\t\t\t\t\t\t!element.contains(rangeStartElement) &&\n\t\t\t\t\t\t!element.contains(rangeEndElement)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telement.setAttribute(attributeName, \"true\");\n\t\t\t\ttrackedElements.add(element);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear TTS word highlight\n\t */\n\tclearTTSWord(): void {\n\t\tif (!this.ttsWordHighlight) return;\n\t\tthis.ttsWordHighlight.clear();\n\t\tfor (const element of this.ttsWordElementHighlights) {\n\t\t\telement.removeAttribute(\"data-pie-tts-word-element\");\n\t\t}\n\t\tthis.ttsWordElementHighlights.clear();\n\t}\n\n\t/**\n\t * Clear TTS sentence highlight\n\t */\n\tclearTTSSentence(): void {\n\t\tif (!this.ttsSentenceHighlight) return;\n\t\tthis.ttsSentenceHighlight.clear();\n\t\tfor (const element of this.ttsSentenceElementHighlights) {\n\t\t\telement.removeAttribute(\"data-pie-tts-sentence-element\");\n\t\t}\n\t\tthis.ttsSentenceElementHighlights.clear();\n\t}\n\n\t/**\n\t * Clear all TTS highlights\n\t */\n\tclearTTS(): void {\n\t\tthis.clearTTSWord();\n\t\tthis.clearTTSSentence();\n\t}\n\n\t/**\n\t * Add an annotation highlight (persistent)\n\t *\n\t * @param range Text range to annotate\n\t * @param color Highlight color\n\t * @returns Annotation ID for later removal\n\t */\n\taddAnnotation(\n\t\trange: Range,\n\t\tcolor: HighlightColor = HighlightColor.YELLOW,\n\t): string {\n\t\tconst id = `annotation-${this.nextAnnotationId++}`;\n\n\t\t// Clone the range to store\n\t\tconst clonedRange = range.cloneRange();\n\n\t\t// Store annotation data\n\t\tconst annotation: Annotation = {\n\t\t\tid,\n\t\t\trange: clonedRange,\n\t\t\ttype: HighlightType.ANNOTATION,\n\t\t\tcolor,\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\t\tthis.annotations.set(id, annotation);\n\n\t\t// Add the SAME range object to the shared color highlight\n\t\t// This ensures we can later delete it by reference\n\t\tconst colorHighlight = this.colorHighlights.get(color);\n\t\tif (colorHighlight) {\n\t\t\tcolorHighlight.add(clonedRange);\n\t\t}\n\n\t\treturn id;\n\t}\n\n\t/**\n\t * Remove an annotation\n\t *\n\t * @param id Annotation ID\n\t */\n\tremoveAnnotation(id: string): void {\n\t\tconst annotation = this.annotations.get(id);\n\t\tif (!annotation) {\n\t\t\tconsole.warn(`[HighlightCoordinator] Annotation ${id} not found`);\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`[HighlightCoordinator] Removing annotation ${id} (color: ${annotation.color})`,\n\t\t);\n\n\t\t// Remove range from the shared color highlight\n\t\tconst colorHighlight = this.colorHighlights.get(annotation.color);\n\t\tif (colorHighlight) {\n\t\t\tconst deleted = colorHighlight.delete(annotation.range);\n\t\t\tconsole.log(\n\t\t\t\t`[HighlightCoordinator] Highlight.delete() returned:`,\n\t\t\t\tdeleted,\n\t\t\t);\n\t\t}\n\n\t\t// Clean up\n\t\tthis.annotations.delete(id);\n\t\tconsole.log(\n\t\t\t`[HighlightCoordinator] Annotation ${id} removed from map. Remaining:`,\n\t\t\tthis.annotations.size,\n\t\t);\n\t}\n\n\t/**\n\t * Remove all annotations\n\t */\n\tclearAnnotations(): void {\n\t\t// Clear all color highlights\n\t\tfor (const colorHighlight of this.colorHighlights.values()) {\n\t\t\tcolorHighlight.clear();\n\t\t}\n\n\t\t// Clear annotation data\n\t\tthis.annotations.clear();\n\t}\n\n\t/**\n\t * Get all annotations\n\t */\n\tgetAnnotations(): Annotation[] {\n\t\treturn Array.from(this.annotations.values());\n\t}\n\n\t/**\n\t * Get annotation by ID\n\t */\n\tgetAnnotation(id: string): Annotation | null {\n\t\treturn this.annotations.get(id) ?? null;\n\t}\n\n\t/**\n\t * Change annotation color\n\t *\n\t * @param id Annotation ID\n\t * @param newColor New color\n\t */\n\tchangeAnnotationColor(id: string, newColor: HighlightColor): void {\n\t\tconst annotation = this.annotations.get(id);\n\t\tif (!annotation) return;\n\n\t\tconst oldColor = annotation.color;\n\t\tif (oldColor === newColor) return;\n\n\t\t// Remove from old color highlight\n\t\tconst oldColorHighlight = this.colorHighlights.get(oldColor);\n\t\tif (oldColorHighlight) {\n\t\t\toldColorHighlight.delete(annotation.range);\n\t\t}\n\n\t\t// Update color\n\t\tannotation.color = newColor;\n\n\t\t// Add to new color highlight\n\t\tconst newColorHighlight = this.colorHighlights.get(newColor);\n\t\tif (newColorHighlight) {\n\t\t\tnewColorHighlight.add(annotation.range);\n\t\t}\n\t}\n\n\t/**\n\t * Export annotations as serializable data for persistence.\n\t * Uses RangeSerializer for robust DOM range serialization.\n\t *\n\t * @param root Root element for serialization (typically document.body or content container)\n\t * @returns Array of serialized annotations\n\t */\n\texportAnnotations(\n\t\troot: Element = document.body,\n\t): Array<\n\t\tSerializedRange & { id: string; color: HighlightColor; timestamp: number }\n\t> {\n\t\treturn this.getAnnotations().map((annotation) => ({\n\t\t\t...this.rangeSerializer.serialize(annotation.range, root),\n\t\t\tid: annotation.id,\n\t\t\tcolor: annotation.color,\n\t\t\ttimestamp: annotation.timestamp,\n\t\t}));\n\t}\n\n\t/**\n\t * Import annotations from serialized data.\n\t * Restores annotations after page navigation or refresh.\n\t *\n\t * @param data Array of serialized annotations\n\t * @param root Root element for deserialization (same as used in export)\n\t * @returns Number of successfully restored annotations\n\t */\n\timportAnnotations(\n\t\tdata: Array<\n\t\t\tSerializedRange & {\n\t\t\t\tid?: string;\n\t\t\t\tcolor: HighlightColor;\n\t\t\t\ttimestamp?: number;\n\t\t\t}\n\t\t>,\n\t\troot: Element = document.body,\n\t): number {\n\t\tlet restored = 0;\n\n\t\tfor (const item of data) {\n\t\t\tconst range = this.rangeSerializer.deserialize(item, root);\n\t\t\tif (range) {\n\t\t\t\tthis.addAnnotation(range, item.color);\n\t\t\t\trestored++;\n\t\t\t}\n\t\t}\n\n\t\treturn restored;\n\t}\n\n\t// ============================================================================\n\t// HighlightCoordinatorApi interface implementation\n\t// ============================================================================\n\n\t/**\n\t * Highlight a text range (interface method)\n\t *\n\t * Generic method that adapts to the specific highlight type.\n\t * For more control, use the specific methods like highlightTTSWord().\n\t */\n\thighlightRange(\n\t\trange: Range,\n\t\ttype: HighlightType,\n\t\tcolor: HighlightColor = HighlightColor.YELLOW,\n\t): void {\n\t\tif (!this.supported) return;\n\n\t\tswitch (type) {\n\t\t\tcase HighlightType.TTS_WORD:\n\t\t\tcase HighlightType.TTS_SENTENCE: {\n\t\t\t\t// For TTS, add to appropriate highlight\n\t\t\t\tconst highlight =\n\t\t\t\t\ttype === HighlightType.TTS_WORD\n\t\t\t\t\t\t? this.ttsWordHighlight\n\t\t\t\t\t\t: this.ttsSentenceHighlight;\n\t\t\t\tif (highlight) {\n\t\t\t\t\thighlight.clear();\n\t\t\t\t\thighlight.add(range);\n\t\t\t\t\tif (type === HighlightType.TTS_WORD) {\n\t\t\t\t\t\tfor (const element of this.ttsWordElementHighlights) {\n\t\t\t\t\t\t\telement.removeAttribute(\"data-pie-tts-word-element\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.ttsWordElementHighlights.clear();\n\t\t\t\t\t\tthis.highlightTTSWordElementFallbacks([range]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase HighlightType.ANNOTATION:\n\t\t\t\t// For annotations, use the existing method\n\t\t\t\tthis.addAnnotation(range, color);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Clear highlights of a specific type (interface method)\n\t */\n\tclearHighlights(type: HighlightType): void {\n\t\tif (!this.supported) return;\n\n\t\tswitch (type) {\n\t\t\tcase HighlightType.TTS_WORD:\n\t\t\t\tthis.clearTTSWord();\n\t\t\t\tbreak;\n\t\t\tcase HighlightType.TTS_SENTENCE:\n\t\t\t\tthis.clearTTSSentence();\n\t\t\t\tbreak;\n\t\t\tcase HighlightType.ANNOTATION:\n\t\t\t\tthis.clearAnnotations();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Clear all highlights (interface method)\n\t */\n\tclearAll(): void {\n\t\tif (!this.supported) return;\n\t\tthis.clearTTS();\n\t\tthis.clearAnnotations();\n\t}\n\n\t/**\n\t * Check if CSS Highlight API is supported (interface method)\n\t */\n\tisSupported(): boolean {\n\t\treturn this.supported;\n\t}\n\n\t/**\n\t * Update TTS highlight style dynamically\n\t *\n\t * @param color CSS color value (e.g., '#ffeb3b')\n\t * @param opacity Opacity value (0.0 to 1.0)\n\t */\n\tupdateTTSHighlightStyle(color: string, opacity: number): void {\n\t\tif (!this.supported) return;\n\t\tif (typeof document === \"undefined\") return;\n\n\t\tconst styleEl = document.getElementById(\"pie-highlight-styles\");\n\t\tif (!styleEl) return;\n\n\t\t// Convert hex to rgba\n\t\tconst hexToRgb = (hex: string) => {\n\t\t\tconst result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\t\t\treturn result\n\t\t\t\t? {\n\t\t\t\t\t\tr: parseInt(result[1], 16),\n\t\t\t\t\t\tg: parseInt(result[2], 16),\n\t\t\t\t\t\tb: parseInt(result[3], 16),\n\t\t\t\t\t}\n\t\t\t\t: null;\n\t\t};\n\n\t\tconst rgb = hexToRgb(color);\n\t\tif (!rgb) return;\n\n\t\tthis.explicitTTSColorOverride = {\n\t\t\tcolor: `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`,\n\t\t\topacity: Math.max(0.2, Math.min(0.95, opacity)),\n\t\t};\n\t\tthis.applyAdaptiveTTSStyle();\n\t}\n\n\t/**\n\t * Cleanup - remove all highlights\n\t */\n\tdestroy(): void {\n\t\tif (!this.supported) return;\n\n\t\tthis.clearTTS();\n\t\tthis.clearAnnotations();\n\n\t\t// Remove style element\n\t\tif (typeof document !== \"undefined\") {\n\t\t\tconst styleEl = document.getElementById(\"pie-highlight-styles\");\n\t\t\tif (styleEl) {\n\t\t\t\tstyleEl.remove();\n\t\t\t}\n\t\t}\n\t\tthis.themeObserver?.disconnect();\n\t\tthis.themeObserver = null;\n\t}\n}\n"]}
@@ -18,6 +18,7 @@
18
18
  import type { ITTSProvider, TTSConfig, TTSProviderCapabilities } from "@pie-players/pie-tts";
19
19
  import type { AccessibilityCatalogResolver, CatalogLookupContext } from "./AccessibilityCatalogResolver.js";
20
20
  import type { HighlightCoordinatorApi } from "./interfaces.js";
21
+ import type { TTSHighlightTargetResolverProvider } from "./tts/highlight-target-resolver.js";
21
22
  export type { ITTSProvider, ITTSProviderImplementation, TTSConfig, TTSFeature, TTSProviderCapabilities, } from "@pie-players/pie-tts";
22
23
  /**
23
24
  * Playback state
@@ -49,6 +50,7 @@ export declare class TTSService {
49
50
  private currentProvider;
50
51
  private provider;
51
52
  private highlightCoordinator;
53
+ private highlightTargetResolverProvider;
52
54
  private catalogResolver;
53
55
  private state;
54
56
  private ttsConfig;
@@ -61,6 +63,7 @@ export declare class TTSService {
61
63
  private currentBoundaryOffset;
62
64
  private activeWordBoundaryOffset;
63
65
  private seekSegments;
66
+ private playbackChunks;
64
67
  private sentenceHighlightSegments;
65
68
  private currentSeekSegmentIndex;
66
69
  private activeSentenceStartOffset;
@@ -92,6 +95,10 @@ export declare class TTSService {
92
95
  * Set highlight coordinator for word highlighting
93
96
  */
94
97
  setHighlightCoordinator(coordinator: HighlightCoordinatorApi): void;
98
+ /**
99
+ * Set a late-bound provider for optional host TTS highlight target remapping.
100
+ */
101
+ setHighlightTargetResolverProvider(provider: TTSHighlightTargetResolverProvider | null): () => void;
95
102
  /**
96
103
  * Set accessibility catalog resolver for spoken content
97
104
  *
@@ -101,6 +108,15 @@ export declare class TTSService {
101
108
  * @param resolver AccessibilityCatalogResolver instance
102
109
  */
103
110
  setCatalogResolver(resolver: AccessibilityCatalogResolver): void;
111
+ private getHighlightResolverRuntime;
112
+ private getNodeElement;
113
+ private isElementWithinScope;
114
+ private isRangeWithinScope;
115
+ private resolveWordHighlightRange;
116
+ private resolveSentenceHighlightTargets;
117
+ private createTextRange;
118
+ private paintTTSWordRange;
119
+ private paintTTSSentenceRanges;
104
120
  /**
105
121
  * Get provider capabilities
106
122
  */
@@ -127,6 +143,7 @@ export declare class TTSService {
127
143
  private createSeekSegmentsFromText;
128
144
  private splitSegmentsAtBoundaries;
129
145
  private createSentenceHighlightSegments;
146
+ private createSeekSegmentsFromSpeechChunks;
130
147
  private getCurrentSeekSegmentIndex;
131
148
  private speakWithPlan;
132
149
  private highlightSentenceSegment;