@pie-players/pie-assessment-toolkit 0.3.72 → 0.3.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -56
- package/dist/attempt/AssessmentSession.d.ts +1 -5
- package/dist/attempt/AssessmentSession.js +0 -29
- package/dist/components/ItemToolBar.custom-element.d.ts +1 -0
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.d.ts +1 -0
- package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
- package/dist/components/SectionToolBar.custom-element.d.ts +1 -0
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +40 -0
- package/dist/components/chunks/ItemToolBar-gmrryv2v.js +2 -0
- package/dist/components/chunks/ItemToolBar-h4xap0t0.js +4 -0
- package/dist/components/chunks/ItemToolBar-wr2myaah.js +2 -0
- package/dist/components/chunks/sre-engine-wf9s43gg.js +1 -0
- package/dist/context/assessment-toolkit-context.d.ts +5 -0
- package/dist/context/runtime-context-consumer.js +5 -38
- package/dist/index.d.ts +6 -6
- package/dist/index.js +8 -9
- package/dist/policy/core/ToolPolicyEngine.d.ts +8 -2
- package/dist/policy/core/ToolPolicyEngine.js +12 -0
- package/dist/runtime/adapter/SectionEngineAdapter.d.ts +3 -3
- package/dist/runtime/adapter/SectionEngineAdapter.js +3 -3
- package/dist/runtime/registration-events.d.ts +3 -0
- package/dist/runtime/section-runtime-engine-host-context.d.ts +3 -9
- package/dist/runtime/section-runtime-engine-host-context.js +5 -43
- package/dist/runtime/tool-host-contract.d.ts +20 -0
- package/dist/runtime/tool-host-contract.js +21 -0
- package/dist/services/HighlightCoordinator.d.ts +1 -7
- package/dist/services/HighlightCoordinator.js +1 -3
- package/dist/services/TTSService.d.ts +15 -1
- package/dist/services/TTSService.js +88 -35
- package/dist/services/ToolCoordinator.d.ts +1 -7
- package/dist/services/ToolCoordinator.js +1 -3
- package/dist/services/ToolRegistry.d.ts +13 -6
- package/dist/services/ToolRegistry.js +19 -7
- package/dist/services/ToolkitCoordinator.d.ts +110 -18
- package/dist/services/ToolkitCoordinator.js +273 -85
- package/dist/services/catalog-owner.d.ts +11 -0
- package/dist/services/catalog-owner.js +25 -0
- package/dist/services/create-tools-config.d.ts +2 -2
- package/dist/services/framework-error.d.ts +8 -1
- package/dist/services/interfaces.d.ts +9 -9
- package/dist/services/pnp-standard-features.d.ts +1 -1
- package/dist/services/section-controller-types.d.ts +30 -0
- package/dist/services/spoken-audio-cards.js +1 -1
- package/dist/services/tool-config-validation.d.ts +13 -2
- package/dist/services/tool-config-validation.js +33 -16
- package/dist/services/tool-context.js +29 -13
- package/dist/services/tool-providers/TTSToolProvider.d.ts +27 -65
- package/dist/services/tool-providers/TTSToolProvider.js +47 -9
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +4 -4
- package/dist/services/tool-providers/ToolProviderRegistry.js +4 -16
- package/dist/services/tool-providers/index.d.ts +0 -9
- package/dist/services/tool-providers/index.js +2 -4
- package/dist/services/tools-config-normalizer.d.ts +20 -1
- package/dist/services/tts/catalog-span-alignment.d.ts +2 -17
- package/dist/services/tts/catalog-span-alignment.js +17 -142
- package/dist/services/tts/generated-speech/types.d.ts +0 -12
- package/dist/services/tts/highlight-pipeline/boundary-normalizer.js +12 -62
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +26 -1
- package/dist/services/tts/highlight-pipeline/normalize-speech-chunks.js +3 -6
- package/dist/services/tts/math-alignment/index.d.ts +0 -5
- package/dist/services/tts/math-alignment/index.js +5 -25
- package/dist/services/tts/math-alignment/speech-tokenizer.d.ts +9 -1
- package/dist/services/tts/math-alignment/speech-tokenizer.js +38 -36
- package/dist/services/tts/math-alignment/types.d.ts +4 -2
- package/dist/services/tts/math-aware-text-processing.js +44 -2
- package/dist/services/tts/math-speech.d.ts +5 -1
- package/dist/services/tts/math-speech.js +9 -6
- package/dist/services/tts/sre-engine.d.ts +7 -0
- package/dist/services/tts/sre-engine.js +11 -0
- package/dist/services/tts/sre-locales.d.ts +14 -0
- package/dist/services/tts/sre-locales.js +57 -0
- package/dist/services/tts/text-processing.d.ts +0 -1
- package/dist/services/tts/text-processing.js +0 -1
- package/dist/services/tts-runtime-config.d.ts +21 -3
- package/dist/services/tts-runtime-config.js +11 -3
- package/dist/tools/client.d.ts +1 -3
- package/dist/tools/client.js +1 -5
- package/dist/tools/internal.d.ts +6 -5
- package/dist/tools/internal.js +6 -8
- package/package.json +17 -36
- package/dist/components/chunks/ItemToolBar-byq80z42.js +0 -40
- package/dist/components/chunks/ItemToolBar-d36g3aw4.js +0 -49
- package/dist/services/ToolConfigResolver.d.ts +0 -161
- package/dist/services/ToolConfigResolver.js +0 -229
- package/dist/services/catalog-media.d.ts +0 -56
- package/dist/services/catalog-media.js +0 -190
- package/dist/services/createDefaultToolRegistry.d.ts +0 -53
- package/dist/services/createDefaultToolRegistry.js +0 -45
- package/dist/services/tool-providers/CortexToolProvider.d.ts +0 -13
- package/dist/services/tool-providers/CortexToolProvider.js +0 -32
- package/dist/services/tool-providers/DesmosToolProvider.d.ts +0 -14
- package/dist/services/tool-providers/DesmosToolProvider.js +0 -32
- package/dist/services/tool-providers/GeoGebraToolProvider.d.ts +0 -16
- package/dist/services/tool-providers/GeoGebraToolProvider.js +0 -32
- package/dist/services/tool-providers/LazyCalculatorToolProvider.d.ts +0 -35
- package/dist/services/tool-providers/LazyCalculatorToolProvider.js +0 -95
- package/dist/services/tts/visual-line-ranges.d.ts +0 -18
- package/dist/services/tts/visual-line-ranges.js +0 -226
- package/dist/tools/index.d.ts +0 -8
- package/dist/tools/index.js +0 -10
- package/dist/tools/response-discovery.d.ts +0 -61
- package/dist/tools/response-discovery.js +0 -113
- package/dist/tools/types.d.ts +0 -337
- package/dist/tools/types.js +0 -12
- package/dist/tools/variant-resolver.d.ts +0 -41
- package/dist/tools/variant-resolver.js +0 -207
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{C as
|
|
2
|
-
- ${
|
|
3
|
-
- `)}`}var
|
|
4
|
-
`);throw Error(`[tool-config-validation:${
|
|
5
|
-
${Y}`)}function Z7(G,Q={}){let Y=i1(Q.strictness),J=Q.source??"tools",X=N5(Q.toolRegistry),j=b7(G),Z=[],q=Object.values(j.placement).some((H)=>H.length>0)||Object.keys(j.providers).length>0||(j.policy.allowed?.length??0)>0||(j.policy.blocked?.length??0)>0;if(X.size===0&&q)Z.push(c({code:"tools.registryUnavailable",severity:"warning",path:"tools",message:'No tool registry was supplied, so tool ids, placement levels and provider config were not validated. Pass `toolRegistry` — for the packaged capability set, `createPackagedToolRegistry()` from "@pie-players/pie-default-tool-loaders".'}));let B=Object.hasOwn(j.providers,"tts"),K={...j.providers||{}};for(let H of Object.keys(K).sort()){if(H==="tts"){delete K.tts;continue}let N=X.get(H);K[H]=F5(H,K[H],N,Z),M5(H,K[H],N,Z)}let W={...j,providers:K};if(z5(W,X,Z),O5(W,X,Z),P5(W,X,B,Z),B)q6(Z.filter((H)=>H.code==="tools.removedProviderKey"),J);if(Y==="warn")j6(Z,J);let $=Z.filter((H)=>H.severity==="error");if(Y==="error"&&$.length>0)q6($,J);if(Y==="error"&&$.length===0)j6(Z,J);return{config:W,diagnostics:Z}}import{languageTagLookupSequence as b5,normalizeLanguageTag as _6}from"@pie-players/pie-players-shared/i18n/language-tags";var s1=(G)=>Array.isArray(G)&&G.length>0;function n1(G){if(G.kind==="passage")return{ownerKind:"passage",assessmentId:G.assessmentId,sectionId:G.sectionId,passageId:G.canonicalItemId||G.itemId};return{ownerKind:"itemModel",assessmentId:G.assessmentId,sectionId:G.sectionId,itemId:G.itemId,canonicalItemId:G.canonicalItemId||G.itemId}}function U6(G,Q){if(!G)return[];let Y=n1(Q),J=[];if(s1(G.accessibilityCatalogs))J.push({context:Y,catalogs:G.accessibilityCatalogs});if(s1(G.config?.extractedCatalogs))J.push({context:Y,catalogs:G.config.extractedCatalogs});if(Q.kind==="passage")return J;if(Y.ownerKind!=="itemModel")return J;for(let X of G.config?.models??[]){if(!s1(X.accessibilityCatalogs))continue;J.push({context:{...Y,modelId:X.id},catalogs:X.accessibilityCatalogs})}return J}var a1=new Set(["speak","break","prosody","emphasis","say-as","sub","mark","phoneme","lang","p","s","voice","audio","lexicon"]),B6=new Set(["script","style","iframe","object","embed","foreignobject","noscript","template"]),W6=new Set(["alphabet","ph","time","strength","rate","pitch","volume","name","interpret-as","format","detail","language","xml:lang","lang","gender","src"]),K6=new Set(["break","mark","lexicon"]);function L5(G){let Q=G;for(let Y of K6){let J=new RegExp(`<${Y}\\b([^>/]*?)\\s*/>`,"gi");Q=Q.replace(J,(X,j)=>{let Z=j?j.replace(/\s+$/,""):"";return`<${Y}${Z}></${Y}>`})}return Q}var w5=[/^localhost$/i,/^127(?:\.\d{1,3}){3}$/,/^0(?:\.\d{1,3}){3}$/,/^10(?:\.\d{1,3}){3}$/,/^192\.168(?:\.\d{1,3}){2}$/,/^172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2}$/,/^169\.254(?:\.\d{1,3}){2}$/,/^::1$/,/^fe80:/i,/^fc00:/i,/^fd[0-9a-f]{2}:/i,/^metadata\.google\.internal$/i,/^metadata\.azure\.internal$/i,/^metadata\.packet\.net$/i];function R5(G){if(typeof G!=="string"||G.length===0)return!1;let Q;try{Q=new URL(G)}catch{return!1}if(Q.protocol!=="http:"&&Q.protocol!=="https:")return!1;let Y=Q.hostname.replace(/^\[|\]$/g,"").replace(/\.$/,"");return!w5.some((J)=>J.test(Y))}function r1(G){let Q=Array.from(G.children);for(let J of Q){let X=J.tagName.toLowerCase();if(B6.has(X)){J.remove();continue}if(r1(J),!a1.has(X)){let j=G.ownerDocument.createTextNode(J.textContent??"");J.replaceWith(j)}}let Y=Array.from(G.attributes).map((J)=>J.name);for(let J of Y)if(!W6.has(J.toLowerCase()))G.removeAttribute(J);if(G.tagName.toLowerCase()==="audio"){let J=G.getAttribute("src");if(J!==null&&!R5(J))G.removeAttribute("src")}}function o1(G){let Q=G.tagName.toLowerCase(),Y=Array.from(G.attributes).filter((X)=>W6.has(X.name.toLowerCase())).map((X)=>` ${X.name}="${E5(X.value)}"`).join("");if(K6.has(Q))return`<${Q}${Y}/>`;let J=[];for(let X of Array.from(G.childNodes))if(X.nodeType===3)J.push(q1(X.nodeValue??""));else if(X.nodeType===1){let j=X,Z=j.tagName.toLowerCase();if(B6.has(Z))continue;if(a1.has(Z))J.push(o1(j));else J.push(q1(j.textContent??""))}return`<${Q}${Y}>${J.join("")}</${Q}>`}function t1(G){let Q=String(G||"").trim();if(!Q||!Q.includes("<"))return G;if(typeof DOMParser>"u")return G;let J=new DOMParser().parseFromString(L5(Q),"text/html"),X=J.querySelector("speak");if(X)return r1(X),o1(X);let j=J.createElement("speak");for(let Z of Array.from(J.body.childNodes))j.appendChild(Z);return r1(j),Array.from(j.childNodes).map((Z)=>{if(Z.nodeType===3)return q1(Z.nodeValue??"");if(Z.nodeType===1){let q=Z;if(a1.has(q.tagName.toLowerCase()))return o1(q);return q1(q.textContent??"")}return""}).join("")}function q1(G){return G.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function E5(G){return G.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var A6=new Set(["spoken","sign-language","transcript","braille","tactile","simplified-language","audio-description","extended-description"]),e1="ext:";function V6(G){if(A6.has(G))return!0;return G.startsWith(e1)&&G.length>e1.length}var $6=new Set;function G8(G,Q=new Set){if(G===null||typeof G==="string"||typeof G==="number"||typeof G==="boolean"||typeof G>"u")return G;if(typeof G!=="object")throw TypeError("catalog cards must contain JSON-compatible values");if(Q.has(G))throw TypeError("catalog cards must not contain cycles");Q.add(G);try{if(Array.isArray(G))return Object.freeze(G.map((X)=>G8(X,Q)));let Y=Object.getPrototypeOf(G);if(Y!==Object.prototype&&Y!==null)throw TypeError("catalog cards must contain only plain objects and arrays");let J={};for(let[X,j]of Object.entries(G))J[X]=G8(j,Q);return Object.freeze(J)}finally{Q.delete(G)}}function H6(G,Q,Y){let J=`${Q}|${G}`;if($6.has(J))return;$6.add(J);let X=`${Array.from(A6).join(", ")}, or an "${e1}" prefixed vendor extension`;if(Q==="card"){console.warn(`[AccessibilityCatalogResolver] catalog "${Y}" has a card of unknown type "${G}"; it is stored but no reader asks for that type, so the alternate will never be shown. Expected one of: ${X}.`);return}console.warn(`[AccessibilityCatalogResolver] lookup for unknown catalog type "${G}" on "${Y}" cannot match any card. Expected one of: ${X}.`)}var D6=(G)=>G.payload!==void 0?"payload":"content";class Q8{assessmentCatalogs=new Map;itemCatalogs=new Map;scopedCatalogs=new Map;defaultLanguage="en-US";sanitizedSpokenCache=new Map;catalogChangeListeners=new Set;reportedSnapshotProblems=new Set;constructor(G,Q="en-US"){this.defaultLanguage=Q,this.indexCatalogs(G??[],"assessment")}setDefaultLanguage(G){this.defaultLanguage=G}onCatalogsChange(G){return this.catalogChangeListeners.add(G),()=>{this.catalogChangeListeners.delete(G)}}emitCatalogsChange(G){for(let Q of Array.from(this.catalogChangeListeners))try{Q(G)}catch{}}getDefaultLanguage(){return this.defaultLanguage}indexCatalogs(G,Q){let Y=Q==="assessment"?this.assessmentCatalogs:this.itemCatalogs;for(let J of this.sanitizeCatalogs(G)){if(Y.has(J.identifier)){console.warn(`[AccessibilityCatalogResolver] Duplicate ${Q} catalog "${J.identifier}" ignored`);continue}Y.set(J.identifier,J)}}insertScopedCatalogs(G,Q){if(!Q||Q.length===0)return null;let Y=this.getOwnerKey(G),J=this.scopedCatalogs.get(Y),X=J?.catalogs??new Map,j=[];for(let Z of this.sanitizeCatalogs(Q)){if(X.has(Z.identifier)){console.warn(`[AccessibilityCatalogResolver] Duplicate scoped catalog "${Z.identifier}" ignored for ${Y}`);continue}X.set(Z.identifier,Z),j.push(Z.identifier)}if(!J&&j.length>0)this.scopedCatalogs.set(Y,{context:{...G},catalogs:X});return{key:Y,context:{...G},catalogs:X,insertedIds:j}}removeScopedInsertion(G){let Q=this.scopedCatalogs.get(G.key);if(Q?.catalogs!==G.catalogs)return!1;let Y=!1;for(let J of G.insertedIds)Y=Q.catalogs.delete(J)||Y;if(Q.catalogs.size===0)this.scopedCatalogs.delete(G.key);return Y}registerCatalogs(G,Q){let Y=this.insertScopedCatalogs(G,Q);if(Y&&Y.insertedIds.length>0)this.emitCatalogsChange({reason:"scoped-registered",context:G});let J=!0;return()=>{if(!J)return;if(J=!1,Y&&this.removeScopedInsertion(Y))this.emitCatalogsChange({reason:"scoped-removed",context:G})}}registerOwner(G){let{owner:Q,entity:Y}=G,J=n1(Q),X=[],j=[];try{j=U6(Y,Q)}catch(B){console.warn("[AccessibilityCatalogResolver] A mounted content owner could not be traversed for catalogs; the primary content remains available.",B)}for(let B of j)try{let K=this.insertScopedCatalogs(B.context,B.catalogs);if(K)X.push(K)}catch(K){console.warn("[AccessibilityCatalogResolver] Invalid catalogs on a mounted content owner were ignored; the primary content and other valid catalogs remain available.",K)}if(X.some((B)=>B.insertedIds.length>0))this.emitCatalogsChange({reason:"scoped-registered",context:J});let q=!0;return()=>{if(!q)return;q=!1;let B=!1;for(let K of X)B=this.removeScopedInsertion(K)||B;if(B)this.emitCatalogsChange({reason:"scoped-removed",context:J})}}forOwner(G){let Q={...G};return Object.freeze({snapshot:()=>this.createOwnerSnapshot(Q),onChange:(Y)=>this.onCatalogsChange((J)=>{if(this.catalogChangeAffectsOwner(J,Q))Y()})})}addItemCatalogs(G){if(!G||G.length===0)return;this.indexCatalogs(G,"item"),this.emitCatalogsChange({reason:"item-added"})}clearItemCatalogs(){if(this.itemCatalogs.size===0)return;this.itemCatalogs.clear(),this.emitCatalogsChange({reason:"item-cleared"})}hasCatalog(G){return this.itemCatalogs.has(G)||this.assessmentCatalogs.has(G)||Array.from(this.scopedCatalogs.values()).some((Q)=>Q.catalogs.has(G))}getAlternative(G,Q){if(!V6(Q.type))H6(Q.type,"lookup",G);let Y=Q.context?this.scopedCatalogs.get(this.getOwnerKey(Q.context))?.catalogs.get(G):null;if(Y){let j=this.findMatchingCard(Y,Q);if(j)return this.resolveCard(G,j,"item")}if(Q.context){let j=this.findScopedCandidates(G,Q.context);if(j.length===1){let Z=this.findMatchingCard(j[0],Q);if(Z)return this.resolveCard(G,Z,"item")}else if(j.length>1)return console.warn(`[AccessibilityCatalogResolver] Ambiguous scoped catalog "${G}" for owner context`,Q.context),null}let J=this.itemCatalogs.get(G);if(J){let j=this.findMatchingCard(J,Q);if(j)return this.resolveCard(G,j,"item")}let X=this.assessmentCatalogs.get(G);if(X){let j=this.findMatchingCard(X,Q);if(j)return this.resolveCard(G,j,"assessment")}return null}resolveCard(G,Q,Y){return{catalogId:G,type:Q.catalog,language:Q.language,content:Q.catalog==="spoken"&&Q.content!==void 0?this.ensureSpokenSanitized(Q.content):Q.content,payload:Q.payload,source:Y}}ensureSpokenSanitized(G){let Q=this.sanitizedSpokenCache.get(G);if(Q!==void 0)return Q;let Y=t1(G);return this.sanitizedSpokenCache.set(G,Y),Y}getOwnerKey(G){return[G.ownerKind,G.assessmentId||"",G.sectionId||"",G.canonicalItemId||"",G.itemId||"",G.passageId||"",G.modelId||""].join("|")}scopedCatalogEntries(){let G=[];for(let Q of this.scopedCatalogs.values())for(let Y of Q.catalogs.entries())G.push(Y);return G}findScopedCandidates(G,Q){return Array.from(this.scopedCatalogs.values()).filter((Y)=>this.isCompatibleOwnerContext(Y.context,Q)).map((Y)=>Y.catalogs.get(G)).filter((Y)=>Boolean(Y))}isCompatibleOwnerContext(G,Q){if(G.ownerKind!==Q.ownerKind)return!1;if(Q.assessmentId&&G.assessmentId!==Q.assessmentId)return!1;if(Q.sectionId&&G.sectionId!==Q.sectionId)return!1;if(Q.canonicalItemId&&G.canonicalItemId!==Q.canonicalItemId)return!1;if(Q.itemId&&G.itemId!==Q.itemId)return!1;if(Q.passageId&&G.passageId!==Q.passageId)return!1;if(Q.modelId&&G.modelId!==Q.modelId)return!1;return!0}ownerScopedCatalogEntries(G){let Q=[],Y=this.scopedCatalogs.get(this.getOwnerKey(G));if(Y)Q.push(...Y.catalogs.entries());for(let J of this.scopedCatalogs.values()){if(J===Y)continue;if(!this.isCompatibleOwnerContext(J.context,G))continue;Q.push(...J.catalogs.entries())}return Q}createOwnerSnapshot(G){let Q=[],Y=this.ownerScopedCatalogEntries(G);if(G.ownerKind==="global")Y.push(...this.assessmentCatalogs.entries());for(let[J,X]of Y)for(let j of X.cards)try{Q.push(Object.freeze({catalogId:J,card:G8(j)}))}catch(Z){let q=`${this.getOwnerKey(G)}\x00${J}`;if(!this.reportedSnapshotProblems.has(q))this.reportedSnapshotProblems.add(q),console.warn(`[AccessibilityCatalogResolver] Catalog "${J}" contains a card that cannot be exposed in an owner snapshot; that card was ignored.`,Z)}return Object.freeze({cards:Object.freeze(Q)})}catalogChangeAffectsOwner(G,Q){if(!G.context)return!1;if(this.isCompatibleOwnerContext(G.context,Q))return!0;if(Q.ownerKind==="itemModel"&&Q.modelId&&G.context.ownerKind==="itemModel"&&!G.context.modelId)return this.isCompatibleOwnerContext({...G.context,modelId:Q.modelId},Q);return!1}sanitizeCatalogs(G){return G.map((Q)=>({...Q,cards:Q.cards.map((Y)=>{if(!V6(Y.catalog))H6(Y.catalog,"card",Q.identifier);return{...Y,content:Y.catalog==="spoken"&&Y.content!==void 0?t1(Y.content):Y.content}})}))}findMatchingCard(G,Q){let{type:Y,language:J,useFallback:X=!0,form:j}=Q,Z=[],q=(B)=>{for(let K of b5(B))Z.push((W)=>_6(W.language)===K)};if(J)q(J);if(X)q(this.defaultLanguage),Z.push(()=>!0);for(let B of Z){let K=G.cards.filter((W)=>W.catalog===Y&&B(W));if(K.length===0)continue;if(j){let W=K.find(($)=>D6($)===j);if(W)return W}return K[0]}return null}getAllAlternatives(G){let Q=[],Y=new Set,J=(Z,q)=>{let B=`${Z.catalog}|${_6(Z.language)}|${D6(Z)}`;if(Y.has(B))return;Y.add(B),Q.push(this.resolveCard(G,Z,q))},X=this.itemCatalogs.get(G);if(X)for(let Z of X.cards)J(Z,"item");let j=this.assessmentCatalogs.get(G);if(j)for(let Z of j.cards)J(Z,"assessment");for(let[Z,q]of this.scopedCatalogEntries()){if(Z!==G)continue;for(let B of q.cards)J(B,"item")}return Q}getAllCatalogIds(){let G=this.scopedCatalogEntries().map(([Q])=>Q);return Array.from(new Set([...this.itemCatalogs.keys(),...this.assessmentCatalogs.keys(),...G]))}getStatistics(){let G=new Set,Q=new Set;for(let Y of this.assessmentCatalogs.values())for(let J of Y.cards)if(G.add(J.catalog),J.language)Q.add(J.language);for(let Y of this.itemCatalogs.values())for(let J of Y.cards)if(G.add(J.catalog),J.language)Q.add(J.language);for(let Y of this.scopedCatalogs.values())for(let J of Y.catalogs.values())for(let X of J.cards)if(G.add(X.catalog),X.language)Q.add(X.language);return{totalCatalogs:this.assessmentCatalogs.size+this.itemCatalogs.size+Array.from(this.scopedCatalogs.values()).reduce((Y,J)=>Y+J.catalogs.size,0),assessmentCatalogs:this.assessmentCatalogs.size,itemCatalogs:this.itemCatalogs.size+Array.from(this.scopedCatalogs.values()).reduce((Y,J)=>Y+J.catalogs.size,0),availableTypes:G,availableLanguages:Q}}hasAlternativeType(G,Q){return this.getAllAlternatives(G).some((J)=>J.type===Q)}getCatalogsByType(G){let Q=new Set;for(let[Y,J]of this.assessmentCatalogs.entries())if(J.cards.some((X)=>X.catalog===G))Q.add(Y);for(let[Y,J]of this.itemCatalogs.entries())if(J.cards.some((X)=>X.catalog===G))Q.add(Y);for(let[Y,J]of this.scopedCatalogEntries())if(J.cards.some((X)=>X.catalog===G))Q.add(Y);return Array.from(Q)}reset(){this.assessmentCatalogs.clear(),this.itemCatalogs.clear(),this.scopedCatalogs.clear(),this.sanitizedSpokenCache.clear(),this.reportedSnapshotProblems.clear()}destroy(){this.reset()}}class Y8{elementStates=new Map;listeners=new Set;onStateChange=null;getGlobalElementId(G,Q,Y,J){return`${G}:${Q}:${Y}:${J}`}parseGlobalElementId(G){let Q=G.split(":");if(Q.length!==4)return null;return{assessmentId:Q[0],sectionId:Q[1],itemId:Q[2],elementId:Q[3]}}setState(G,Q,Y){let J=this.elementStates.get(G);if(!J)J=new Map,this.elementStates.set(G,J);J.set(Q,Y),this._notifyListeners(),this._notifyStateChange()}getState(G,Q){return this.elementStates.get(G)?.get(Q)}getElementState(G){let Q=this.elementStates.get(G);if(!Q)return{};return Object.fromEntries(Q.entries())}getAllState(){let G={};for(let[Q,Y]of this.elementStates.entries())G[Q]=Object.fromEntries(Y.entries());return G}subscribe(G){return this.listeners.add(G),()=>this.listeners.delete(G)}_notifyListeners(){for(let G of this.listeners)G(this.elementStates)}setOnStateChange(G){this.onStateChange=G}_notifyStateChange(){if(this.onStateChange)this.onStateChange(this.getAllState())}loadState(G){this.elementStates.clear();for(let[Q,Y]of Object.entries(G)){let J=new Map(Object.entries(Y));this.elementStates.set(Q,J)}this._notifyListeners()}clearElement(G){this.elementStates.delete(G),this._notifyListeners(),this._notifyStateChange()}clearTool(G){for(let Q of this.elementStates.values())Q.delete(G);this._notifyListeners(),this._notifyStateChange()}clearSection(G,Q){let Y=`${G}:${Q}:`,J=[];for(let X of this.elementStates.keys())if(X.startsWith(Y))J.push(X);for(let X of J)this.elementStates.delete(X);this._notifyListeners(),this._notifyStateChange()}clearAll(){this.elementStates.clear(),this._notifyListeners(),this._notifyStateChange()}}class p7{listeners=new Set;subscribeFrameworkErrors(G){this.listeners.add(G);let Q=!0;return()=>{if(!Q)return;Q=!1,this.listeners.delete(G)}}reportFrameworkError(G){let Q=Array.from(this.listeners);for(let Y of Q)try{Y(G)}catch(J){console.warn("[FrameworkErrorBus] listener failed:",J)}}dispose(){this.listeners.clear()}getListenerCount(){return this.listeners.size}}class J8{serialize(G,Q){return{startContainer:this.getNodePath(G.startContainer,Q),startOffset:G.startOffset,endContainer:this.getNodePath(G.endContainer,Q),endOffset:G.endOffset,text:G.toString()}}deserialize(G,Q){let Y=this.findNodeByPath(G.startContainer,Q),J=this.findNodeByPath(G.endContainer,Q);if(!Y||!J)return null;try{let X=new Range;if(X.setStart(Y,G.startOffset),X.setEnd(J,G.endOffset),X.toString()===G.text)return X;return null}catch(X){return console.warn("Failed to deserialize range:",X),null}}getNodePath(G,Q){if(G===Q)return"";if(G.nodeType===Node.TEXT_NODE){let Y=G.parentElement;if(!Y)throw Error("Text node has no parent");let X=Array.from(Y.childNodes).filter((Z)=>Z.nodeType===Node.TEXT_NODE).indexOf(G);return`${this.getElementPath(Y,Q)}::text[${X}]`}if(G.nodeType===Node.ELEMENT_NODE)return this.getElementPath(G,Q);throw Error(`Unsupported node type: ${G.nodeType}`)}getElementPath(G,Q){if(G===Q)return"";let Y=[],J=G;while(J&&J!==Q){if(J.id){Y.unshift(`#${J.id}`);break}let X=J.parentElement;if(!X)break;let j=Array.from(X.children).filter((B)=>B.tagName===J.tagName),Z=j.indexOf(J),q=j.length>1?`${J.tagName.toLowerCase()}:nth-of-type(${Z+1})`:J.tagName.toLowerCase();Y.unshift(q),J=X}return Y.join(" > ")}findNodeByPath(G,Q){if(G==="")return Q;if(G.includes("::text[")){let[Y,J]=G.split("::text["),X=Number.parseInt(J.replace("]",""),10),j=Y?Q.querySelector(Y):Q;if(!j)return null;return Array.from(j.childNodes).filter((q)=>q.nodeType===Node.TEXT_NODE)[X]||null}try{return Q.querySelector(G)}catch(Y){return console.warn("Invalid selector path:",G,Y),null}}serializeMany(G,Q){return G.map((Y)=>this.serialize(Y,Q))}deserializeMany(G,Q){return G.map((Y)=>this.deserialize(Y,Q))}}var u;(function(G){G.TTS_WORD="tts-word",G.TTS_SENTENCE="tts-sentence",G.ANNOTATION="annotation"})(u||(u={}));var $7;(function(G){G.YELLOW="yellow",G.GREEN="green",G.BLUE="blue",G.PINK="pink",G.ORANGE="orange",G.UNDERLINE="underline"})($7||($7={}));class g7{config;ttsWordHighlight=null;ttsSentenceHighlight=null;ttsWordElementHighlights=new Set;ttsSentenceElementHighlights=new Set;annotations=new Map;colorHighlights=new Map;nextAnnotationId=1;supported=!1;rangeSerializer;themeObserver=null;explicitTTSColorOverride=null;constructor(G={}){if(this.config=G,this.rangeSerializer=new J8,typeof CSS>"u"||!("highlights"in CSS)){console.warn("CSS Custom Highlight API not supported (SSR or unsupported browser)");return}this.supported=!0,this.initializeHighlights(),this.registerStyles(),this.applyAdaptiveTTSStyle(),this.setupThemeObservation()}setupThemeObservation(){if(typeof document>"u")return;if(typeof MutationObserver>"u")return;let G=()=>this.applyAdaptiveTTSStyle();this.themeObserver=new MutationObserver(G),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["style","data-theme","data-color-scheme","class"]});for(let Q of document.querySelectorAll("pie-theme"))this.themeObserver.observe(Q,{attributes:!0,attributeFilter:["theme","scheme","provider","variables","style","data-theme","data-color-scheme"]})}parseColor(G){if(!G)return null;let Q=G.trim();if(!Q)return null;let Y=/^#([a-f\d]{3}|[a-f\d]{6})$/i.exec(Q);if(Y){let X=Y[1];if(X.length===3)return[parseInt(X[0]+X[0],16),parseInt(X[1]+X[1],16),parseInt(X[2]+X[2],16)];return[parseInt(X.slice(0,2),16),parseInt(X.slice(2,4),16),parseInt(X.slice(4,6),16)]}let J=/^rgba?\((.+)\)$/i.exec(Q);if(J){let j=J[1].replace(/\//g,",").split(/[,\s]+/).map((K)=>K.trim()).filter(Boolean),Z=Number(j[0]),q=Number(j[1]),B=Number(j[2]);if(Number.isFinite(Z)&&Number.isFinite(q)&&Number.isFinite(B))return[Z,q,B]}if(typeof document<"u"){let X=document.createElement("span");if(X.style.color=Q,typeof X.style.color==="string"&&X.style.color){document.body?.appendChild(X);let j=typeof getComputedStyle==="function"?getComputedStyle(X).color:"";X.remove();let Z=j.trim();if(Z&&Z!==Q)return this.parseColor(j)}}return null}relativeLuminance([G,Q,Y]){let J=(q)=>{let B=q/255;return B<=0.03928?B/12.92:((B+0.055)/1.055)**2.4},X=J(G),j=J(Q),Z=J(Y);return 0.2126*X+0.7152*j+0.0722*Z}contrastRatio(G,Q){let Y=this.relativeLuminance(G),J=this.relativeLuminance(Q),X=Math.max(Y,J),j=Math.min(Y,J);return(X+0.05)/(j+0.05)}blend(G,Q,Y){return[Math.round(G[0]*Y+Q[0]*(1-Y)),Math.round(G[1]*Y+Q[1]*(1-Y)),Math.round(G[2]*Y+Q[2]*(1-Y))]}resolveAdaptiveTTSStyle(G){let Q=[255,235,59],Y=[17,24,39],J=[255,255,255],X=G||(typeof document<"u"?document.documentElement:null),j=X&&typeof getComputedStyle==="function"?getComputedStyle(X):null,Z=this.parseColor(j?.getPropertyValue("--pie-background")||j?.backgroundColor)||J,q=this.parseColor(j?.getPropertyValue("--pie-text"))||Y,B=this.explicitTTSColorOverride?this.parseColor(this.explicitTTSColorOverride.color)||Q:this.parseColor(j?.getPropertyValue("--pie-missing"))||Q,K=this.explicitTTSColorOverride?[Math.max(0.3,Math.min(0.95,this.explicitTTSColorOverride.opacity))]:[0.8,0.72,0.68,0.62,0.56,0.5],W=K[K.length-1],$=-1/0;for(let g of K){let q7=this.blend(B,Z,g),U7=this.contrastRatio(q7,Z),B7=this.contrastRatio(q7,q),w7=U7*1.2+B7*0.8;if(U7>=1.25&&B7>=2.4){W=g;break}if(w7>$)$=w7,W=g}let H=Math.max(0.24,Math.min(0.85,W*0.55)),N=Math.max(0.55,Math.min(0.95,W+0.2)),F=Math.max(0.22,Math.min(0.6,W*0.45)),O=q,L=this.blend(O,Z,N),D=this.contrastRatio(L,Z),P=this.relativeLuminance(Z)>0.45?[0,0,0]:[255,255,255],S=D>=1.35?O:P,v=`rgba(${B[0]}, ${B[1]}, ${B[2]}, ${W})`,I=`rgba(${B[0]}, ${B[1]}, ${B[2]}, ${H})`,p=`rgba(${S[0]}, ${S[1]}, ${S[2]}, ${N})`,E=`rgba(${S[0]}, ${S[1]}, ${S[2]}, ${F})`;return{wordHighlight:v,sentenceHighlight:I,wordUnderline:p,wordShadow:E}}applyAdaptiveTTSStyle(G){if(typeof document>"u")return;let Q=this.resolveAdaptiveTTSStyle(G);document.documentElement.style.setProperty("--pie-tts-word-highlight",Q.wordHighlight),document.documentElement.style.setProperty("--pie-tts-sentence-highlight",Q.sentenceHighlight),document.documentElement.style.setProperty("--pie-tts-line-highlight",Q.sentenceHighlight),document.documentElement.style.setProperty("--pie-tts-word-underline",Q.wordUnderline),document.documentElement.style.setProperty("--pie-tts-word-shadow",Q.wordShadow)}initializeHighlights(){if(!this.supported)return;this.ttsWordHighlight=new Highlight,this.ttsSentenceHighlight=new Highlight,CSS.highlights.set("tts-word",this.ttsWordHighlight),CSS.highlights.set("tts-sentence",this.ttsSentenceHighlight);for(let G of Object.values($7)){let Q=new Highlight;this.colorHighlights.set(G,Q),CSS.highlights.set(`annotation-${G}`,Q)}}registerStyles(){if(!this.supported)return;if(typeof document>"u")return;if(document.getElementById("pie-highlight-styles"))return;let G=document.createElement("style");G.id="pie-highlight-styles",G.textContent=`
|
|
1
|
+
import{B as D6,C as N6,H as M6,I as f,J as z6,K as O6,L as u9,N as P6,P as L7,Q as L6,R as b7,S as b9,T as S9,b as U6,c as V6,d as A6,e as c,f as y,g as m,h as E,i as h9,j as _6,k as m9,l as L1,m as w1,n as b,o as $6,p as A,q as h,t as p9,u as F6,v as R1,w as E1,x as H6}from"./chunks/ItemToolBar-h4xap0t0.js";import{U as X8,V as Z8}from"./chunks/ItemToolBar-wr2myaah.js";import{X as f5}from"./chunks/ItemToolBar-gmrryv2v.js";import{coerceBooleanAttributes as l2}from"@pie-players/pie-players-shared/ui/attribute-coercion";import{ContextProvider as W6,ContextRoot as K6,requestContext as i2}from"@pie-players/pie-context";import{attachInstrumentationEventBridge as s2,createStageTracker as n2,resolveInstrumentationProvider as r2,TOOLKIT_INSTRUMENTATION_EVENT_MAP as o2}from"@pie-players/pie-players-shared/pie";import{isInstrumentationProvider as a2}from"@pie-players/pie-players-shared";import{createPieI18n as t2,DEFAULT_LOCALE as e2}from"@pie-players/pie-players-shared/i18n";function B1(Q){return{kind:Q.kind,severity:Q.severity??"error",source:Q.source,message:Q.message,details:[...Q.details||[]],recoverable:Q.recoverable===!0,cause:Q.cause}}function g1(Q){let Y=Q.error instanceof Error&&Q.error.message.trim().length>0?Q.error.message:String(Q.error||"Unknown framework error");return B1({kind:Q.kind,source:Q.source,message:Y,recoverable:Q.recoverable,cause:Q.error})}var $3={"coordinator-ready":"coordinator-init","state-load":"tool-state-load","state-save":"tool-state-save","provider-register":"provider-register","provider-init":"provider-init","tts-init":"tts-init","section-controller-init":"section-controller-init","section-controller-dispose":"section-controller-dispose"};function W0(Q){let Y=$3[Q.context.phase],J=Q.context.providerId?`pie-toolkit-coordinator/${Q.context.providerId}`:`pie-toolkit-coordinator:${Q.context.phase}`;return g1({kind:Y,source:J,error:Q.error,recoverable:Q.recoverable})}function K0(Q){let Y=`[pie-framework:${Q.kind}:${Q.source}]`;if(Q.details.length===0)return`${Y} ${Q.message}`;return`${Y} ${Q.message}
|
|
2
|
+
- ${Q.details.join(`
|
|
3
|
+
- `)}`}var F3="error";function c1(Q){if(Q==="off"||Q==="warn"||Q==="error")return Q;return F3}function l(Q){return Q}function H3(Q){if(!Q)return new Map;return new Map(Q.getAllTools().slice().sort((Y,J)=>Y.toolId.localeCompare(J.toolId)).map((Y)=>[Y.toolId,Y]))}function D3(Q,Y,J,G){if(!Y||!J?.provider?.sanitizeConfig)return Y;try{let X=J.provider.sanitizeConfig(Y);if(!X||typeof X!=="object"||Array.isArray(X))return G.push(l({code:"tools.providerSanitizeFailed",severity:"error",path:`providers.${Q}`,message:`Provider sanitizer for "${Q}" must return an object.`,providerId:Q,toolId:Q})),Y;return X}catch(X){return G.push(l({code:"tools.providerSanitizeFailed",severity:"error",path:`providers.${Q}`,message:`Provider sanitizer failed for "${Q}": ${X instanceof Error?X.message:String(X)}`,providerId:Q,toolId:Q})),Y}}function N3(Q,Y,J,G){if(!Y||!J?.provider?.validateConfig)return;try{let X=J.provider.validateConfig(Y);if(!Array.isArray(X)){G.push(l({code:"tools.invalidProviderValidation",severity:"error",path:`providers.${Q}`,message:`Provider validator for "${Q}" must return an array.`,providerId:Q,toolId:Q}));return}for(let j of X)G.push({...j,path:j.path||`providers.${Q}`,providerId:j.providerId||Q,toolId:j.toolId||Q})}catch(X){G.push(l({code:"tools.providerValidateFailed",severity:"error",path:`providers.${Q}`,message:`Provider validator failed for "${Q}": ${X instanceof Error?X.message:String(X)}`,providerId:Q,toolId:Q}))}}function M3(Q,Y,J){if(Y.size===0)return;let G=["section","item","passage"];for(let X of G)for(let j of Q.placement[X]){let Z=Y.get(j);if(!Z){J.push(l({code:"tools.unknownToolId",severity:"error",path:`placement.${X}`,message:`Unknown tool id "${j}" in placement.${X}.`,toolId:j}));continue}if(Z.activation==="region"){J.push(l({code:"tools.unplaceableActivation",severity:"error",path:`placement.${X}`,message:`Tool "${j}" renders into a host surface (activation "region") and cannot be placed on the ${X} toolbar. Remove it from placement.${X}; its availability comes from policy plus its content dependency.`,toolId:j}));continue}let B=Z.supportedLevels.includes(X),W=X==="item"&&Z.supportedLevels.includes("section");if(!B&&!W)J.push(l({code:"tools.unsupportedLevel",severity:"error",path:`placement.${X}`,message:`Tool "${j}" does not support level "${X}".`,toolId:j}))}}function z3(Q,Y,J){if(Y.size===0)return;for(let G of Q.policy.allowed||[]){if(Y.has(G))continue;J.push(l({code:"tools.unknownToolId",severity:"error",path:"policy.allowed",message:`Unknown tool id "${G}" in policy.allowed.`,toolId:G}))}for(let G of Q.policy.blocked||[]){if(Y.has(G))continue;J.push(l({code:"tools.unknownToolId",severity:"error",path:"policy.blocked",message:`Unknown tool id "${G}" in policy.blocked.`,toolId:G}))}}function O3(Q,Y,J,G){if(J)G.push(l({code:"tools.removedProviderKey",severity:"error",path:"providers.tts",message:'Provider key "tts" is no longer supported. Use "providers.textToSpeech".',providerId:"tts",toolId:"textToSpeech"}));for(let X of Object.keys(Q.providers).sort()){if(Y.size===0||Y.has(X))continue;G.push(l({code:"tools.unknownProviderKey",severity:"error",path:`providers.${X}`,message:`Unknown provider key "${X}".`,providerId:X,toolId:X}))}}function U0(Q,Y){if(Q.length===0)return;for(let J of Q){let G=`[tool-config-validation:${Y}]`;console.warn(`${G} ${J.path} - ${J.message}`)}}function V0(Q,Y){let J=Q.map((G)=>`- ${G.path}: ${G.message}`).join(`
|
|
4
|
+
`);throw Error(`[tool-config-validation:${Y}] Invalid tools config:
|
|
5
|
+
${J}`)}function A0(Q,Y={}){let J=d1(Q,Y.toolRegistry);return l1(J.diagnostics,Y),J}function d1(Q,Y){let J=H3(Y),G=b7(Q),X=[],j=Object.values(G.placement).some((K)=>K.length>0)||Object.keys(G.providers).length>0||(G.policy.allowed?.length??0)>0||(G.policy.blocked?.length??0)>0;if(J.size===0&&j)X.push(l({code:"tools.registryUnavailable",severity:"warning",path:"tools",message:'No tool registry was supplied, so tool ids, placement levels and provider config were not validated, and a coordinator without one registers no tool providers. Pass `toolRegistry` to the coordinator or the toolkit it is bound to — for the packaged capability set, `createPackagedToolRegistry()` from "@pie-players/pie-default-tool-loaders".'}));let Z=Object.hasOwn(G.providers,"tts"),B={...G.providers||{}};for(let K of Object.keys(B).sort()){if(K==="tts"){delete B.tts;continue}let U=J.get(K);B[K]=D3(K,B[K],U,X),N3(K,B[K],U,X)}let W={...G,providers:B};return M3(W,J,X),z3(W,J,X),O3(W,J,Z,X),{config:W,diagnostics:X}}function l1(Q,Y={}){let J=c1(Y.strictness),G=Y.source??"tools",X=Q.filter((Z)=>Z.code==="tools.removedProviderKey");if(X.length>0)V0(X,G);if(J==="warn")U0(Q,G);let j=Q.filter((Z)=>Z.severity==="error");if(J==="error"&&j.length>0)V0(j,G);if(J==="error"&&j.length===0)U0(Q,G)}import{languageTagLookupSequence as E3,normalizeLanguageTag as D0}from"@pie-players/pie-players-shared/i18n/language-tags";var i1=(Q)=>Array.isArray(Q)&&Q.length>0;function s1(Q){if(Q.kind==="passage")return{ownerKind:"passage",assessmentId:Q.assessmentId,sectionId:Q.sectionId,passageId:Q.canonicalItemId||Q.itemId};return{ownerKind:"itemModel",assessmentId:Q.assessmentId,sectionId:Q.sectionId,itemId:Q.itemId,canonicalItemId:Q.canonicalItemId||Q.itemId}}function _0(Q,Y){if(!Q)return[];let J=s1(Y),G=[];if(i1(Q.accessibilityCatalogs))G.push({context:J,catalogs:Q.accessibilityCatalogs});if(i1(Q.config?.extractedCatalogs))G.push({context:J,catalogs:Q.config.extractedCatalogs});if(Y.kind==="passage")return G;if(J.ownerKind!=="itemModel")return G;for(let X of Q.config?.models??[]){if(!i1(X.accessibilityCatalogs))continue;G.push({context:{...J,modelId:X.id},catalogs:X.accessibilityCatalogs})}return G}var o1=new Set(["speak","break","prosody","emphasis","say-as","sub","mark","phoneme","lang","p","s","voice","audio","lexicon"]),$0=new Set(["script","style","iframe","object","embed","foreignobject","noscript","template"]),F0=new Set(["alphabet","ph","time","strength","rate","pitch","volume","name","interpret-as","format","detail","language","xml:lang","lang","gender","src"]),H0=new Set(["break","mark","lexicon"]);function P3(Q){let Y=Q;for(let J of H0){let G=new RegExp(`<${J}\\b([^>/]*?)\\s*/>`,"gi");Y=Y.replace(G,(X,j)=>{let Z=j?j.replace(/\s+$/,""):"";return`<${J}${Z}></${J}>`})}return Y}var L3=[/^localhost$/i,/^127(?:\.\d{1,3}){3}$/,/^0(?:\.\d{1,3}){3}$/,/^10(?:\.\d{1,3}){3}$/,/^192\.168(?:\.\d{1,3}){2}$/,/^172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2}$/,/^169\.254(?:\.\d{1,3}){2}$/,/^::1$/,/^fe80:/i,/^fc00:/i,/^fd[0-9a-f]{2}:/i,/^metadata\.google\.internal$/i,/^metadata\.azure\.internal$/i,/^metadata\.packet\.net$/i];function w3(Q){if(typeof Q!=="string"||Q.length===0)return!1;let Y;try{Y=new URL(Q)}catch{return!1}if(Y.protocol!=="http:"&&Y.protocol!=="https:")return!1;let J=Y.hostname.replace(/^\[|\]$/g,"").replace(/\.$/,"");return!L3.some((G)=>G.test(J))}function n1(Q){let Y=Array.from(Q.children);for(let G of Y){let X=G.tagName.toLowerCase();if($0.has(X)){G.remove();continue}if(n1(G),!o1.has(X)){let j=Q.ownerDocument.createTextNode(G.textContent??"");G.replaceWith(j)}}let J=Array.from(Q.attributes).map((G)=>G.name);for(let G of J)if(!F0.has(G.toLowerCase()))Q.removeAttribute(G);if(Q.tagName.toLowerCase()==="audio"){let G=Q.getAttribute("src");if(G!==null&&!w3(G))Q.removeAttribute("src")}}function r1(Q){let Y=Q.tagName.toLowerCase(),J=Array.from(Q.attributes).filter((X)=>F0.has(X.name.toLowerCase())).map((X)=>` ${X.name}="${R3(X.value)}"`).join("");if(H0.has(Y))return`<${Y}${J}/>`;let G=[];for(let X of Array.from(Q.childNodes))if(X.nodeType===3)G.push(q1(X.nodeValue??""));else if(X.nodeType===1){let j=X,Z=j.tagName.toLowerCase();if($0.has(Z))continue;if(o1.has(Z))G.push(r1(j));else G.push(q1(j.textContent??""))}return`<${Y}${J}>${G.join("")}</${Y}>`}function a1(Q){let Y=String(Q||"").trim();if(!Y||!Y.includes("<"))return Q;if(typeof DOMParser>"u")return Q;let G=new DOMParser().parseFromString(P3(Y),"text/html"),X=G.querySelector("speak");if(X)return n1(X),r1(X);let j=G.createElement("speak");for(let Z of Array.from(G.body.childNodes))j.appendChild(Z);return n1(j),Array.from(j.childNodes).map((Z)=>{if(Z.nodeType===3)return q1(Z.nodeValue??"");if(Z.nodeType===1){let B=Z;if(o1.has(B.tagName.toLowerCase()))return r1(B);return q1(B.textContent??"")}return""}).join("")}function q1(Q){return Q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function R3(Q){return Q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var P0=new Set(["spoken","sign-language","transcript","braille","tactile","simplified-language","audio-description","extended-description"]),t1="ext:";function N0(Q){if(P0.has(Q))return!0;return Q.startsWith(t1)&&Q.length>t1.length}var M0=new Set;function e1(Q,Y=new Set){if(Q===null||typeof Q==="string"||typeof Q==="number"||typeof Q==="boolean"||typeof Q>"u")return Q;if(typeof Q!=="object")throw TypeError("catalog cards must contain JSON-compatible values");if(Y.has(Q))throw TypeError("catalog cards must not contain cycles");Y.add(Q);try{if(Array.isArray(Q))return Object.freeze(Q.map((X)=>e1(X,Y)));let J=Object.getPrototypeOf(Q);if(J!==Object.prototype&&J!==null)throw TypeError("catalog cards must contain only plain objects and arrays");let G={};for(let[X,j]of Object.entries(Q))G[X]=e1(j,Y);return Object.freeze(G)}finally{Y.delete(Q)}}function z0(Q,Y,J){let G=`${Y}|${Q}`;if(M0.has(G))return;M0.add(G);let X=`${Array.from(P0).join(", ")}, or an "${t1}" prefixed vendor extension`;if(Y==="card"){console.warn(`[AccessibilityCatalogResolver] catalog "${J}" has a card of unknown type "${Q}"; it is stored but no reader asks for that type, so the alternate will never be shown. Expected one of: ${X}.`);return}console.warn(`[AccessibilityCatalogResolver] lookup for unknown catalog type "${Q}" on "${J}" cannot match any card. Expected one of: ${X}.`)}var O0=(Q)=>Q.payload!==void 0?"payload":"content";class Q9{assessmentCatalogs=new Map;itemCatalogs=new Map;scopedCatalogs=new Map;defaultLanguage="en-US";sanitizedSpokenCache=new Map;catalogChangeListeners=new Set;reportedSnapshotProblems=new Set;constructor(Q,Y="en-US"){this.defaultLanguage=Y,this.indexCatalogs(Q??[],"assessment")}setDefaultLanguage(Q){this.defaultLanguage=Q}onCatalogsChange(Q){return this.catalogChangeListeners.add(Q),()=>{this.catalogChangeListeners.delete(Q)}}emitCatalogsChange(Q){for(let Y of Array.from(this.catalogChangeListeners))try{Y(Q)}catch{}}getDefaultLanguage(){return this.defaultLanguage}indexCatalogs(Q,Y){let J=Y==="assessment"?this.assessmentCatalogs:this.itemCatalogs;for(let G of this.sanitizeCatalogs(Q)){if(J.has(G.identifier)){console.warn(`[AccessibilityCatalogResolver] Duplicate ${Y} catalog "${G.identifier}" ignored`);continue}J.set(G.identifier,G)}}insertScopedCatalogs(Q,Y){if(!Y||Y.length===0)return null;let J=this.getOwnerKey(Q),G=this.scopedCatalogs.get(J),X=G?.catalogs??new Map,j=[];for(let Z of this.sanitizeCatalogs(Y)){if(X.has(Z.identifier)){console.warn(`[AccessibilityCatalogResolver] Duplicate scoped catalog "${Z.identifier}" ignored for ${J}`);continue}X.set(Z.identifier,Z),j.push(Z.identifier)}if(!G&&j.length>0)this.scopedCatalogs.set(J,{context:{...Q},catalogs:X});return{key:J,context:{...Q},catalogs:X,insertedIds:j}}removeScopedInsertion(Q){let Y=this.scopedCatalogs.get(Q.key);if(Y?.catalogs!==Q.catalogs)return!1;let J=!1;for(let G of Q.insertedIds)J=Y.catalogs.delete(G)||J;if(Y.catalogs.size===0)this.scopedCatalogs.delete(Q.key);return J}registerCatalogs(Q,Y){let J=this.insertScopedCatalogs(Q,Y);if(J&&J.insertedIds.length>0)this.emitCatalogsChange({reason:"scoped-registered",context:Q});let G=!0;return()=>{if(!G)return;if(G=!1,J&&this.removeScopedInsertion(J))this.emitCatalogsChange({reason:"scoped-removed",context:Q})}}registerOwner(Q){let{owner:Y,entity:J}=Q,G=s1(Y),X=[],j=[];try{j=_0(J,Y)}catch(W){console.warn("[AccessibilityCatalogResolver] A mounted content owner could not be traversed for catalogs; the primary content remains available.",W)}for(let W of j)try{let K=this.insertScopedCatalogs(W.context,W.catalogs);if(K)X.push(K)}catch(K){console.warn("[AccessibilityCatalogResolver] Invalid catalogs on a mounted content owner were ignored; the primary content and other valid catalogs remain available.",K)}if(X.some((W)=>W.insertedIds.length>0))this.emitCatalogsChange({reason:"scoped-registered",context:G});let B=!0;return()=>{if(!B)return;B=!1;let W=!1;for(let K of X)W=this.removeScopedInsertion(K)||W;if(W)this.emitCatalogsChange({reason:"scoped-removed",context:G})}}forOwner(Q){let Y={...Q};return Object.freeze({snapshot:()=>this.createOwnerSnapshot(Y),onChange:(J)=>this.onCatalogsChange((G)=>{if(this.catalogChangeAffectsOwner(G,Y))J()})})}addItemCatalogs(Q){if(!Q||Q.length===0)return;this.indexCatalogs(Q,"item"),this.emitCatalogsChange({reason:"item-added"})}clearItemCatalogs(){if(this.itemCatalogs.size===0)return;this.itemCatalogs.clear(),this.emitCatalogsChange({reason:"item-cleared"})}hasCatalog(Q){return this.itemCatalogs.has(Q)||this.assessmentCatalogs.has(Q)||Array.from(this.scopedCatalogs.values()).some((Y)=>Y.catalogs.has(Q))}getAlternative(Q,Y){if(!N0(Y.type))z0(Y.type,"lookup",Q);let J=Y.context?this.scopedCatalogs.get(this.getOwnerKey(Y.context))?.catalogs.get(Q):null;if(J){let j=this.findMatchingCard(J,Y);if(j)return this.resolveCard(Q,j,"item")}if(Y.context){let j=this.findScopedCandidates(Q,Y.context);if(j.length===1){let Z=this.findMatchingCard(j[0],Y);if(Z)return this.resolveCard(Q,Z,"item")}else if(j.length>1)return console.warn(`[AccessibilityCatalogResolver] Ambiguous scoped catalog "${Q}" for owner context`,Y.context),null}let G=this.itemCatalogs.get(Q);if(G){let j=this.findMatchingCard(G,Y);if(j)return this.resolveCard(Q,j,"item")}let X=this.assessmentCatalogs.get(Q);if(X){let j=this.findMatchingCard(X,Y);if(j)return this.resolveCard(Q,j,"assessment")}return null}resolveCard(Q,Y,J){return{catalogId:Q,type:Y.catalog,language:Y.language,content:Y.catalog==="spoken"&&Y.content!==void 0?this.ensureSpokenSanitized(Y.content):Y.content,payload:Y.payload,source:J}}ensureSpokenSanitized(Q){let Y=this.sanitizedSpokenCache.get(Q);if(Y!==void 0)return Y;let J=a1(Q);return this.sanitizedSpokenCache.set(Q,J),J}getOwnerKey(Q){return[Q.ownerKind,Q.assessmentId||"",Q.sectionId||"",Q.canonicalItemId||"",Q.itemId||"",Q.passageId||"",Q.modelId||""].join("|")}scopedCatalogEntries(){let Q=[];for(let Y of this.scopedCatalogs.values())for(let J of Y.catalogs.entries())Q.push(J);return Q}findScopedCandidates(Q,Y){return Array.from(this.scopedCatalogs.values()).filter((J)=>this.isCompatibleOwnerContext(J.context,Y)).map((J)=>J.catalogs.get(Q)).filter((J)=>Boolean(J))}isCompatibleOwnerContext(Q,Y){if(Q.ownerKind!==Y.ownerKind)return!1;if(Y.assessmentId&&Q.assessmentId!==Y.assessmentId)return!1;if(Y.sectionId&&Q.sectionId!==Y.sectionId)return!1;if(Y.canonicalItemId&&Q.canonicalItemId!==Y.canonicalItemId)return!1;if(Y.itemId&&Q.itemId!==Y.itemId)return!1;if(Y.passageId&&Q.passageId!==Y.passageId)return!1;if(Y.modelId&&Q.modelId!==Y.modelId)return!1;return!0}ownerScopedCatalogEntries(Q){let Y=[],J=this.scopedCatalogs.get(this.getOwnerKey(Q));if(J)Y.push(...J.catalogs.entries());for(let G of this.scopedCatalogs.values()){if(G===J)continue;if(!this.isCompatibleOwnerContext(G.context,Q))continue;Y.push(...G.catalogs.entries())}return Y}createOwnerSnapshot(Q){let Y=[],J=this.ownerScopedCatalogEntries(Q);if(Q.ownerKind==="global")J.push(...this.assessmentCatalogs.entries());for(let[G,X]of J)for(let j of X.cards)try{Y.push(Object.freeze({catalogId:G,card:e1(j)}))}catch(Z){let B=`${this.getOwnerKey(Q)}\x00${G}`;if(!this.reportedSnapshotProblems.has(B))this.reportedSnapshotProblems.add(B),console.warn(`[AccessibilityCatalogResolver] Catalog "${G}" contains a card that cannot be exposed in an owner snapshot; that card was ignored.`,Z)}return Object.freeze({cards:Object.freeze(Y)})}catalogChangeAffectsOwner(Q,Y){if(!Q.context)return!1;if(this.isCompatibleOwnerContext(Q.context,Y))return!0;if(Y.ownerKind==="itemModel"&&Y.modelId&&Q.context.ownerKind==="itemModel"&&!Q.context.modelId)return this.isCompatibleOwnerContext({...Q.context,modelId:Y.modelId},Y);return!1}sanitizeCatalogs(Q){return Q.map((Y)=>({...Y,cards:Y.cards.map((J)=>{if(!N0(J.catalog))z0(J.catalog,"card",Y.identifier);return{...J,content:J.catalog==="spoken"&&J.content!==void 0?a1(J.content):J.content}})}))}findMatchingCard(Q,Y){let{type:J,language:G,useFallback:X=!0,form:j}=Y,Z=[],B=(W)=>{for(let K of E3(W))Z.push((U)=>D0(U.language)===K)};if(G)B(G);if(X)B(this.defaultLanguage),Z.push(()=>!0);for(let W of Z){let K=Q.cards.filter((U)=>U.catalog===J&&W(U));if(K.length===0)continue;if(j){let U=K.find((_)=>O0(_)===j);if(U)return U}return K[0]}return null}getAllAlternatives(Q){let Y=[],J=new Set,G=(Z,B)=>{let W=`${Z.catalog}|${D0(Z.language)}|${O0(Z)}`;if(J.has(W))return;J.add(W),Y.push(this.resolveCard(Q,Z,B))},X=this.itemCatalogs.get(Q);if(X)for(let Z of X.cards)G(Z,"item");let j=this.assessmentCatalogs.get(Q);if(j)for(let Z of j.cards)G(Z,"assessment");for(let[Z,B]of this.scopedCatalogEntries()){if(Z!==Q)continue;for(let W of B.cards)G(W,"item")}return Y}getAllCatalogIds(){let Q=this.scopedCatalogEntries().map(([Y])=>Y);return Array.from(new Set([...this.itemCatalogs.keys(),...this.assessmentCatalogs.keys(),...Q]))}getStatistics(){let Q=new Set,Y=new Set;for(let J of this.assessmentCatalogs.values())for(let G of J.cards)if(Q.add(G.catalog),G.language)Y.add(G.language);for(let J of this.itemCatalogs.values())for(let G of J.cards)if(Q.add(G.catalog),G.language)Y.add(G.language);for(let J of this.scopedCatalogs.values())for(let G of J.catalogs.values())for(let X of G.cards)if(Q.add(X.catalog),X.language)Y.add(X.language);return{totalCatalogs:this.assessmentCatalogs.size+this.itemCatalogs.size+Array.from(this.scopedCatalogs.values()).reduce((J,G)=>J+G.catalogs.size,0),assessmentCatalogs:this.assessmentCatalogs.size,itemCatalogs:this.itemCatalogs.size+Array.from(this.scopedCatalogs.values()).reduce((J,G)=>J+G.catalogs.size,0),availableTypes:Q,availableLanguages:Y}}hasAlternativeType(Q,Y){return this.getAllAlternatives(Q).some((G)=>G.type===Y)}getCatalogsByType(Q){let Y=new Set;for(let[J,G]of this.assessmentCatalogs.entries())if(G.cards.some((X)=>X.catalog===Q))Y.add(J);for(let[J,G]of this.itemCatalogs.entries())if(G.cards.some((X)=>X.catalog===Q))Y.add(J);for(let[J,G]of this.scopedCatalogEntries())if(G.cards.some((X)=>X.catalog===Q))Y.add(J);return Array.from(Y)}reset(){this.assessmentCatalogs.clear(),this.itemCatalogs.clear(),this.scopedCatalogs.clear(),this.sanitizedSpokenCache.clear(),this.reportedSnapshotProblems.clear()}destroy(){this.reset()}}class Y9{elementStates=new Map;listeners=new Set;onStateChange=null;getGlobalElementId(Q,Y,J,G){return`${Q}:${Y}:${J}:${G}`}parseGlobalElementId(Q){let Y=Q.split(":");if(Y.length!==4)return null;return{assessmentId:Y[0],sectionId:Y[1],itemId:Y[2],elementId:Y[3]}}setState(Q,Y,J){let G=this.elementStates.get(Q);if(!G)G=new Map,this.elementStates.set(Q,G);G.set(Y,J),this._notifyListeners(),this._notifyStateChange()}getState(Q,Y){return this.elementStates.get(Q)?.get(Y)}getElementState(Q){let Y=this.elementStates.get(Q);if(!Y)return{};return Object.fromEntries(Y.entries())}getAllState(){let Q={};for(let[Y,J]of this.elementStates.entries())Q[Y]=Object.fromEntries(J.entries());return Q}subscribe(Q){return this.listeners.add(Q),()=>this.listeners.delete(Q)}_notifyListeners(){for(let Q of this.listeners)Q(this.elementStates)}setOnStateChange(Q){this.onStateChange=Q}_notifyStateChange(){if(this.onStateChange)this.onStateChange(this.getAllState())}loadState(Q){this.elementStates.clear();for(let[Y,J]of Object.entries(Q)){let G=new Map(Object.entries(J));this.elementStates.set(Y,G)}this._notifyListeners()}clearElement(Q){this.elementStates.delete(Q),this._notifyListeners(),this._notifyStateChange()}clearTool(Q){for(let Y of this.elementStates.values())Y.delete(Q);this._notifyListeners(),this._notifyStateChange()}clearSection(Q,Y){let J=`${Q}:${Y}:`,G=[];for(let X of this.elementStates.keys())if(X.startsWith(J))G.push(X);for(let X of G)this.elementStates.delete(X);this._notifyListeners(),this._notifyStateChange()}clearAll(){this.elementStates.clear(),this._notifyListeners(),this._notifyStateChange()}}class u7{listeners=new Set;subscribeFrameworkErrors(Q){this.listeners.add(Q);let Y=!0;return()=>{if(!Y)return;Y=!1,this.listeners.delete(Q)}}reportFrameworkError(Q){let Y=Array.from(this.listeners);for(let J of Y)try{J(Q)}catch(G){console.warn("[FrameworkErrorBus] listener failed:",G)}}dispose(){this.listeners.clear()}getListenerCount(){return this.listeners.size}}class J9{serialize(Q,Y){return{startContainer:this.getNodePath(Q.startContainer,Y),startOffset:Q.startOffset,endContainer:this.getNodePath(Q.endContainer,Y),endOffset:Q.endOffset,text:Q.toString()}}deserialize(Q,Y){let J=this.findNodeByPath(Q.startContainer,Y),G=this.findNodeByPath(Q.endContainer,Y);if(!J||!G)return null;try{let X=new Range;if(X.setStart(J,Q.startOffset),X.setEnd(G,Q.endOffset),X.toString()===Q.text)return X;return null}catch(X){return console.warn("Failed to deserialize range:",X),null}}getNodePath(Q,Y){if(Q===Y)return"";if(Q.nodeType===Node.TEXT_NODE){let J=Q.parentElement;if(!J)throw Error("Text node has no parent");let X=Array.from(J.childNodes).filter((Z)=>Z.nodeType===Node.TEXT_NODE).indexOf(Q);return`${this.getElementPath(J,Y)}::text[${X}]`}if(Q.nodeType===Node.ELEMENT_NODE)return this.getElementPath(Q,Y);throw Error(`Unsupported node type: ${Q.nodeType}`)}getElementPath(Q,Y){if(Q===Y)return"";let J=[],G=Q;while(G&&G!==Y){if(G.id){J.unshift(`#${G.id}`);break}let X=G.parentElement;if(!X)break;let j=Array.from(X.children).filter((W)=>W.tagName===G.tagName),Z=j.indexOf(G),B=j.length>1?`${G.tagName.toLowerCase()}:nth-of-type(${Z+1})`:G.tagName.toLowerCase();J.unshift(B),G=X}return J.join(" > ")}findNodeByPath(Q,Y){if(Q==="")return Y;if(Q.includes("::text[")){let[J,G]=Q.split("::text["),X=Number.parseInt(G.replace("]",""),10),j=J?Y.querySelector(J):Y;if(!j)return null;return Array.from(j.childNodes).filter((B)=>B.nodeType===Node.TEXT_NODE)[X]||null}try{return Y.querySelector(Q)}catch(J){return console.warn("Invalid selector path:",Q,J),null}}serializeMany(Q,Y){return Q.map((J)=>this.serialize(J,Y))}deserializeMany(Q,Y){return Q.map((J)=>this.deserialize(J,Y))}}var u;(function(Q){Q.TTS_WORD="tts-word",Q.TTS_SENTENCE="tts-sentence",Q.ANNOTATION="annotation"})(u||(u={}));var _7;(function(Q){Q.YELLOW="yellow",Q.GREEN="green",Q.BLUE="blue",Q.PINK="pink",Q.ORANGE="orange",Q.UNDERLINE="underline"})(_7||(_7={}));class p7{ttsWordHighlight=null;ttsSentenceHighlight=null;ttsWordElementHighlights=new Set;ttsSentenceElementHighlights=new Set;annotations=new Map;colorHighlights=new Map;nextAnnotationId=1;supported=!1;rangeSerializer;themeObserver=null;explicitTTSColorOverride=null;constructor(){if(this.rangeSerializer=new J9,typeof CSS>"u"||!("highlights"in CSS)){console.warn("CSS Custom Highlight API not supported (SSR or unsupported browser)");return}this.supported=!0,this.initializeHighlights(),this.registerStyles(),this.applyAdaptiveTTSStyle(),this.setupThemeObservation()}setupThemeObservation(){if(typeof document>"u")return;if(typeof MutationObserver>"u")return;let Q=()=>this.applyAdaptiveTTSStyle();this.themeObserver=new MutationObserver(Q),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["style","data-theme","data-color-scheme","class"]});for(let Y of document.querySelectorAll("pie-theme"))this.themeObserver.observe(Y,{attributes:!0,attributeFilter:["theme","scheme","provider","variables","style","data-theme","data-color-scheme"]})}parseColor(Q){if(!Q)return null;let Y=Q.trim();if(!Y)return null;let J=/^#([a-f\d]{3}|[a-f\d]{6})$/i.exec(Y);if(J){let X=J[1];if(X.length===3)return[parseInt(X[0]+X[0],16),parseInt(X[1]+X[1],16),parseInt(X[2]+X[2],16)];return[parseInt(X.slice(0,2),16),parseInt(X.slice(2,4),16),parseInt(X.slice(4,6),16)]}let G=/^rgba?\((.+)\)$/i.exec(Y);if(G){let j=G[1].replace(/\//g,",").split(/[,\s]+/).map((K)=>K.trim()).filter(Boolean),Z=Number(j[0]),B=Number(j[1]),W=Number(j[2]);if(Number.isFinite(Z)&&Number.isFinite(B)&&Number.isFinite(W))return[Z,B,W]}if(typeof document<"u"){let X=document.createElement("span");if(X.style.color=Y,typeof X.style.color==="string"&&X.style.color){document.body?.appendChild(X);let j=typeof getComputedStyle==="function"?getComputedStyle(X).color:"";X.remove();let Z=j.trim();if(Z&&Z!==Y)return this.parseColor(j)}}return null}relativeLuminance([Q,Y,J]){let G=(B)=>{let W=B/255;return W<=0.03928?W/12.92:((W+0.055)/1.055)**2.4},X=G(Q),j=G(Y),Z=G(J);return 0.2126*X+0.7152*j+0.0722*Z}contrastRatio(Q,Y){let J=this.relativeLuminance(Q),G=this.relativeLuminance(Y),X=Math.max(J,G),j=Math.min(J,G);return(X+0.05)/(j+0.05)}blend(Q,Y,J){return[Math.round(Q[0]*J+Y[0]*(1-J)),Math.round(Q[1]*J+Y[1]*(1-J)),Math.round(Q[2]*J+Y[2]*(1-J))]}resolveAdaptiveTTSStyle(Q){let Y=[255,235,59],J=[17,24,39],G=[255,255,255],X=Q||(typeof document<"u"?document.documentElement:null),j=X&&typeof getComputedStyle==="function"?getComputedStyle(X):null,Z=this.parseColor(j?.getPropertyValue("--pie-background")||j?.backgroundColor)||G,B=this.parseColor(j?.getPropertyValue("--pie-text"))||J,W=this.explicitTTSColorOverride?this.parseColor(this.explicitTTSColorOverride.color)||Y:this.parseColor(j?.getPropertyValue("--pie-missing"))||Y,K=this.explicitTTSColorOverride?[Math.max(0.3,Math.min(0.95,this.explicitTTSColorOverride.opacity))]:[0.8,0.72,0.68,0.62,0.56,0.5],U=K[K.length-1],_=-1/0;for(let g of K){let B7=this.blend(W,Z,g),q7=this.contrastRatio(B7,Z),W7=this.contrastRatio(B7,B),w7=q7*1.2+W7*0.8;if(q7>=1.25&&W7>=2.4){U=g;break}if(w7>_)_=w7,U=g}let $=Math.max(0.24,Math.min(0.85,U*0.55)),N=Math.max(0.55,Math.min(0.95,U+0.2)),D=Math.max(0.22,Math.min(0.6,U*0.45)),O=B,P=this.blend(O,Z,N),F=this.contrastRatio(P,Z),L=this.relativeLuminance(Z)>0.45?[0,0,0]:[255,255,255],C=F>=1.35?O:L,v=`rgba(${W[0]}, ${W[1]}, ${W[2]}, ${U})`,k=`rgba(${W[0]}, ${W[1]}, ${W[2]}, ${$})`,p=`rgba(${C[0]}, ${C[1]}, ${C[2]}, ${N})`,R=`rgba(${C[0]}, ${C[1]}, ${C[2]}, ${D})`;return{wordHighlight:v,sentenceHighlight:k,wordUnderline:p,wordShadow:R}}applyAdaptiveTTSStyle(Q){if(typeof document>"u")return;let Y=this.resolveAdaptiveTTSStyle(Q);document.documentElement.style.setProperty("--pie-tts-word-highlight",Y.wordHighlight),document.documentElement.style.setProperty("--pie-tts-sentence-highlight",Y.sentenceHighlight),document.documentElement.style.setProperty("--pie-tts-line-highlight",Y.sentenceHighlight),document.documentElement.style.setProperty("--pie-tts-word-underline",Y.wordUnderline),document.documentElement.style.setProperty("--pie-tts-word-shadow",Y.wordShadow)}initializeHighlights(){if(!this.supported)return;this.ttsWordHighlight=new Highlight,this.ttsSentenceHighlight=new Highlight,CSS.highlights.set("tts-word",this.ttsWordHighlight),CSS.highlights.set("tts-sentence",this.ttsSentenceHighlight);for(let Q of Object.values(_7)){let Y=new Highlight;this.colorHighlights.set(Q,Y),CSS.highlights.set(`annotation-${Q}`,Y)}}registerStyles(){if(!this.supported)return;if(typeof document>"u")return;if(document.getElementById("pie-highlight-styles"))return;let Q=document.createElement("style");Q.id="pie-highlight-styles",Q.textContent=`
|
|
6
6
|
/* TTS highlights - temporary */
|
|
7
7
|
::highlight(tts-word) {
|
|
8
8
|
background-color: var(--pie-tts-word-highlight, color-mix(in srgb, var(--pie-missing, #ffeb3b) 68%, transparent));
|
|
@@ -212,14 +212,14 @@ ${Y}`)}function Z7(G,Q={}){let Y=i1(Q.strictness),J=Q.source??"tools",X=N5(Q.too
|
|
|
212
212
|
text-shadow: none;
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
|
-
`,document.head.appendChild(G)}highlightTTSWord(G,Q,Y){if(!this.ttsWordHighlight)return;this.applyAdaptiveTTSStyle(G.parentElement),this.clearTTSWord();let J=document.createRange();J.setStart(G,Q),J.setEnd(G,Y),this.ttsWordHighlight.add(J)}highlightTTSWordElement(G){if(!this.ttsWordHighlight)return;this.applyAdaptiveTTSStyle(G),this.clearTTSWord(),G.setAttribute("data-pie-tts-word-element","true"),this.ttsWordElementHighlights.add(G)}highlightTTSSentence(G){if(!this.ttsSentenceHighlight)return;let Q=G[0]?.startContainer,Y=Q?.nodeType===Node.ELEMENT_NODE?Q:Q?.parentElement;this.applyAdaptiveTTSStyle(Y),this.clearTTSSentence();for(let J of G)this.ttsSentenceHighlight.add(J);this.highlightTTSElementFallbacks(G)}highlightTTSSentenceElements(G){if(!this.ttsSentenceHighlight)return;this.applyAdaptiveTTSStyle(G[0]||null),this.clearTTSSentence();for(let Q of G)Q.setAttribute("data-pie-tts-sentence-element","true"),this.ttsSentenceElementHighlights.add(Q)}static SENTENCE_FALLBACK_SELECTOR="math, mjx-container, svg, img, canvas, [role='img']";static WORD_FALLBACK_SELECTOR="svg, img, canvas, [role='img']";highlightTTSElementFallbacks(G){if(typeof Element>"u")return;this.highlightElementFallbacks(G,"data-pie-tts-sentence-element",this.ttsSentenceElementHighlights,g7.SENTENCE_FALLBACK_SELECTOR)}highlightTTSWordElementFallbacks(G){if(typeof Element>"u")return;this.highlightElementFallbacks(G,"data-pie-tts-word-element",this.ttsWordElementHighlights,g7.WORD_FALLBACK_SELECTOR)}highlightElementFallbacks(G,Q,Y,J){for(let X of G){let j=X.commonAncestorContainer.nodeType===Node.ELEMENT_NODE?X.commonAncestorContainer:X.commonAncestorContainer.parentElement;if(!j)continue;let Z=[],q=X.startContainer.nodeType===Node.ELEMENT_NODE?X.startContainer:X.startContainer.parentElement,B=X.endContainer.nodeType===Node.ELEMENT_NODE?X.endContainer:X.endContainer.parentElement;for(let K of[q,B]){let W=K;while(W){if(W.matches?.(J))Z.push(W);W=W.parentElement}}if(j.matches?.(J))Z.push(j);Z.push(...Array.from(j.querySelectorAll(J)));for(let K of new Set(Z)){try{if(!X.intersectsNode(K)&&!K.contains(q)&&!K.contains(B))continue}catch{continue}K.setAttribute(Q,"true"),Y.add(K)}}}clearTTSWord(){if(!this.ttsWordHighlight)return;this.ttsWordHighlight.clear();for(let G of this.ttsWordElementHighlights)G.removeAttribute("data-pie-tts-word-element");this.ttsWordElementHighlights.clear()}clearTTSSentence(){if(!this.ttsSentenceHighlight)return;this.ttsSentenceHighlight.clear();for(let G of this.ttsSentenceElementHighlights)G.removeAttribute("data-pie-tts-sentence-element");this.ttsSentenceElementHighlights.clear()}clearTTS(){this.clearTTSWord(),this.clearTTSSentence()}addAnnotation(G,Q=$7.YELLOW){let Y=`annotation-${this.nextAnnotationId++}`,J=G.cloneRange(),X={id:Y,range:J,type:u.ANNOTATION,color:Q,timestamp:Date.now()};this.annotations.set(Y,X);let j=this.colorHighlights.get(Q);if(j)j.add(J);return Y}removeAnnotation(G){let Q=this.annotations.get(G);if(!Q){console.warn(`[HighlightCoordinator] Annotation ${G} not found`);return}console.log(`[HighlightCoordinator] Removing annotation ${G} (color: ${Q.color})`);let Y=this.colorHighlights.get(Q.color);if(Y){let J=Y.delete(Q.range);console.log("[HighlightCoordinator] Highlight.delete() returned:",J)}this.annotations.delete(G),console.log(`[HighlightCoordinator] Annotation ${G} removed from map. Remaining:`,this.annotations.size)}clearAnnotations(){for(let G of this.colorHighlights.values())G.clear();this.annotations.clear()}getAnnotations(){return Array.from(this.annotations.values())}getAnnotation(G){return this.annotations.get(G)??null}changeAnnotationColor(G,Q){let Y=this.annotations.get(G);if(!Y)return;let J=Y.color;if(J===Q)return;let X=this.colorHighlights.get(J);if(X)X.delete(Y.range);Y.color=Q;let j=this.colorHighlights.get(Q);if(j)j.add(Y.range)}exportAnnotations(G=document.body){return this.getAnnotations().map((Q)=>({...this.rangeSerializer.serialize(Q.range,G),id:Q.id,color:Q.color,timestamp:Q.timestamp}))}importAnnotations(G,Q=document.body){let Y=0;for(let J of G){let X=this.rangeSerializer.deserialize(J,Q);if(X)this.addAnnotation(X,J.color),Y++}return Y}highlightRange(G,Q,Y=$7.YELLOW){if(!this.supported)return;switch(Q){case u.TTS_WORD:case u.TTS_SENTENCE:{let J=Q===u.TTS_WORD?this.ttsWordHighlight:this.ttsSentenceHighlight;if(J){if(J.clear(),J.add(G),Q===u.TTS_WORD){for(let X of this.ttsWordElementHighlights)X.removeAttribute("data-pie-tts-word-element");this.ttsWordElementHighlights.clear(),this.highlightTTSWordElementFallbacks([G])}}break}case u.ANNOTATION:this.addAnnotation(G,Y);break}}clearHighlights(G){if(!this.supported)return;switch(G){case u.TTS_WORD:this.clearTTSWord();break;case u.TTS_SENTENCE:this.clearTTSSentence();break;case u.ANNOTATION:this.clearAnnotations();break}}clearAll(){if(!this.supported)return;this.clearTTS(),this.clearAnnotations()}isSupported(){return this.supported}updateTTSHighlightStyle(G,Q){if(!this.supported)return;if(typeof document>"u")return;if(!document.getElementById("pie-highlight-styles"))return;let X=((j)=>{let Z=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(j);return Z?{r:parseInt(Z[1],16),g:parseInt(Z[2],16),b:parseInt(Z[3],16)}:null})(G);if(!X)return;this.explicitTTSColorOverride={color:`rgb(${X.r}, ${X.g}, ${X.b})`,opacity:Math.max(0.2,Math.min(0.95,Q))},this.applyAdaptiveTTSStyle()}destroy(){if(!this.supported)return;this.clearTTS(),this.clearAnnotations(),this.themeObserver?.disconnect(),this.themeObserver=null}}function N6(G){return(...Q)=>{console.debug(`[${G}]`,...Q)}}var a=N6("ToolCoordinator"),j7;(function(G){G[G.BASE=0]="BASE",G[G.TOOL=1000]="TOOL",G[G.MODAL=2000]="MODAL",G[G.CONTROL=3000]="CONTROL",G[G.HIGHLIGHT=4000]="HIGHLIGHT"})(j7||(j7={}));class X8{config;tools=new Map;layerCounters=new Map;listeners=new Set;visibilityState=new Map;constructor(G={}){this.config=G,this.layerCounters.set(j7.BASE,0),this.layerCounters.set(j7.TOOL,0),this.layerCounters.set(j7.MODAL,0),this.layerCounters.set(j7.CONTROL,0),this.layerCounters.set(j7.HIGHLIGHT,0)}subscribe(G){return this.listeners.add(G),()=>{this.listeners.delete(G)}}notifyListeners(){this.listeners.forEach((G)=>G())}registerTool(G,Q,Y,J=j7.MODAL){if(a("registerTool called:",{id:G,name:Q,hasElement:!!Y,layer:J}),this.tools.has(G)){a(`Tool ${G} is already registered`);return}let X=this.visibilityState.get(G)??!1;if(!Y){this.tools.set(G,{id:G,name:Q,element:null,layer:J,isVisible:X,baseZIndex:J}),a("Tool registered without element:",G);return}let j=J+this.getNextLayerOffset(J);Y.style.zIndex=String(j),Y.style.display=X?"":"none";let Z=()=>this.bringToFront(Y);if(Y.addEventListener("mousedown",Z),this.tools.set(G,{id:G,name:Q,element:Y,layer:J,isVisible:X,baseZIndex:j,mouseDownHandler:Z}),X)this.bringToFront(Y);a("Tool registered with element:",G)}unregisterTool(G){let Q=this.tools.get(G);if(!Q)return;if(Q.element&&Q.mouseDownHandler)Q.element.removeEventListener("mousedown",Q.mouseDownHandler);this.tools.delete(G)}releaseTool(G){this.unregisterTool(G),this.visibilityState.delete(G)}showTool(G){let Q=this.tools.get(G);if(!Q){a(`Tool ${G} not found`);return}if(Q.element)Q.element.style.display="",this.bringToFront(Q.element);Q.isVisible=!0,this.visibilityState.set(G,!0),this.notifyListeners()}hideTool(G){let Q=this.tools.get(G);if(!Q){a(`Tool ${G} not found`);return}if(Q.element)Q.element.style.display="none";Q.isVisible=!1,this.visibilityState.set(G,!1),this.notifyListeners()}toggleTool(G){a("toggleTool called for:",G);let Q=this.tools.get(G);if(!Q){a(`Tool ${G} not found. Registered tools:`,Array.from(this.tools.keys()));return}if(a("Tool found, current visibility:",Q.isVisible),Q.isVisible)this.hideTool(G);else this.showTool(G)}isToolVisible(G){let Q=this.tools.get(G);if(Q)return Q.isVisible;return this.visibilityState.get(G)??!1}bringToFront(G){let Q=Array.from(this.tools.values()).find((X)=>X.element===G);if(!Q)return;let Y=this.getMaxZIndexInLayer(Q.layer),J=Math.max(Y+1,Q.layer+1);G.style.zIndex=String(J),Q.baseZIndex=J}getRegisteredTools(){return Array.from(this.tools.keys())}getToolElement(G){return this.tools.get(G)?.element??null}getNextLayerOffset(G){let Q=this.layerCounters.get(G)??0;return this.layerCounters.set(G,Q+1),Q}getMaxZIndexInLayer(G){let Q=G;for(let Y of this.tools.values())if(Y.layer===G)Q=Math.max(Q,Y.baseZIndex);return Q}resetZIndices(){for(let G of this.tools.values())if(G.element)G.element.style.zIndex=String(G.baseZIndex)}updateToolElement(G,Q){let Y=this.tools.get(G);if(!Y){a(`Tool ${G} not found`);return}if(Y.element&&Y.mouseDownHandler)Y.element.removeEventListener("mousedown",Y.mouseDownHandler);let J=()=>this.bringToFront(Q);if(Q.addEventListener("mousedown",J),Y.element=Q,Y.mouseDownHandler=J,Q.style.zIndex=String(Y.baseZIndex),Y.isVisible)Q.style.display="";else Q.style.display="none"}hideAllTools(){for(let G of this.tools.keys())this.hideTool(G);this.notifyListeners()}getToolState(G){let Q=this.tools.get(G);if(!Q)return;return{id:Q.id,name:Q.name,isVisible:Q.isVisible,element:Q.element??null,layer:Q.layer}}getVisibleTools(){return Array.from(this.tools.values()).filter((G)=>G.isVisible).map((G)=>({id:G.id,name:G.name,isVisible:G.isVisible,element:G.element??null,layer:G.layer}))}}var S5=/^[a-z][a-z0-9+.-]*:/i,T5=new Set(["http:","https:","data:","blob:"]);function F6(G){return G!==void 0&&G!==1}function C5(G){if(typeof G!=="string")return!1;let Q=G.trim();if(!Q)return!1;if(Q.startsWith("//")||!S5.test(Q))return!0;let Y=Q.slice(0,Q.indexOf(":")+1).toLowerCase();return T5.has(Y)}function M6(G){if(!Array.isArray(G))return[];let Q=[];for(let Y of G){if(!Y||typeof Y!=="object")continue;let J=Y;if(!C5(J.src))continue;let X={src:J.src.trim()};if(typeof J.type==="string"&&J.type.trim())X.type=J.type.trim();if(Number.isFinite(J.width))X.width=J.width;if(Number.isFinite(J.height))X.height=J.height;if(Q.some((j)=>j.src===X.src))continue;Q.push(X)}return Q}function z6(G){if(!G||typeof G!=="object")return;let Q=G,Y=Number(Q.startSeconds);if(!Number.isFinite(Y)||Y<0)return;let J=Number(Q.endSeconds);if(!Number.isFinite(J)||J<=Y)return{startSeconds:Y};return{startSeconds:Y,endSeconds:J}}function O6(G){if(typeof G!=="string")return;return G.trim()||void 0}var y5=100,x5=1;function P6(G,Q,Y){if(!Q)return()=>{};let{startSeconds:J,endSeconds:X}=Q,j;if(J>0)if(j=()=>{if(G.currentTime<J)G.currentTime=J},G.readyState>=x5)j();else G.addEventListener("loadedmetadata",j);let Z,q;if(X!==void 0)Z=()=>{if(G.currentTime>=X)Y()},G.addEventListener("timeupdate",Z),q=setInterval(()=>{if(!G.paused)Z?.()},y5);return()=>{if(j)G.removeEventListener("loadedmetadata",j);if(Z)G.removeEventListener("timeupdate",Z);if(q!==void 0)clearInterval(q)}}function L6(G,Q){if(!Q)return G;if(G.includes("#"))return G;let Y=Q.endSeconds!==void 0?`,${Q.endSeconds}`:"";return`${G}#t=${Q.startSeconds}${Y}`}function w6(G){if(!G)return null;let Q=G.payload;if(!Q||typeof Q!=="object")return null;let Y=Q.media;if(!Y||typeof Y!=="object")return console.warn("[spoken-audio] card carries a `payload` with no `media`; recorded speech needs `media.sources`, so this card is ignored and read-aloud falls back to the script or generated speech"),null;if(F6(Y.version))return console.warn(`[spoken-audio] card's media declares version ${String(Y.version)}, which this build does not render; the card is ignored and read-aloud falls back to the script or generated speech`),null;if(Y.kind!==void 0&&Y.kind!=="audio")return console.warn(`[spoken-audio] card's media is kind "${Y.kind}", not "audio"; a spoken card carries recorded speech, so this card is ignored`),null;let J=M6(Y.sources);if(J.length===0)return console.warn("[spoken-audio] card's `media.sources` yielded no usable URL; read-aloud falls back to the script or generated speech"),null;return{sources:J,fragment:z6(Q.fragment),label:O6(Y.label)}}var S7=(G,Q)=>{let Y=Q?.useSentenceSegmenter!==!1;try{if(!Y)throw Error("Segmenter disabled by policy");let q=globalThis.Intl?.Segmenter;if(typeof q==="function"){let B=new q(Q?.locale,{granularity:"sentence"}),K=Array.from(B.segment(G)).map((W)=>({text:W.segment,offset:W.index})).filter((W)=>W.text.trim().length>0);if(K.length>0)return K}}catch{}let J=/[^.!?]+(?:[.!?]+|$)/g,X=G.match(J)||[G],j=[],Z=0;for(let q of X){let B=G.indexOf(q,Z);if(B===-1)continue;j.push({text:q,offset:B}),Z=B+q.length}return j.length>0?j:[{text:G,offset:0}]};var R6=5000,E6=2000,b6=(G)=>String(G||"").trim().toLowerCase(),f5=()=>{let G=typeof navigator<"u"?navigator.language||navigator.languages?.[0]:"";return b6(G||"en-US")},k5=(G,Q)=>{if(Q)return G.find((Z)=>Z.voiceURI===Q)||G.find((Z)=>Z.name===Q)||null;let Y=f5(),J=Y.split("-")[0]||"en",X=(Z)=>{let q=b6(Z.lang);return q===Y||q.startsWith(`${J}-`)},j=[(Z)=>Z.localService&&X(Z),(Z)=>Z.default&&X(Z),(Z)=>X(Z),(Z)=>Z.localService,(Z)=>Z.default];for(let Z of j){let q=G.find(Z);if(q)return q}return G[0]||null},I5=(G)=>!G.default;class T7{providerId="browser";providerName="Browser Speech Synthesis";version="1.0.0";async initialize(G){if(typeof window>"u")throw Error("BrowserTTSProvider requires browser environment");if(!("speechSynthesis"in window))throw Error("Browser does not support Speech Synthesis API");return new S6(G)}supportsFeature(G){return!0}getCapabilities(){return{supportsPause:!0,supportsResume:!0,supportsWordBoundary:!0,supportsVoiceSelection:!0,supportsRateControl:!0,supportsPitchControl:!0,supportsSSML:!1}}destroy(){}}class S6{utterance=null;config=null;_isPlaying=!1;_isPaused=!1;speakRunId=0;settlePendingVoiceWait=null;settlePendingChunk=null;onPlaybackStart=void 0;constructor(G){this.config=G}waitForBrowserVoices(G,Q){return new Promise((Y,J)=>{let X=speechSynthesis,j=typeof X.addEventListener==="function"&&typeof X.removeEventListener==="function",Z=j?null:X.onvoiceschanged,q=!1,B=null,K=null,W=()=>{if(B!==null)clearTimeout(B),B=null;if(j)X.removeEventListener("voiceschanged",N);else if(X.onvoiceschanged===F)X.onvoiceschanged=Z;if(K&&this.settlePendingVoiceWait===K)this.settlePendingVoiceWait=null},$=(O,L)=>{if(q)return;if(q=!0,W(),L)J(L);else Y(O)},H=()=>{if(G!==this.speakRunId){$(!1);return}if(X.getVoices().length>0)$(!0)},N=()=>H(),F=(O)=>{try{Z?.call(X,O)}finally{H()}};if(K=()=>$(!1),this.settlePendingVoiceWait=K,B=setTimeout(()=>$(!1,Error(`Configured browser voice "${Q}" could not be resolved because the browser did not publish its voice inventory within ${E6/1000} seconds.`)),E6),j)X.addEventListener("voiceschanged",N);else X.onvoiceschanged=F;H()})}async resolveBrowserVoice(G){let Q=typeof this.config?.voice==="string"?this.config.voice.trim():"",Y=speechSynthesis.getVoices();if(Q&&Y.length===0){if(!await this.waitForBrowserVoices(G,Q)||G!==this.speakRunId)return{shouldContinue:!1,voice:null};Y=speechSynthesis.getVoices()}if(G!==this.speakRunId)return{shouldContinue:!1,voice:null};let J=k5(Y,Q||void 0);if(Q&&!J)throw Error(`Configured browser voice "${Q}" is unavailable. Select a voice exposed by this browser using its voiceURI or name.`);return{shouldContinue:!0,voice:J}}async speak(G){if(!this.config)throw Error("TTS not initialized");this.stop();let Q=this.speakRunId,Y=await this.resolveBrowserVoice(Q);if(!Y.shouldContinue)return;let J=this.splitIntoChunks(G);for(let X of J){if(Q!==this.speakRunId)break;if(!await this.speakChunk(X.text,X.offset,Q,Y.voice))break}}async speakSegments(G){if(!this.config)throw Error("TTS not initialized");this.stop();let Q=this.speakRunId,Y=await this.resolveBrowserVoice(Q);if(!Y.shouldContinue)return;for(let J of G){if(Q!==this.speakRunId)break;let X=this.splitIntoChunks(J.text);for(let Z of X){if(Q!==this.speakRunId)break;if(!await this.speakChunk(Z.text,J.startOffset+Z.offset,Q,Y.voice))break}let j=Math.max(0,Number(J.pauseMsAfter||0));if(j>0&&Q===this.speakRunId){if(!await this.waitForPause(j,Q))break}}}async waitForPause(G,Q){return await new Promise((Y)=>setTimeout(Y,G)),Q===this.speakRunId}splitIntoChunks(G){if(G.length<=260)return[{text:G,offset:0}];let Y=this.segmentSentences(G),J=[],X="",j=0;for(let Z of Y){let q=Z.text.trim();if(!q)continue;let B=Z.text.search(/\S/),K=Z.offset+(B===-1?0:B);if(!X){X=q,j=K;continue}let W=`${X} ${q}`;if(W.length<=260)X=W;else J.push({text:X,offset:j}),X=q,j=K}if(X)J.push({text:X,offset:j});return J.length?J:[{text:G,offset:0}]}getHighlightMode(){return(this.config?.providerOptions||{}).highlightMode==="word"?"word":"sentence"}getSegmentationPolicy(){let G=this.config?.providerOptions||{},Q=G.segmenter||{},J=Q.mode!=="regexOnly",X=typeof Q.locale==="string"&&Q.locale.trim().length>0?Q.locale:typeof G.locale==="string"&&G.locale.trim().length>0?G.locale:void 0;return{useSentenceSegmenter:J,useWordSegmenter:J,locale:X}}segmentSentences(G){let Q=this.getSegmentationPolicy();return S7(G,{locale:Q.locale,useSentenceSegmenter:Q.useSentenceSegmenter})}inferWordLength(G,Q){let Y=Math.max(0,Math.min(Q,Math.max(0,G.length-1)));return G.slice(Y).match(/^\s*([^\s]+)/)?.[1]?.length||1}async speakChunk(G,Q,Y,J){return new Promise((X,j)=>{if(Y!==this.speakRunId){X(!1);return}let Z=new SpeechSynthesisUtterance(G);if(this.utterance=Z,J&&I5(J))Z.voice=J;if(this.config?.rate)Z.rate=this.config.rate;if(this.config?.pitch)Z.pitch=this.config.pitch;let q=!1,B=!1,K=null,W=null,$=()=>{if(this.utterance===Z)this.utterance=null},H=()=>{if(K!==null)clearTimeout(K),K=null},N=()=>{Z.onstart=null,Z.onend=null,Z.onerror=null,Z.onpause=null,Z.onresume=null,Z.onboundary=null},F=(L,D)=>{if(B)return;if(B=!0,H(),N(),$(),W&&this.settlePendingChunk===W)this.settlePendingChunk=null;if(Y===this.speakRunId)this._isPlaying=!1,this._isPaused=!1;if(D)j(D);else X(L)},O=(L)=>Error(L==="ended"?"Browser speech synthesis ended before audio started. The browser speech engine may be unavailable or stuck; try another voice or restart the browser.":`Browser speech synthesis did not start within ${R6/1000} seconds. The browser speech engine may be unavailable or stuck; try another voice or restart the browser.`);W=()=>F(!1),this.settlePendingChunk=W,Z.onstart=()=>{if(Y!==this.speakRunId){F(!1);return}q=!0,H(),this._isPlaying=!0,this._isPaused=!1;try{this.onPlaybackStart?.()}catch(L){console.error("Browser TTS playback-start callback failed",L)}},Z.onend=()=>{if(Y!==this.speakRunId){F(!1);return}if(!q){F(!1,O("ended"));return}F(!0)},Z.onerror=(L)=>{if(Y!==this.speakRunId){F(!1);return}if(L.error==="interrupted"||L.error==="canceled"){F(!1);return}F(!1,Error(`Speech synthesis error: ${L.error}`))},Z.onpause=()=>{if(Y!==this.speakRunId)return;this._isPaused=!0},Z.onresume=()=>{if(Y!==this.speakRunId)return;this._isPaused=!1},Z.onboundary=(L)=>{if(Y!==this.speakRunId)return;if(console.log("[BrowserProvider] Boundary event:",L.name,"charIndex:",L.charIndex,"charLength:",L.charLength),L.name!=="word"||!this.onWordBoundary)return;if(this.getHighlightMode()==="sentence")return;let D=Math.max(0,Math.min(L.charIndex,Math.max(0,G.length-1))),P=Number(L.charLength||0),S=this.inferWordLength(G,D),v=Number.isFinite(P)&&P>0&&P<=80&&D+P<=G.length?P:S,I=G.substring(D,Math.min(G.length,D+v)).trim(),p=Q+D;console.log("[BrowserProvider] Calling onWordBoundary with word:",I,"at position:",p),this.onWordBoundary(I,p,v)},K=setTimeout(()=>{if(B||q||Y!==this.speakRunId)return;F(!1,O("timedOut")),speechSynthesis.cancel()},R6);try{speechSynthesis.speak(Z)}catch(L){F(!1,L instanceof Error?L:Error("Browser speech synthesis failed to queue speech"))}})}pause(){if(this._isPlaying&&!this._isPaused)speechSynthesis.pause()}resume(){if(this._isPlaying&&this._isPaused)speechSynthesis.resume()}stop(){let G=this.utterance,Q=this._isPlaying||G!==null;if(this.speakRunId+=1,this.settlePendingVoiceWait?.(),this.settlePendingChunk?.(),Q)speechSynthesis.cancel();this.utterance=null,this._isPlaying=!1,this._isPaused=!1}isPlaying(){return this._isPlaying&&!this._isPaused}isPaused(){return this._isPaused}updateSettings(G){if(!this.config)this.config={};if(G.rate!==void 0)this.config.rate=G.rate;if(G.pitch!==void 0)this.config.pitch=G.pitch;if(G.voice!==void 0)this.config.voice=G.voice;if(G.providerOptions!==void 0)this.config.providerOptions={...this.config.providerOptions||{},...G.providerOptions||{}}}onWordBoundary}var T=(G)=>G.trim().replace(/\s+/g," "),U1=()=>/[\p{L}]+|\d+(?:\.\d+)?|[±√=+\-*/()²³^×÷≤≥≠≈<>|%°'′\u2062]/gu,Z8=(G)=>{if(G.hidden)return!0;if(G.tagName?.toLowerCase()==="mjx-assistive-mml")return!0;if(G.getAttribute("aria-hidden")==="true")return!0;if(G.hasAttribute("inert"))return!0;let Q=G.classList;if(Q?.contains("sr-only")||Q?.contains("pie-sr-only")||Q?.contains("visually-hidden"))return!0;if(typeof window<"u"){let Y=window.getComputedStyle(G);if(Y.display==="none"||Y.visibility==="hidden")return!0;let J=Number.parseFloat(Y.width||"0"),X=Number.parseFloat(Y.height||"0"),j=Number.isFinite(J)&&Number.isFinite(X)&&J<=1&&X<=1,Z=Y.clipPath.includes("inset(50%")||Y.clipPath.includes("inset(100%")||Y.clip.includes("rect(0px, 0px, 0px, 0px)")||Y.clip.includes("rect(0 0 0 0)");if((Y.position==="absolute"||Y.position==="fixed")&&j&&(Y.overflow==="hidden"||Z))return!0;if(Y.opacity==="0"&&j)return!0}return!1},B1=(G,Q)=>{let Y=G.nodeType===1?G:G.parentElement;while(Y){if(Z8(Y))return!0;if(Q&&Y===Q)break;Y=Y.parentElement}return!1};var y6=new Set(["computer-read-aloud","all"]),T6=new Set([...y6,"screen-reader"]),C6=new Set,v5=(G)=>{let Q=G.getAttribute?.("data-tts-suppress");if(Q===null||Q===void 0)return!1;let Y=Q.trim().toLowerCase();if(y6.has(Y))return!0;if(T6.has(Y))return!1;if(!C6.has(Y))C6.add(Y),console.warn(`[tts] data-tts-suppress="${Q}" is not one of ${Array.from(T6).join(", ")}; suppressing read-aloud for this content anyway, because a suppression attribute that fails open would leak the answer to items where reading is the construct. Correct the value to silence this.`);return!0},W1=(G,Q)=>{let Y=G.nodeType===1?G:G.parentElement;while(Y){if(v5(Y))return!0;if(Q&&Y===Q)break;Y=Y.parentElement}return!1},H7=(G,Q)=>B1(G,Q)||W1(G),j8=(G,Q)=>{if(typeof document>"u"||typeof document.createTreeWalker!=="function"||typeof NodeFilter>"u"||typeof G.intersectsNode!=="function")return{text:G.toString(),filtered:!1};let Y=[],J=!1,X=document.createTreeWalker(Q,NodeFilter.SHOW_TEXT),j=X.nextNode();while(j){let Z=j;if(G.intersectsNode(Z))if(H7(Z,Q))J=!0;else{let q=Z.textContent||"",B=Z===G.startContainer?G.startOffset:0,K=Z===G.endContainer?G.endOffset:q.length;Y.push(q.slice(B,K))}j=X.nextNode()}return{text:Y.join(""),filtered:J}},q8=(G,Q,Y)=>{if(!G||!Q)return!1;if(/\s/.test(G)||/\s/.test(Q))return!1;let J=Y?.boundarySpacingMode??"segmenterPreferred";if(J==="none")return!1;if(J==="segmenterPreferred")try{let Z=globalThis.Intl?.Segmenter;if(typeof Z==="function"){let q=new Z(Y?.locale,{granularity:"word"});if(Array.from(q.segment(`${G}${Q}`)).filter((W)=>W.isWordLike!==!1&&W.segment.trim().length>0).length>=2)return!0}}catch{}let X=/[A-Za-z0-9]/.test(G),j=/[A-Za-z0-9]/.test(Q);return X&&j},C7=(G,Q)=>{let Y=new Map;if(typeof document>"u"||typeof document.createTreeWalker!=="function"||typeof NodeFilter>"u")return{text:"",map:Y};let J=[],X=0,j=!0,Z=!1,q=null,B=null,K=document.createTreeWalker(G,NodeFilter.SHOW_TEXT),W=K.nextNode();while(W){let H=W;if(H.parentElement&&!H7(H,G)){let F=H.textContent||"",O=F.match(/\S/),L=O?O[0]:null;if(!j&&!Z&&q8(B,L,Q)){if(J.push(" "),q)Y.set(X,q);X++,Z=!0}for(let D=0;D<F.length;D++){let P=F[D],S=/\s/.test(P);if(j){if(!S)j=!1,J.push(P),Y.set(X,{node:H,offset:D}),q={node:H,offset:D},X++,Z=!1,B=P}else if(S){if(!Z)J.push(" "),Y.set(X,{node:H,offset:D}),q={node:H,offset:D},X++;Z=!0}else J.push(P),Y.set(X,{node:H,offset:D}),q={node:H,offset:D},X++,Z=!1,B=P}}W=K.nextNode()}let $=J.join("").trimEnd();while(Y.has($.length))Y.delete($.length);return{text:$,map:Y}};var h5=new Set(["speak","p","s","emphasis","prosody","say-as","voice","lang"]),x6=new Set(["audio","phoneme"]),k6=(G)=>G.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/ /g," ").replace(/ /g," ").replace(/&/g,"&"),K1=(G,Q,Y)=>{for(let J=0;J<Q.length;J++)G.push({char:Q[J],rawOffset:Y===null?null:Y+J})},m5=(G,Q,Y)=>{let J=Q.slice(Y).match(/^&(quot|apos|lt|gt|nbsp|amp|#160);/i);if(!J)return 0;return K1(G,k6(J[0]),Y),J[0].length},f6=(G)=>{G.push({char:" ",rawOffset:null})},u5=(G)=>{let Q=new Map,Y=[],J=!0;for(let X of G){if(/\s/.test(X.char)){if(!J&&Y.length>0){if(Y.push(" "),X.rawOffset!==null)Q.set(X.rawOffset,Y.length-1)}J=!0;continue}if(Y.push(X.char),X.rawOffset!==null)Q.set(X.rawOffset,Y.length-1);J=!1}while(Y.length>0&&Y[Y.length-1]===" ")Y.pop();for(let[X,j]of Q)if(j>=Y.length)Q.delete(X);return{text:Y.join(""),rawToSpokenOffsetMap:Q}},p5=(G)=>{return G.match(/^<\/?\s*([A-Za-z0-9:-]+)/)?.[1]?.toLowerCase()||""},g5=(G,Q)=>{let Y=new RegExp(`${Q}\\s*=\\s*("([^"]*)"|'([^']*)')`,"i"),J=G.match(Y);return k6(J?.[2]??J?.[3]??"")||null},_1=(G)=>{let Q=[],Y=!1,J=!1,X=0;while(X<G.length){let Z=G[X];if(Z!=="<"){if(Z==="&"){let H=m5(Q,G,X);if(H>0){X+=H;continue}}K1(Q,Z,X),X++;continue}let q=G.indexOf(">",X+1);if(q<0){K1(Q,Z,X),X++;continue}J=!0;let B=G.slice(X,q+1),K=p5(B),W=/^<\s*\//.test(B),$=/\/\s*>$/.test(B);if(!W&&K==="sub"){let H=g5(B,"alias");if(!H){Y=!0,X=q+1;continue}K1(Q,H,null);let N=G.toLowerCase().indexOf("</sub>",q+1);X=N>=0?N+6:q+1;continue}if(!W&&K==="break"){f6(Q),X=q+1;continue}if(!W&&x6.has(K)){if(Y=!0,$){X=q+1;continue}}if(K&&!h5.has(K)&&!x6.has(K)&&K!=="break"&&K!=="sub")Y=!0;if(!W&&(K==="p"||K==="s"))f6(Q);X=q+1}let j=u5(Q);return{spokenText:T(j.text),rawToSpokenOffsetMap:j.rawToSpokenOffsetMap,unsupportedSemantic:Y,hasMarkup:J}};var c5=U1(),u6=new Map([["zero","0"],["one","1"],["two","2"],["three","3"],["four","4"],["five","5"],["six","6"],["seven","7"],["eight","8"],["nine","9"],["ten","10"]]),l5=[{phrase:["plus","or","minus"],visible:"±",score:8},{phrase:["square","root"],visible:"√",score:8},{phrase:["divided","by"],visible:"/",score:7},{phrase:["all","over"],visible:"/",score:7},{phrase:["equals"],visible:"=",score:7},{phrase:["equal"],visible:"=",score:7},{phrase:["times"],visible:"",score:7},{phrase:["multiplied","by"],visible:"",score:7},{phrase:["over"],visible:"/",score:6},{phrase:["squared"],visible:"²",score:6},{phrase:["squared"],visible:"2",score:4},{phrase:["negative"],visible:"-",score:5},{phrase:["minus"],visible:"-",score:5},{phrase:["plus"],visible:"+",score:5}],U8=(G)=>{let Q=[];for(let Y of G.matchAll(c5)){let J=Y[0],X=Y.index??0;Q.push({text:J,normalized:J.toLowerCase(),start:X,end:X+J.length})}return Q},B8=(G)=>u6.get(G.normalized)||G.normalized,d5=(G,Q)=>{let Y=[];for(let J=0;J<G.length;J++){for(let X=0;X<Q.length;X++){let j=B8(G[J]),Z=B8(Q[X]);if(j===Z)Y.push({spokenStartToken:J,spokenEndToken:J+1,visibleToken:X,score:10})}for(let X of l5){let j=G.slice(J,J+X.phrase.length);if(j.length!==X.phrase.length)continue;if(!j.every((Z,q)=>Z.normalized===X.phrase[q]))continue;for(let Z=0;Z<Q.length;Z++){if(Q[Z].normalized!==X.visible)continue;Y.push({spokenStartToken:J,spokenEndToken:J+X.phrase.length,visibleToken:Z,score:X.score})}}}return Y},i5=(G,Q)=>{let Y=d5(G,Q).sort((B,K)=>G[B.spokenStartToken].start-G[K.spokenStartToken].start||Q[B.visibleToken].start-Q[K.visibleToken].start),J=Array(Y.length).fill(0),X=Array(Y.length).fill(-1);for(let B=0;B<Y.length;B++){let K=Y[B];J[B]=K.score;for(let W=0;W<B;W++){let $=Y[W];if($.spokenEndToken<=K.spokenStartToken&&$.visibleToken<K.visibleToken){let H=K.spokenStartToken-$.spokenEndToken,N=K.visibleToken-$.visibleToken-1,F=Math.max(0,Math.abs(H-N)-2),O=J[W]+K.score-F;if(O>J[B])J[B]=O,X[B]=W}}}let j=-1;for(let B=0;B<J.length;B++)if(j<0||J[B]>J[j])j=B;if(j<0)return[];let Z=[],q=j;while(q>=0)Z.unshift(Y[q]),q=X[q];return Z.map((B)=>{let K=G[B.spokenStartToken],W=G[B.spokenEndToken-1],$=Q[B.visibleToken];return{spokenStart:K.start,spokenEnd:W.end,visibleStart:$.start,visibleEnd:$.end,score:B.score}})},s5=(G,Q,Y)=>{if(G.length===0)return 0;let J=G.length/Math.max(1,Math.min(Q.length,Y.length)),X=G.reduce((j,Z)=>j+Z.score,0)/G.length/10;return Math.min(1,J*X)},V1=(G)=>{let Q=_1(G.speechText),Y=T(G.visibleText),J=Q.spokenText,X=U8(J),j=U8(Y),Z=Q.unsupportedSemantic?[]:i5(X,j),q=s5(Z,X,j),B=J===Y&&J.length>0,K=Z.length===1&&Z[0].score===10&&X.length<=2&&j.length<=2,W=Q.unsupportedSemantic?"region-fallback":B?"exact-word":Z.length>=2||K?q>=0.12?"anchor-span":"region-fallback":"region-fallback",$=Q.unsupportedSemantic?"unsupported":Q.hasMarkup?"raw-ssml":"plain-spoken-text";return{speechText:G.speechText,spokenText:J,visibleText:Y,playbackMode:W,boundaryOffsetMode:$,anchors:Z,confidence:q,spokenTokens:X,visibleTokens:j,rawToSpokenOffsetMap:Q.rawToSpokenOffsetMap}},W8=(G,Q)=>G.find((Y)=>Y.start<=Q&&Q<Y.end)||null,p6=(G)=>{if(!G)return null;if(/^<[^>]+>$/.test(G.trim()))return null;let Q=U8(G)[0];if(!Q)return null;return u6.get(Q.normalized)||Q.normalized},I6=(G,Q,Y)=>{let J=p6(Y);if(!Q||!J)return!1;let X=W8(G.spokenTokens,Q.start);if(!X)return!1;return B8(X)===J},v6=(G,Q)=>{let Y=G.rawToSpokenOffsetMap.get(Q);if(Y!==void 0)return Y;for(let J=Q;J<G.speechText.length;J++){let X=G.rawToSpokenOffsetMap.get(J);if(X!==void 0)return X;if(G.speechText[J]===">")break}return null},h6=(G,Q,Y)=>{let J=v6(G,Q);if(J===null)return null;let X=v6(G,Math.max(Q,Q+Y-1)),j=W8(G.spokenTokens,J),Z=X!==null&&X>=J?X-J+1:j?j.end-J:Y;return{start:J,length:Math.max(1,Z)}},m6=(G,Q,Y)=>{if(Q<0||Q>=G.spokenText.length)return null;let J=W8(G.spokenTokens,Q);if(!J)return null;return{start:Q,length:Math.min(Y,J.end-Q)}},g6=(G,Q,Y=1,J)=>{if(G.boundaryOffsetMode==="unsupported"||!Number.isFinite(Q))return null;let X=Math.max(1,Number.isFinite(Y)?Y:1);if(J&&/^<[^>]+>$/.test(J.trim()))return null;if(G.boundaryOffsetMode==="raw-ssml"){let j=h6(G,Q,X),Z=m6(G,Q,X);if(J){if(I6(G,j,J))return j;if(I6(G,Z,J))return Z;if(p6(J))return null}return j||Z}return m6(G,Q,X)||h6(G,Q,X)},c6=(G,Q)=>{if(G.playbackMode==="region-fallback")return null;let Y=G.anchors.find((j)=>j.spokenStart<=Q&&Q<j.spokenEnd);if(Y)return{start:Y.visibleStart,end:Y.visibleEnd};let J=null,X=null;for(let j of G.anchors){if(j.spokenEnd<=Q){J=j;continue}if(j.spokenStart>Q){X=j;break}}if(J&&X)return{start:Math.min(J.visibleStart,X.visibleStart),end:Math.max(J.visibleEnd,X.visibleEnd)};return null};var n5=new Map([["+",["plus"]],["-",["minus","negative"]],["−",["minus","negative"]],["×",["times","multiplied by"]],["÷",["divided by"]],["=",["equals","equal to"]],["≠",["is not equal to","not equal to"]],["≈",["approximately equals"]],["≤",["less than or equal to"]],["≥",["greater than or equal to"]],["<",["less than"]],[">",["greater than"]],["∠",["angle"]],["△",["triangle"]],["□",["box"]],["○",["circle"]],["°",["degrees","degree"]],["%",["percent"]],["'",["prime"]],["′",["prime"]],["•",["times"]],["·",["times"]],["",["times","multiplied by"]]]),r5=new Map([["","function-application"],["","implicit-multiply"],["","invisible-separator"],["","invisible-plus"]]),l6=new Map([["2",["squared"]],["3",["cubed"]]]),o5=new Map([["msqrt","radical"],["mroot","radical"],["msub","subscript"],["msubsup","subsupscript"],["munder","underscript"],["mover","overscript"],["munderover","underoverscript"],["mmultiscripts","multiscript"],["menclose","enclosure"]]),a5=(G)=>G.replace(/\s+/g," ").trim(),D7=(G)=>(G.localName||G.tagName||"").toLowerCase(),t5=(G)=>G.nodeType===Node.ELEMENT_NODE,y7=(G)=>Array.from(G.childNodes).filter(t5),K8=(G)=>a5(G.textContent||""),Q7=(G,Q)=>({type:"element-range",quality:Q,element:G}),e5=(G)=>{switch(G){case"mi":return"identifier";case"mn":return"number";case"mo":return"operator";case"mtext":case"ms":return"text";case"mspace":return"space";default:return"unknown"}},GG=(G,Q)=>{if(Q==="operator"){if(G==="−")return"-";return G}return G.toLowerCase()},QG=(G,Q,Y)=>{if(Y==="fraction")return["over","divided by"];if(Y==="superscript")return l6.get(G)??[];if(G==="|")return["absolute value"];if(Q==="operator")return n5.get(G)||[];return[]},A7=(G)=>{let Q=G.normalized??GG(G.text,G.kind||"unknown");return{id:`math-token-${G.state.nextId++}`,kind:G.kind,role:G.role,text:G.text,normalized:Q,spokenAliases:QG(G.text,G.kind,G.role),sourceElement:G.sourceElement,path:G.path,target:G.target||Q7(G.sourceElement,"element-range"),optional:G.optional}},N7=(G,Q,Y="tokens")=>{G[Y].push(Q)},d6=(G,Q,Y)=>{y7(G).forEach((J,X)=>Y7(J,Q,`${Y}/${D7(J)}[${X}]`))},YG=(G,Q,Y)=>{let J=y7(G);if(J[0])Y7(J[0],Q,`${Y}/numerator`);if(N7(Q,A7({state:Q,kind:"structure",role:"fraction",text:"/",sourceElement:G,path:Y,target:Q7(G,"element-range")})),J[1])Y7(J[1],Q,`${Y}/denominator`)},JG=(G,Q,Y)=>{let J=G.getAttribute("open")||"(",X=G.getAttribute("close")||")";N7(Q,A7({state:Q,kind:"operator",role:J==="|"?"absolute-value-fence":"open-fence",text:J,sourceElement:G,path:`${Y}/open`,target:Q7(G,"element-range")})),d6(G,Q,Y),N7(Q,A7({state:Q,kind:"operator",role:X==="|"?"absolute-value-fence":"close-fence",text:X,sourceElement:G,path:`${Y}/close`,target:Q7(G,"element-range")}))},XG=(G,Q,Y)=>{let J=y7(G);if(J[0])Y7(J[0],Q,`${Y}/base`);let X=J[1];if(!X)return;let j=K8(X);if(l6.has(j)){N7(Q,A7({state:Q,kind:"structure",role:"superscript",text:j,normalized:j,sourceElement:X,path:`${Y}/exponent`,target:Q7(G,"element-range")}));return}Y7(X,Q,`${Y}/exponent`)},ZG=(G,Q,Y,J)=>{N7(Q,A7({state:Q,kind:"structure",role:J,text:K8(G)||J,normalized:`\x00${J}`,sourceElement:G,path:Y,target:Q7(G,"element-range")}))},jG=(G,Q,Y)=>{let J=0;for(let X of y7(G)){if(D7(X)==="mtr"||D7(X)==="mlabeledtr")J++,N7(Q,A7({state:Q,kind:"layout",role:"table-row",text:`row-${J}`,normalized:`row-${J}`,sourceElement:X,path:`${Y}/row[${J}]`,target:Q7(X,"region-fallback")}),"layoutTargets");Y7(X,Q,`${Y}/${D7(X)}[${J}]`)}},qG=(G,Q,Y)=>{let J=K8(G);if(!J)return;let X=e5(D7(G)),j=X==="operator"?r5.get(J):void 0,Z=j??(X==="operator"&&(J==="("||J===")")?"grouping-fence":X);N7(Q,A7({state:Q,kind:X,role:Z,text:J,sourceElement:G,path:Y,target:j&&G.parentElement?Q7(G.parentElement,"region-fallback"):void 0,optional:Boolean(j)||Z==="grouping-fence"}))},Y7=(G,Q,Y)=>{let J=D7(G);switch(J){case"annotation":case"annotation-xml":return;case"semantics":{let X=y7(G).find((j)=>{let Z=D7(j);return Z!=="annotation"&&Z!=="annotation-xml"});if(X)Y7(X,Q,`${Y}/presentation`);return}case"mi":case"mn":case"mo":case"mtext":case"ms":case"mspace":qG(G,Q,Y);return;case"mfrac":YG(G,Q,Y);return;case"msup":XG(G,Q,Y);return;case"mfenced":JG(G,Q,Y);return;case"mtable":jG(G,Q,Y);return;case"mphantom":return;case"maction":{let X=y7(G)[0];if(X)Y7(X,Q,`${Y}/action`);return}default:{let X=o5.get(J);if(X){ZG(G,Q,Y,X);return}d6(G,Q,Y)}}},i6=(G)=>{let Q={tokens:[],layoutTargets:[],nextId:0};return Y7(G,Q,"/math"),{tokens:Q.tokens,layoutTargets:Q.layoutTargets,expressionTarget:Q7(G,"region-fallback")}};var s6=(G)=>{if(!G.boundary)return null;return G.alignment.segments.find((Y)=>Y.speechTokenIds.includes(G.boundary.token.id))?.target||null};var UG=(G)=>{let Q=[],Y=new Set,J=(X)=>{let j=X.toLowerCase().trim().split(/\s+/).filter(Boolean);if(j.length===0)return;let Z=j.join(" ");if(Y.has(Z))return;Y.add(Z),Q.push(j)};J(G.normalized);for(let X of G.spokenAliases)J(X);return Q},n6=(G,Q,Y)=>{let J=0;for(let X of Y){if(X.length<=J)continue;let j=!0;for(let Z=0;Z<X.length;Z++){let q=G[Q+Z];if(!q||q.normalized.toLowerCase()!==X[Z]){j=!1;break}}if(j)J=X.length}return J},BG=(G,Q)=>{let Y=[],J=0;for(let X of Q){let j=UG(X);if(X.optional){let Z=n6(G,J,j);if(Z>0)Y.push({speechTokens:G.slice(J,J+Z),math:X}),J+=Z;continue}while(J<G.length){let Z=n6(G,J,j);if(Z>0){Y.push({speechTokens:G.slice(J,J+Z),math:X}),J+=Z;break}J++}}return Y},WG=(G,Q,Y)=>{let J=Y.filter((Z)=>!Z.optional).length,X=G.filter((Z)=>!Z.math.optional).length,j=G.reduce((Z,q)=>Z+q.speechTokens.length,0);return J>0&&X===J&&j===Q.length},KG=(G)=>G.map(({speechTokens:Q,math:Y})=>({speechTokenIds:Q.map((J)=>J.id),mathTokenIds:[Y.id],score:1,confidence:1,target:Y.target})),r6=(G)=>{let Q=G.minExactWordConfidence??0.95,Y=BG(G.speech.tokens,G.math.tokens),J=WG(Y,G.speech.tokens,G.math.tokens)?1:0;return{segments:J>=Q?KG(Y):[],confidence:J,fallbackTarget:G.math.expressionTarget}};var o6=U1(),_G=new Map([["zero","0"],["one","1"],["two","2"],["three","3"],["four","4"],["five","5"],["six","6"],["seven","7"],["eight","8"],["nine","9"],["ten","10"]]),a6=(G)=>{let Q=G.toLowerCase();return _G.get(Q)||Q},VG=(G)=>{let Q=[];for(let Y of G.matchAll(o6)){let J=Y[0],X=Y.index??0;Q.push({id:`speech-token-${Q.length}`,text:J,normalized:a6(J),start:X,end:X+J.length,sourceStart:X,sourceEnd:X+J.length,coordinateSystem:"normalized-speech"})}return Q},F7=(G)=>{let Q=_1(G.speechText);return{speechText:G.speechText,spokenText:Q.spokenText,tokens:VG(Q.spokenText),rawToSpokenOffsetMap:Q.rawToSpokenOffsetMap,boundaryOffsetSpace:Q.unsupportedSemantic?"unsupported":Q.hasMarkup?"raw-ssml":"plain-spoken-text",unsupportedSemantic:Q.unsupportedSemantic,hasMarkup:Q.hasMarkup}},$8=(G)=>{if(!G)return null;if(/^<[^>]+>$/.test(G.trim()))return null;let Q=G.match(o6);if(!Q?.[0])return null;return a6(Q[0])},$G=(G,Q)=>G.find((Y)=>Y.start<=Q&&Q<Y.end)||null,HG=(G,Q)=>{let Y=G.rawToSpokenOffsetMap.get(Q);if(Y!==void 0)return Y;for(let J=Q;J<G.speechText.length;J++){let X=G.rawToSpokenOffsetMap.get(J);if(X!==void 0)return X;if(G.speechText[J]===">")break}return null},_8=(G,Q,Y)=>{if(Q===null)return null;let J=$G(G.tokens,Q);if(!J)return null;return{token:J,start:Q,length:Math.max(1,Math.min(Y,J.end-Q)),confidence:0.75}},V8=(G,Q)=>{let Y=$8(Q);return Boolean(G&&Y&&G.token.normalized===Y)},H8=(G)=>{if(G.tokenization.boundaryOffsetSpace==="unsupported"||!Number.isFinite(G.position)||G.boundaryWord&&/^<[^>]+>$/.test(G.boundaryWord.trim()))return null;let Q=Math.max(1,Number.isFinite(G.length)?G.length:1),Y=_8(G.tokenization,HG(G.tokenization,G.position),Q),J=_8(G.tokenization,G.position>=0&&G.position<G.tokenization.spokenText.length?G.position:null,Q);if(V8(Y,G.boundaryWord))return{...Y,confidence:1};if(V8(J,G.boundaryWord))return{...J,confidence:1};if(G.boundaryWord&&$8(G.boundaryWord))return null;return G.tokenization.boundaryOffsetSpace==="raw-ssml"?Y||J:J||Y},t6=(G)=>{if(G.tokenization.boundaryOffsetSpace==="unsupported"||!Number.isFinite(G.position)||G.boundaryWord&&/^<[^>]+>$/.test(G.boundaryWord.trim()))return null;let Q=Math.max(1,Number.isFinite(G.length)?G.length:1),Y=_8(G.tokenization,G.position>=0&&G.position<G.tokenization.spokenText.length?G.position:null,Q);if(V8(Y,G.boundaryWord))return{...Y,confidence:1};if(G.boundaryWord&&$8(G.boundaryWord))return null;return Y};var x7=(G)=>{let Q=F7({speechText:G.speechText}),Y=i6(G.mathElement);return{speech:Q,math:Y,result:r6({speech:Q,math:Y})}};var e6=(G,Q)=>{let Y=t6({tokenization:G.speech,position:Q.position,length:Q.length,boundaryWord:Q.boundaryWord});return s6({alignment:G.result,boundary:Y})},G0=(G,Q)=>{if(!Q.boundaryWord||/^<[^>]+>$/.test(Q.boundaryWord.trim()))return null;let Y=F7({speechText:Q.boundaryWord}).tokens[0];if(!Y)return null;let J=G.math.tokens.filter((X)=>{let j=Y.normalized.toLowerCase();return X.normalized.toLowerCase()===j||X.spokenAliases.some((Z)=>Z.toLowerCase()===j)});return J.length===1?J[0].target:null};var DG=new Set(["math","maction","menclose","merror","mfenced","mfrac","mi","mmultiscripts","mn","mo","mover","mpadded","mphantom","mprescripts","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msubsup","msup","mtable","mtd","mtext","mtr","munder","munderover","none","semantics","annotation","annotation-xml"]),AG=new Set(["accent","accentunder","align","bevelled","class","close","columnalign","columnlines","columnspacing","columnspan","denomalign","depth","dir","display","encoding","fence","height","href","id","largeop","length","linethickness","lspace","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","width","xmlns","xml:lang"]),Q0=(G)=>G.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),NG=(G)=>Q0(G).replace(/"/g,"""),FG=(G,Q)=>{let Y=G.toLowerCase(),J=Q.trim().toLowerCase();if(Y.startsWith("on"))return!0;if(!AG.has(Y))return!0;if(J.includes("javascript:"))return!0;if(J.includes("data:text/html"))return!0;return!1},MG=(G)=>{let Q=G.localName.toLowerCase();if(!DG.has(Q))return!1;let Y=G.namespaceURI;return!Y||Y==="http://www.w3.org/1998/Math/MathML"||Y==="http://www.w3.org/1999/xhtml"},Y0=(G)=>{if(G.nodeType===Node.TEXT_NODE)return Q0(G.textContent||"");if(G.nodeType===Node.COMMENT_NODE)return"";if(G.nodeType!==Node.ELEMENT_NODE)return null;let Q=G;if(!MG(Q))return null;let Y=Q.localName.toLowerCase(),J=[];for(let Z of Array.from(Q.attributes)){let q=Z.name.toLowerCase();if(FG(q,Z.value))continue;if(q==="xmlns"&&Z.value!=="http://www.w3.org/1998/Math/MathML")return null;J.push(`${q}="${NG(Z.value)}"`)}if(Y==="math"&&!J.some((Z)=>Z.startsWith("xmlns=")))J.unshift('xmlns="http://www.w3.org/1998/Math/MathML"');let X=[];for(let Z of Array.from(Q.childNodes)){let q=Y0(Z);if(q===null)return null;X.push(q)}let j=J.length>0?` ${J.join(" ")}`:"";return`<${Y}${j}>${X.join("")}</${Y}>`},zG=(G)=>{if(typeof DOMParser<"u")return new DOMParser().parseFromString(G,"application/xml");return null},$1=(G)=>{let Q=String(G||"").trim();if(!Q)return null;let Y=zG(Q);if(!Y)return null;if(Y.getElementsByTagName("parsererror").length>0)return null;let J=Y.documentElement;if(!J||J.localName.toLowerCase()!=="math")return null;return Y0(J)};var J0=(G)=>({chars:[],map:new Map,position:0,inLeadingWhitespace:!0,lastCharWasWhitespace:!1,lastMapped:null,options:G}),X0=(G)=>G.classList?.contains("MathJax")||G.tagName?.toLowerCase()==="mjx-container",Z0=(G)=>G.tagName?.toLowerCase()==="mjx-assistive-mml",j0=(G)=>{let Q=G.tagName?.toLowerCase();return Q==="annotation"||Q==="annotation-xml"},OG=(G)=>{let Q=G.getAttribute("data-mathml");return Q&&Q.trim()?Q:null},PG=(G)=>{return G.querySelector("mjx-assistive-mml math")?.outerHTML||null},LG=(G)=>{if(G.tagName.toLowerCase()==="math")return $1(G.outerHTML);let Q=OG(G);if(Q){let Y=$1(Q);if(Y)return Y}if(X0(G)){let Y=PG(G);if(Y){let J=$1(Y);if(J)return J}}return null};var wG=new Set(["P","H1","H2","H3","H4","H5","H6","LI","TD","TH","DD","DT","FIGCAPTION","LABEL","BUTTON"]),RG=new Set(["heading","listitem","option","radio","row","cell","columnheader","rowheader"]),EG=(G,Q)=>{let Y=G.parentElement,J=null;while(Y&&Y!==Q){let X=(Y.getAttribute("role")||"").toLowerCase(),j=Y.tagName.toUpperCase();if(wG.has(j)||RG.has(X)){J=Y;break}Y=Y.parentElement}return J||Q},bG=(G)=>Boolean(typeof G.querySelector==="function"&&G.querySelector("math, [data-mathml], .MathJax, mjx-container, mjx-assistive-mml"))||G.tagName?.toLowerCase()==="math"||G.hasAttribute?.("data-mathml")||X0(G),M7=(G,Q,Y)=>{if(/[.,;:!?]/.test(Q)&&G.chars.length>0&&G.chars[G.chars.length-1]===" ")G.chars.pop(),G.position--,G.map.delete(G.position);if(G.chars.push(Q),Y)G.map.set(G.position,Y),G.lastMapped=Y;else if(G.lastMapped)G.map.set(G.position,G.lastMapped);G.position++},q0=(G,Q)=>{if(G.inLeadingWhitespace||G.lastCharWasWhitespace||G.chars.length===0)return!1;let Y=G.chars[G.chars.length-1];return q8(Y,Q,G.options)},U0=(G,Q)=>{let Y=Q.textContent||"",J=!1;for(let X=0;X<Y.length;X++){let j=Y[X],Z=/\s/.test(j);if(G.inLeadingWhitespace){if(!Z)G.inLeadingWhitespace=!1,M7(G,j,{node:Q,offset:X}),J=!0,G.lastCharWasWhitespace=!1;continue}if(Z){if(!G.lastCharWasWhitespace)M7(G," ",{node:Q,offset:X});G.lastCharWasWhitespace=!0;continue}if(!J&&q0(G,j))M7(G," ",{node:Q,offset:X});M7(G,j,{node:Q,offset:X}),J=!0,G.lastCharWasWhitespace=!1}},SG=(G,Q)=>{for(let Y=0;Y<Q.text.length;Y++){let J=Q.text[Y],X=/\s/.test(J),j=Q.map.get(Y)||null,Z=j?.node||G.lastMapped?.node||null,q=j?.offset??G.lastMapped?.offset??0,B=j?{node:j.node,offset:j.offset}:Z?{node:Z,offset:q}:null;if(G.inLeadingWhitespace){if(X)continue;G.inLeadingWhitespace=!1}if(X){if(!G.lastCharWasWhitespace)M7(G," ",B);G.lastCharWasWhitespace=!0;continue}if(Y===0&&q0(G,J))M7(G," ",B);if(M7(G,J,B),G.lastCharWasWhitespace=!1,j)G.map.set(G.position-1,{node:j.node,offset:j.offset}),G.lastMapped={node:j.node,offset:j.offset};else if(Z)G.map.set(G.position-1,{node:Z,offset:q})}},TG=(G)=>{if(typeof DOMParser>"u")return"";let Q=new DOMParser().parseFromString(G,"application/xml");if(Q.getElementsByTagName("parsererror").length>0)return"";let Y=[],J=(X)=>{if(X.nodeType===3){let Z=X.textContent||"";if(Z.trim())Y.push(Z);return}if(X.nodeType!==1)return;let j=X;if(j0(j))return;for(let Z of Array.from(j.childNodes))J(Z)};return J(Q.documentElement),T(Y.join(" "))},CG=(G,Q,Y)=>{let J=J0(Y),X=(q)=>{if(H7(q,G))return;if(q.nodeType===3){U0(J,q);return}if(q.nodeType!==1)return;let B=q;if(Z0(B)||j0(B))return;for(let K of Array.from(B.childNodes))X(K)};X(G),B0(J);let j=T(J.chars.join(""));if(j)return{text:j,map:J.map};let Z=TG(Q);if(!Z)return C7(G,Y);return{text:Z,map:new Map}},B0=(G)=>{while(G.chars.length>0&&/\s/.test(G.chars[G.chars.length-1]))G.chars.pop(),G.position--,G.map.delete(G.position)},yG=(G,Q)=>{let Y=J0(Q),J=[],X=0,j,Z=!1,q=()=>{let W=T(Y.chars.slice(X,Y.chars.length).join(""));if(W)J.push({type:"text",text:W,sourceElement:j});X=Y.chars.length,j=void 0},B=(W)=>{if(H7(W,G))return;if(W.nodeType===Node.TEXT_NODE){let N=EG(W,G);if(j&&N!==j)q();j=N,U0(Y,W);return}if(W.nodeType!==Node.ELEMENT_NODE)return;let $=W;if(Z0($))return;let H=LG($);if(H){q();let N=CG($,H,Q);SG(Y,N);let F=T(N.text);J.push({type:"math",mathml:H,fallbackText:F,sourceElement:$}),X=Y.chars.length,Z=!0;return}for(let N of Array.from($.childNodes))B(N)};for(let W of Array.from(G.childNodes))B(W);B0(Y),q();let K=Y.chars.join("");while(Y.map.has(K.length))Y.map.delete(K.length);return{visibleText:K,map:Y.map,chunks:J,containsMathMarkup:Z}},z7=(G,Q)=>{if(!bG(G)){let{text:Y,map:J}=C7(G,Q);return{visibleText:Y,map:J,chunks:Y?[{type:"text",text:Y}]:[],containsMathMarkup:!1}}return yG(G,Q)};var D8=null,W0=Promise.resolve(),fG=(G)=>(G||"en").split("-")[0].toLowerCase()||"en",kG=async()=>{if(!D8)D8=import("speech-rule-engine").then((G)=>{let Q=G.default||G;if(!Q||typeof Q.toSpeech!=="function")throw Error("speech-rule-engine did not expose toSpeech");return Q});return D8},IG=(G)=>G==="en"?"clearspeak":"mathspeak",K0=(G)=>!!G&&typeof G==="object"&&!Array.isArray(G),_0=(G)=>typeof G==="string"&&G.trim()?G.trim():void 0,O7=(G)=>{if(!K0(G))return;let Q=_0(G.domain),Y=_0(G.style),J=K0(G.engineOptions)?G.engineOptions:void 0;if(!Q&&!Y&&!J)return;return{...Q?{domain:Q}:{},...Y?{style:Y}:{},...J?{engineOptions:J}:{}}},vG=async(G,Q,Y,J)=>{let X=fG(Q),j=O7(J);await G.setupEngine?.({...j?.engineOptions||{},locale:X,domain:j?.domain||IG(X),...j?.style?{style:j.style}:{},modality:"speech",markup:Y}),await G.engineReady?.()},hG=async(G)=>{let Q=W0.then(G,G);return W0=Q.then(()=>{return},()=>{return}),Q},V0=async(G,Q,Y,J,X)=>hG(async()=>{return await vG(G,Y,J,X),G.toSpeech(Q)}),mG=(G)=>G.replace(/^\s*<\?xml[^>]*\?>\s*/i,""),uG=async(G,Q,Y,J)=>{try{let X=mG(await V0(G,Q,Y,"ssml",J));return X.includes("<speak")?X:null}catch(X){return console.debug("[TTSService] Math SSML generation failed; using plain",{message:X instanceof Error?X.message:String(X)}),null}},H1=async(G,Q={})=>{if(!G.some((K)=>K.type==="math"))return{speechText:T(G.map((K)=>K.type==="text"?K.text:K.fallbackText).join(" ")),usedMathSpeech:!1,usedFallback:!1};let Y=null,J=!1,X=!1,j=Q.loadSre||kG,Z=[];for(let K of G){if(K.type==="text"){Z.push(K.text);continue}try{if(!Y)Y=await j();let W=T(await V0(Y,K.mathml,Q.language,"none",Q.mathSpeech));if(W){Z.push(W),J=!0;continue}X=!0,Z.push(K.fallbackText)}catch(W){X=!0,console.debug("[TTSService] Math speech generation failed; using visible fallback",{message:W instanceof Error?W.message:String(W)}),Z.push(K.fallbackText)}}let q=T(Z.join(" ")),B;if(Q.produceSsml&&Y&&J&&G.length===1&&G[0].type==="math")B=await uG(Y,G[0].mathml,Q.language,Q.mathSpeech)??void 0;return{speechText:q,usedMathSpeech:J,usedFallback:X,ssml:B}};var pG=(G,Q)=>H1([G],Q),gG=(G)=>(G||"en").split("-")[0].toLowerCase()||"en",cG=new Set(["H1","H2","H3","H4","H5","H6","LI","LABEL","BUTTON"]),lG=new Set(["heading","listitem","option","radio"]),dG=(G)=>{if(G.type!=="text"||!G.sourceElement)return!1;let Q=G.sourceElement.tagName.toUpperCase(),Y=(G.sourceElement.getAttribute("role")||"").toLowerCase();return cG.has(Q)||lG.has(Y)},A8=async(G)=>{let Q=G.resolveMathSpeech??pG,{visibleText:Y}=G,J=[],X=0,j=(q)=>{let B=T(q),K=Y.indexOf(B,X),W=K>=0?K:X,$=W+B.length;return X=$,{start:W,end:$}},Z=[];for(let q=0;q<G.chunks.length;q++){let B=G.chunks[q];if(B.type==="text"){let N=dG(B)?[{text:B.text,offset:0}]:S7(B.text,{locale:G.language});for(let F of N){let O=T(F.text);if(!O)continue;let L=j(O);J.push({sourceChunkIndex:q,segment:{kind:"prose",spokenText:O,visibleText:O,visibleSpan:L}}),Z.push(O)}continue}let K=j(B.fallbackText),W=await Q(B,{language:G.language,produceSsml:G.produceSsml,mathSpeech:G.mathSpeech}),$=!W.speechText,H=W.speechText||B.fallbackText;J.push({sourceChunkIndex:q,segment:{kind:"math",spokenText:H,mathml:B.mathml,fallbackText:B.fallbackText,visibleSpan:K,usedFallback:$,ssml:W.ssml}}),Z.push(H)}return{segments:J,locale:gG(G.language),visibleText:Y,plainSpeechText:T(Z.join(" "))}};var iG=(G)=>(G||"en").split("-")[0].toLowerCase()||"en",sG="sre-v1",nG=256,N8=(G)=>{if(Array.isArray(G))return`array:[${G.map(N8).join(",")}]`;if(G&&typeof G==="object")return`object:{${Object.entries(G).sort(([Q],[Y])=>Q.localeCompare(Y)).map(([Q,Y])=>`${JSON.stringify(Q)}:${N8(Y)}`).join(",")}}`;if(G===null)return"null:null";if(typeof G>"u")return"undefined:";if(typeof G==="function")return`function:${G.name||"anonymous"}`;if(typeof G==="symbol")return`symbol:${String(G)}`;if(typeof G==="bigint")return`bigint:${G.toString()}`;if(typeof G==="number")return Number.isFinite(G)?`number:${G}`:`number:${String(G)}`;return`${typeof G}:${JSON.stringify(G)}`},$0=(G,Q,Y,J)=>`${sG}\x00${iG(G)}\x00${Q?"ssml":"plain"}\x00${N8(Y??null)}\x00${J}`,F8=(G={})=>{let Q=Math.max(1,G.maxEntries??nG),Y=G.resolve??((j,Z)=>H1([j],Z)),J=new Map,X=(j,Z)=>{J.delete(j),J.set(j,Z);while(J.size>Q){let q=J.keys().next().value;if(q!==void 0)J.delete(q)}};return async(j,Z)=>{let q=O7(Z.mathSpeech),B=Z.produceSsml===!0,K=$0(Z.language,B,q,j.mathml),W=J.get(K);if(W)return J.delete(K),J.set(K,W),W;let $=await Y(j,{...Z,mathSpeech:q});if(B&&$.ssml&&Q>1)X($0(Z.language,!1,q,j.mathml),{speechText:$.speechText,usedMathSpeech:$.usedMathSpeech,usedFallback:$.usedFallback});return X(K,$),$}};var rG=(G)=>{if(!G||/^<[^>]+>$/.test(G.trim()))return null;return F7({speechText:G}).tokens[0]?.normalized||null},oG=(G,Q)=>{let Y=F7({speechText:G.speechText});if(!Number.isFinite(Q.position))return{boundary:null,spokenText:Y.spokenText};let J=H8({tokenization:Y,position:Q.position,length:Q.length,boundaryWord:Q.word});return{boundary:J?{start:J.start,length:J.length}:null,spokenText:Y.spokenText}},aG=(G,Q,Y)=>{if(!Y)return!0;return F7({speechText:G}).tokens.find((X)=>X.start<=Q&&Q<X.end)?.normalized===Y},H0=(G,Q)=>{let Y=rG(Q.word);if(G.id!==Q.chunkId)return{chunkId:Q.chunkId,normalizedWord:Y,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"boundary chunk id did not match highlight chunk"};if(Q.providerOffsetSpace==="unknown"||G.offsetSpace==="unsupported")return{chunkId:G.id,normalizedWord:Y,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"boundary offset space is unsupported"};let J,X;if(G.catalogAlignment)J=g6(G.catalogAlignment,Q.position,Q.length,Q.word),X=G.catalogAlignment.spokenText;else{let j=oG(G,Q);J=j.boundary,X=j.spokenText}if(!J)return{chunkId:G.id,normalizedWord:Y,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"could not resolve provider boundary to chunk speech"};if(!aG(X,J.start,Y))return{chunkId:G.id,normalizedWord:Y,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"could not resolve provider boundary to matching word"};return{chunkId:G.id,normalizedWord:Y,chunkSpokenStart:J.start,chunkSpokenEnd:J.start+J.length,confidence:Y?1:0.75,reason:G.catalogAlignment?"resolved through catalog alignment":"resolved through speech tokenization"}};var P7=(G)=>{if(G.semanticTarget)return{activeTarget:G.semanticTarget,regionTarget:G.regionTarget,quality:G.semanticTarget.quality==="exact-word"?"exact-word":G.semanticTarget.quality==="expression"?"expression":"semantic-token",confidence:G.confidence,reason:G.reason};if(G.expressionTarget)return{activeTarget:G.expressionTarget,regionTarget:G.regionTarget,quality:"expression",confidence:G.confidence,reason:G.reason};return{activeTarget:null,regionTarget:G.regionTarget,quality:"region",confidence:G.confidence,reason:G.reason}};var A0=new Map([["mi","mjx-mi"],["mn","mjx-mn"],["mo","mjx-mo"],["mtext","mjx-mtext"]]),M8="mi,mn,mo,mtext",N0="mjx-mi,mjx-mn,mjx-mo,mjx-mtext",F0=["mjx-mfrac","mjx-msqrt","mjx-mroot","mjx-mtable","mjx-munder","mjx-mover","mjx-munderover"].join(","),M0=(G)=>{if(G.type==="text-range")return G.node.parentElement;return G.element},D1=(G)=>{let Q=G;while(Q){if(Q.localName?.toLowerCase()==="mjx-container")return Q;Q=Q.parentElement}return null},D0=(G)=>{if(!G)return!1;if(D1(G))return!1;return!B1(G)},z0=(G)=>{let Q=G.getBoundingClientRect?.();return Boolean(Q&&Q.width>0&&Q.height>0)},z8=(G)=>{let Q=G;while(Q){if(Q.localName?.toLowerCase()==="math")return Q;Q=Q.parentElement}return null},O0=(G,Q)=>{if(G.length===0)return!1;if(G.length!==Q.length)return!1;for(let Y=0;Y<G.length;Y+=1){let J=A0.get(G[Y].localName.toLowerCase());if(!J)return!1;if(Q[Y].localName.toLowerCase()!==J)return!1}return!0},tG=(G,Q)=>{if(!G)return null;if(!A0.has(G.localName.toLowerCase()))return null;if(Q.querySelector(F0))return null;let Y=z8(G),J=Q.querySelector("mjx-math");if(!Y||!J)return null;let X=Array.from(Y.querySelectorAll(M8)),j=X.indexOf(G);if(j<0)return null;let Z=Array.from(J.querySelectorAll(N0));if(!O0(X,Z))return null;let q=Z[j];if(!q||!z0(q))return null;return q},P0=(G)=>{let Q=D1(G);if(Q){if(Q.querySelector(F0))return"expression";let X=z8(G)??G,j=Q.querySelector("mjx-math");if(!j)return"expression";let Z=Array.from(X.querySelectorAll(M8)),q=Array.from(j.querySelectorAll(N0));if(!O0(Z,q))return"expression";return q.some((B)=>z0(B))?"token":"expression"}let Y=z8(G)??G;return Array.from(Y.querySelectorAll(M8)).some((X)=>!B1(X))?"token":"expression"},O8=(G)=>{let Q=M0(G),Y=D1(Q);if(Y){let J=tG(Q,Y);if(J)return{type:"element",quality:"semantic-token",element:J};return{type:"element",quality:"expression",element:Y}}if(G.type==="text-range"){if(!D0(G.node.parentElement))return null;return{type:"text-range",quality:"semantic-token",node:G.node,startOffset:G.startOffset,endOffset:G.endOffset}}if(!D0(G.element))return null;return{type:"element",quality:G.quality==="region-fallback"?"expression":"semantic-token",element:G.element}},L0=O8,w0=()=>{let G=new WeakMap;return(Q)=>{let Y=M0(Q),J=D1(Y);if(!Y||!J)return O8(Q);if(G.has(Y))return G.get(Y)??null;let X=O8(Q);return G.set(Y,X),X}};var R0=(G,Q,Y,J=G.mathAlignments,X=L0)=>{if(Q.chunkSpokenStart===null||Q.chunkSpokenEnd===null)return null;let j=null;for(let Z of J){let q=e6(Z.alignment,{position:Q.chunkSpokenStart,length:Math.max(1,Q.chunkSpokenEnd-Q.chunkSpokenStart),boundaryWord:Y.word})||G0(Z.alignment,{boundaryWord:Y.word});if(!q)continue;let B=X(q);if(!B)continue;if(B.quality==="semantic-token")return B;j??=B}return j};var A1=(G,Q,Y)=>{if(!G||typeof document>"u")return null;if(Y<=Q)return null;let J=G.get(Q),X=G.get(Math.max(Q,Y-1));if(!J)return null;if(!X)X=J;try{let j=document.createRange();return j.setStart(J.node,J.offset),j.setEnd(X.node,X.offset+1),j}catch{return null}};var E0=(G,Q)=>{if(!G.catalogAlignment||Q.chunkSpokenStart===null)return null;let Y=c6(G.catalogAlignment,Q.chunkSpokenStart);if(!Y)return null;let J=A1(G.visibleMap,Y.start,Y.end);if(!J)return null;return{type:"range",quality:G.catalogAlignment.playbackMode==="exact-word"?"exact-word":"semantic-token",range:J}};var eG=(G)=>G.regionRange?{type:"range",quality:"region",range:G.regionRange}:G.regionElement?{type:"element",quality:"region",element:G.regionElement}:null,b0=(G,Q=G.chunk.mathAlignments)=>{if(Q.length!==1)return null;let Y=Q[0]?.alignment.result.fallbackTarget;return Y?G.renderedMathTargetResolver(Y):null},GQ=(G,Q)=>{if(!G)return Q.mathAlignments;return Q.mathAlignments.filter(({element:Y})=>{try{if(G.type==="range")return G.range.intersectsNode(Y);if(G.type==="element")return G.element===Y||G.element.contains(Y);return G.node.parentElement?.contains(Y)||!1}catch{return!1}})},S0=()=>({activeTarget:null,regionTarget:null,quality:"region",confidence:0,reason:"boundary chunk id was not found"}),T0=(G)=>G.length===1?G[0].element:null,QQ=(G,Q)=>Q.length>0&&Q.every(({element:Y})=>G.mathCapabilityByElement.get(Y)==="token"),YQ=3,JQ=(G,Q,Y)=>{if(!Q||Q.type!=="range")return!1;let{startContainer:J,endContainer:X}=Q.range;if(J===X&&J.nodeType===YQ)return!1;return Y.some(({element:Z})=>G.mathCapabilityByElement.get(Z)==="token"&&Z.contains(J)&&Z.contains(X))},XQ=(G,Q)=>({chunk:G,regionTarget:eG(G),renderedMathTargetResolver:w0(),mathCapabilityByElement:new Map(G.mathAlignments.map(({element:Y})=>[Y,Q?P0(Y):"expression"])),heldTokenByElement:new Map}),C0=(G)=>{let Q=G.mathTokenHighlighting!==!1,Y=new Map(G.chunks.map((J)=>[J.id,XQ(J,Q)]));return{chunks:G.chunks,resolveInitial(J){let X=Y.get(J);if(!X)return S0();let j=X.chunk.mathAlignments,Z=j.length===1?j[0].element:null,q=Z?X.mathCapabilityByElement.get(Z):null;if(q==="expression")return P7({semanticTarget:null,expressionTarget:b0(X),regionTarget:X.regionTarget,confidence:0.5,reason:"initial expression (sticky expression mode)"});return P7({semanticTarget:null,expressionTarget:null,regionTarget:X.regionTarget,confidence:0,reason:q==="token"?"initial region (sticky token mode, awaiting first token)":"initial region fallback"})},resolveBoundary(J){let X=Y.get(J.chunkId);if(!X)return S0();let{chunk:j}=X,Z=H0(j,J),q=E0(j,Z),B=GQ(q,j),K=(!q||B.length>0?R0(j,Z,J,B,X.renderedMathTargetResolver):null)||null,W=Q&&K&&K.quality!=="expression"?K:null,$=K&&K.quality==="expression"?K:null;if(W){let H=T0(B);if(H)X.heldTokenByElement.set(H,W);return P7({semanticTarget:W,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason})}if(q&&(Q?!JQ(X,q,B):B.length===0))return P7({semanticTarget:q,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason});if(QQ(X,B)){let H=T0(B),N=H?X.heldTokenByElement.get(H)??null:null;return P7({semanticTarget:N,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:N?"hold last token (sticky token mode)":"region (sticky token mode, awaiting first token)"})}return P7({semanticTarget:null,expressionTarget:$??b0(X,B),regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason})}}};var ZQ=(G)=>{if(G.alignment?.boundaryOffsetMode)return G.alignment.boundaryOffsetMode;let Q=G.mathAlignment?.speech.boundaryOffsetSpace;if(Q)return Q;return"plain-spoken-text"},jQ=(G)=>{if(G.mathAlignments?.length)return G.mathAlignments;if(G.mathAlignment&&G.sourceElement)return[{element:G.sourceElement,alignment:G.mathAlignment}];return[]},y0=(G)=>{return(G.chunks&&G.chunks.length?G.chunks:[{speechText:G.speechText||"",visibleText:G.visibleText||G.speechText||"",sourceElement:G.sourceElement||G.contentRoot,regionElement:G.regionElement||G.sourceElement||G.contentRoot,regionRange:G.regionRange,visibleMap:G.visibleMap}]).map((Y,J)=>({id:`tts-chunk-${J}`,speechText:Y.speechText,visibleText:Y.visibleText,sourceElement:Y.sourceElement,contentRoot:G.contentRoot,regionElement:Y.regionElement??Y.sourceElement,regionRange:Y.regionRange,visibleMap:Y.visibleMap,catalogAlignment:Y.alignment,mathAlignments:jQ(Y),offsetSpace:ZQ(Y)}))};var qQ=["[data-pie-tts-region]","[data-catalog-region]","li","p","label","section","[role='group']","[role='region']","div"].join(","),N1=(G,Q)=>{let Y=G.closest(qQ);if(Y&&Q.contains(Y))return Y;return G};var UQ=(G,Q,Y)=>{let J=new Map;for(let X=Q;X<Y;X++){let j=G.get(X);if(j)J.set(X-Q,j)}return J},P8=async(G)=>{let Q=z7(G.contentRoot,G.textProcessingOptions),Y=await A8({chunks:Q.chunks,visibleText:Q.visibleText,language:G.language,mathSpeech:G.mathSpeech,produceSsml:G.produceSsml,resolveMathSpeech:G.resolveMathSpeech});return{plan:{items:Y.segments.map(({segment:X,sourceChunkIndex:j})=>{let Z=Q.chunks[j];if(X.kind==="prose"){let B=Z?.type==="text"?Z.sourceElement??G.contentRoot:G.contentRoot;return{segment:X,anchor:{sourceElement:B,regionElement:N1(B,G.contentRoot),visibleMap:UQ(Q.map,X.visibleSpan.start,X.visibleSpan.end)}}}let q=Z?.type==="math"?Z.sourceElement??null:null;return{segment:X,anchor:{sourceElement:q,regionElement:q}}}),locale:Y.locale,visibleText:Y.visibleText,plainSpeechText:Y.plainSpeechText},containsMathMarkup:Q.containsMathMarkup,visibleText:Q.visibleText}};var BQ=(G,Q)=>{let Y=V1({speechText:G.spokenText,visibleText:G.spokenText});return{speechText:G.spokenText,visibleText:G.visibleText,sourceElement:Q.sourceElement,regionElement:Q.regionElement,regionRange:A1(Q.visibleMap,0,G.visibleText.length)??void 0,speechMatchesVisibleText:!0,playbackMode:Y.playbackMode,alignment:Y,visibleMap:Q.visibleMap}},x0=(G,Q)=>{let Y=Q.sourceElement;return{speechText:G.spokenText,visibleText:G.fallbackText,sourceElement:Y,regionElement:Q.regionElement,speechMatchesVisibleText:G.spokenText===G.fallbackText,mathAlignment:Y?x7({mathElement:Y,speechText:G.spokenText}):void 0}},WQ=(G,Q,Y)=>{let J=Q.sourceElement;return{speechText:Y,visibleText:G.fallbackText,sourceElement:J,regionElement:Q.regionElement,speechMatchesVisibleText:!1,mathAlignment:J?x7({mathElement:J,speechText:Y}):void 0,plainFallback:x0(G,Q)}},L8=(G,Q={})=>G.items.map(({segment:Y,anchor:J})=>{if(Y.kind==="prose")return BQ(Y,J);if(Q.format==="ssml"&&Y.ssml)return WQ(Y,J,Y.ssml);return x0(Y,J)});var f0="pie-tts-control-handoff";var R;(function(G){G.IDLE="idle",G.LOADING="loading",G.PLAYING="playing",G.PAUSED="paused",G.ERROR="error"})(R||(R={}));var k0=(G,Q)=>G===Q||G.startContainer===Q.startContainer&&G.startOffset===Q.startOffset&&G.endContainer===Q.endContainer&&G.endOffset===Q.endOffset,KQ=(G,Q)=>{if(G===Q)return!0;if(!G||!Q||G.type!==Q.type||G.quality!==Q.quality)return!1;if(G.type==="range"&&Q.type==="range")return k0(G.range,Q.range);if(G.type==="element"&&Q.type==="element")return G.element===Q.element;if(G.type==="text-range"&&Q.type==="text-range")return G.node===Q.node&&G.startOffset===Q.startOffset&&G.endOffset===Q.endOffset;return!1};class c7{currentProvider=null;provider=null;highlightCoordinator=null;highlightTargetResolverProvider=null;catalogResolver=null;state=R.IDLE;ttsConfig={};currentText=null;currentContentElement=null;normalizedToDOM=new Map;listeners=new Map;lastError=null;speakRunId=0;currentBoundaryOffset=0;activeWordBoundaryOffset=0;seekSegments=[];playbackChunks=[];activeRecordedAudio=null;sentenceHighlightSegments=[];currentSeekSegmentIndex=0;activeSentenceStartOffset=null;playbackStartDeferredRunId=null;pendingPlaybackStartHighlights=[];playbackStartBarrierCleanup=null;playbackRateWriteQueue=Promise.resolve();playbackRateRequestId=0;pendingPlaybackRateRequest=null;activePlaybackRate=null;activeHighlightMode="word";lastRenderedRegionTarget=null;telemetryReporter=null;generatedMathSpeechResolver=F8();static debugEnabled=(()=>{try{if(typeof process<"u"&&process.env?.PIE_TTS_DEBUG==="1")return!0}catch{}return globalThis.__PIE_TTS_DEBUG__===!0})();constructor(){}debugLog(G,Q){if(!c7.debugEnabled)return;if(Q===void 0)console.debug(G);else console.debug(G,Q)}clearPlaybackStartBarrier(G=this.playbackStartBarrierCleanup){if(G?.(),this.playbackStartBarrierCleanup===G)this.playbackStartBarrierCleanup=null}notifyPlaybackStarted(G){if(this.playbackStartDeferredRunId!==G||G!==this.speakRunId)return;this.setState(R.PLAYING);let Q=this.pendingPlaybackStartHighlights.splice(0);for(let Y of Q)Y()}installPlaybackStartBarrier(G,Q=!1){this.clearPlaybackStartBarrier();let Y=this.provider,J=Y&&"onPlaybackStart"in Y?Y:null;if(!J&&!Q)return null;let X=J?.onPlaybackStart,j=()=>{try{this.notifyPlaybackStarted(G)}finally{X?.()}};if(J)J.onPlaybackStart=j;this.playbackStartDeferredRunId=G;let Z=()=>{if(J?.onPlaybackStart===j)J.onPlaybackStart=X;if(this.playbackStartDeferredRunId===G)this.playbackStartDeferredRunId=null,this.pendingPlaybackStartHighlights=[]};return this.playbackStartBarrierCleanup=Z,Z}runWhenPlaybackStarts(G,Q){if(this.playbackStartDeferredRunId===G){this.pendingPlaybackStartHighlights.push(Q);return}Q()}async emitTelemetry(G,Q){try{await this.telemetryReporter?.(G,Q)}catch(Y){console.warn("[TTSService] telemetry callback failed:",Y)}}async initialize(G,Q={}){this.currentProvider=G,this.ttsConfig={...Q};let Y=Q.providerOptions&&typeof Q.providerOptions==="object"?Q.providerOptions:{};this.telemetryReporter=typeof Y.__pieTelemetry==="function"?Y.__pieTelemetry:null;try{this.provider=await G.initialize(Q)}catch(J){if(G.providerId.toLowerCase()==="browser")throw J;if(!this.isBrowserSpeechFallbackAvailable())throw J;if(!await this.switchProviderToBrowser(J,{operation:"tts-initialize"}))throw J}}async updateSettings(G){if(!this.provider)throw Error("TTSService not initialized. Call initialize() first.");let Q=this.provider;if(typeof Q.updateSettings==="function"){let Y={...G,...G.providerOptions?{providerOptions:{...this.ttsConfig.providerOptions||{},...G.providerOptions}}:{}};await Q.updateSettings(Y),this.ttsConfig={...this.ttsConfig,...Y}}else console.warn("[TTSService] Provider does not support dynamic settings updates. Some settings may require reinitialization.")}setHighlightCoordinator(G){this.highlightCoordinator=G}setHighlightTargetResolverProvider(G){return this.highlightTargetResolverProvider=G,()=>{if(this.highlightTargetResolverProvider===G)this.highlightTargetResolverProvider=null}}setCatalogResolver(G){this.catalogResolver=G}hasSpokenAlternate(G,Q="en-US"){if(!G||!this.catalogResolver)return!1;return this.catalogResolver.getAlternative(G,{type:"spoken",language:Q,useFallback:!0,form:"content"})?.content!==void 0}getHighlightResolverRuntime(){let G=null;try{G=this.highlightTargetResolverProvider?.()??null}catch{G=null}let Q=G?.context??{},Y=typeof HTMLElement<"u"&&this.currentContentElement instanceof HTMLElement?this.currentContentElement:null;return{context:{...Q,scopeElement:Q.scopeElement??Y},resolver:G?.resolver??null}}getNodeElement(G){if(!G)return null;return G.nodeType===Node.ELEMENT_NODE?G:G.parentElement}isElementWithinScope(G,Q){if(!Q)return!0;return G===Q||Q.contains(G)}isRangeWithinScope(G,Q){let Y=this.getNodeElement(G.startContainer),J=this.getNodeElement(G.endContainer);if(!Y||!J)return!1;return this.isElementWithinScope(Y,Q)&&this.isElementWithinScope(J,Q)}resolveWordHighlightRange(G){let{context:Q,resolver:Y}=this.getHighlightResolverRuntime(),J=Q.scopeElement??this.currentContentElement;try{let X=Y?.resolveWordRange?.(G,Q);if(X&&this.isRangeWithinScope(X,J))return{range:X,remapped:!k0(G,X)}}catch{}return{range:G,remapped:!1}}resolveSentenceHighlightTargets(G){let{context:Q,resolver:Y}=this.getHighlightResolverRuntime(),J=Q.scopeElement??this.currentContentElement;try{let X=Y?.resolveSentenceRanges?.(G,Q);if(!X)return{ranges:G,elements:[]};let j=[],Z=[];for(let q of X){if(typeof Range<"u"&&q instanceof Range){if(!this.isRangeWithinScope(q,J))return{ranges:G,elements:[]};j.push(q);continue}if(typeof Element<"u"&&q instanceof Element){if(!this.isElementWithinScope(q,J))return{ranges:G,elements:[]};Z.push(q);continue}return{ranges:G,elements:[]}}return{ranges:j,elements:Z}}catch{return{ranges:G,elements:[]}}}createTextRange(G,Q,Y){if(typeof document>"u")return null;if(typeof document.createRange!=="function")return null;try{let J=document.createRange();if(J.setStart(G,Q),J.setEnd(G,Y),J.startContainer!==G||J.endContainer!==G)return null;return J}catch{return null}}paintTTSWordRange(G){if(!this.highlightCoordinator)return;try{if(G.startContainer===G.endContainer&&G.startContainer.nodeType===Node.TEXT_NODE){this.highlightCoordinator.highlightTTSWord(G.startContainer,G.startOffset,G.endOffset);return}}catch{}this.highlightCoordinator.highlightRange(G,u.TTS_WORD,$7.YELLOW)}paintTTSSentenceRanges(G){if(!this.highlightCoordinator)return;let{ranges:Q,elements:Y}=this.resolveSentenceHighlightTargets(G);if(Y.length>0&&Q.length===0&&this.highlightCoordinator.highlightTTSSentenceElements){this.highlightCoordinator.highlightTTSSentenceElements(Y);return}let J=[...Q];for(let X of Y){let j=document.createRange();j.selectNodeContents(X),J.push(j)}this.highlightCoordinator.highlightTTSSentence(J)}getCapabilities(){return this.currentProvider?.getCapabilities()||null}getTextProcessingOptions(G){let Y=(this.ttsConfig.providerOptions||{}).textNormalization||{},J=Y.boundarySpacingMode,X=J==="none"||J==="alnum"||J==="segmenterPreferred"?J:void 0;return{locale:G||(typeof Y.locale==="string"?Y.locale:void 0),boundarySpacingMode:X}}getMathSpeechOptions(){let Q=(this.ttsConfig.providerOptions||{}).mathSpeech;return O7(Q)}buildPositionMap(G,Q,Y){this.normalizedToDOM.clear();let{text:J,map:X}=C7(G,this.getTextProcessingOptions(Y));if(this.normalizedToDOM=X,!c7.debugEnabled)return;this.debugLog("[TTSService] Text comparison:",{spokenLength:Q.length,normalizedDomLength:J.length,match:Q===J,spokenPreview:Q.substring(0,150),normalizedPreview:J.substring(0,150),differAtIndex:Q===J?null:(()=>{for(let j=0;j<Math.min(Q.length,J.length);j++)if(Q[j]!==J[j])return{index:j,spokenChar:Q[j],normalizedChar:J[j],spokenContext:Q.substring(Math.max(0,j-20),j+20),normalizedContext:J.substring(Math.max(0,j-20),j+20)};return null})()}),this.debugLog("[TTSService] Position map built:",{entries:this.normalizedToDOM.size,spokenTextLength:Q.length,normalizedDomLength:J.length,mapLengthMatchesSpoken:this.normalizedToDOM.size===Q.length,firstFewMappings:Array.from(this.normalizedToDOM.entries()).slice(0,10).map(([j,{node:Z,offset:q}])=>({pos:j,offset:q,char:Z.textContent?.[q],expected:Q[j]}))})}getStructuralPauseProfile(){let Q=(this.ttsConfig.providerOptions||{}).structuralPauses||{},Y=Q.units||{},J=(X,j)=>{if(typeof X==="number"&&Number.isFinite(X))return X;if(typeof X==="string"&&X.trim()){let Z=Number(X);return Number.isFinite(Z)?Z:j}return j};return{baseMs:J(Q.baseMs,280),units:{minor:J(Y.minor,0.65),section:J(Y.section,1),major:J(Y.major,1.35)},minMs:J(Q.minMs,120),maxMs:J(Q.maxMs,900)}}resolvePauseMsFromUnits(G){let Q=this.getStructuralPauseProfile(),Y=Math.max(0.25,Math.min(4,Number(this.ttsConfig.rate||1))),J=Q.baseMs*Math.max(0,G)/Y;return Math.max(Q.minMs,Math.min(Q.maxMs,Math.round(J)))}resolveHighlightMode(){let Q=(this.ttsConfig.providerOptions||{}).highlightMode;if(Q==="word"||Q==="sentence")return Q;if((this.currentProvider?.providerId||"").toLowerCase()==="browser")return"sentence";return this.currentProvider?.getCapabilities().supportsWordBoundary??!1?"word":"sentence"}hasExplicitBreakSemantics(G){if(!G.includes("<"))return!1;return/<\s*break\b|<\s*speak\b|<\s*prosody\b|<\s*p\b|<\s*s\b/i.test(G)}isElementHidden(G){return Z8(G)}getBoundaryStrength(G){let Q=Number(G.getAttribute("data-tts-break-ms"));if(Number.isFinite(Q)&&Q>0)return"major";let Y=G.tagName.toUpperCase();if(Y.match(/^H[1-6]$/))return"major";let J=(G.getAttribute("role")||"").toLowerCase();if(J==="heading")return"major";if(J==="listitem"||J==="row"||J==="option"||J==="radio"||Y==="LI")return"section";if(typeof window<"u"){let X=window.getComputedStyle(G).display;if(X==="block"||X==="list-item"||X.startsWith("table")||X==="flex"||X==="grid")return"minor"}return"minor"}getBoundaryAnchor(G,Q){let Y=G.parentElement,J=null;while(Y&&Y!==Q){if(this.isElementHidden(Y))return null;let j=Number(Y.getAttribute("data-tts-break-ms"));if(Number.isFinite(j)&&j>0)return{anchor:Y,units:j/this.getStructuralPauseProfile().baseMs};let Z=(Y.getAttribute("role")||"").toLowerCase(),q=Y.tagName.toUpperCase();if(q.match(/^H[1-6]$/)||Z==="heading"||Z==="listitem"||q==="LI"){J=Y;break}if(!J){if(typeof window<"u"){let B=window.getComputedStyle(Y).display;if(B==="block"||B==="list-item"||B.startsWith("table")||B==="flex"||B==="grid")J=Y}}Y=Y.parentElement}if(!J)return null;let X=this.getBoundaryStrength(J);return{anchor:J,units:this.getStructuralPauseProfile().units[X]}}createSpeechPlan(G,Q){let Y=this.collectSpeechPlanBoundaries(G,Q);return this.createSpeechPlanSegments(Q,Y)}collectSpeechPlanBoundaries(G,Q){let Y=new Map,{map:J}=C7(G,this.getTextProcessingOptions()),X=this.createNodeStartOffsets(J),j=document.createTreeWalker(G,NodeFilter.SHOW_TEXT),Z=j.nextNode(),q=null;while(Z){let B=Z,K=B.parentElement;if(K&&!this.isElementHidden(K)&&!W1(B)){let W=this.getBoundaryAnchor(B,G),$=X.get(B);if(W&&$!==void 0&&W.anchor!==q&&$>0)Y.set($,Math.max(Y.get($)||0,W.units)),q=W.anchor}Z=j.nextNode()}return Y}createNodeStartOffsets(G){let Q=new Map;for(let[Y,J]of G.entries())if(!Q.has(J.node))Q.set(J.node,Y);return Q}createSpeechPlanSegments(G,Q){let Y=Array.from(Q.keys()).filter((B)=>B>0&&B<G.length).sort((B,K)=>B-K),J=[],X=0;for(let B of Y){let K=G.substring(X,B),W=K.match(/^\s*/)?.[0].length||0,$=K.match(/\s*$/)?.[0].length||0,H=X+W,N=B-$;if(N>H){let F=G.substring(H,N);J.push({text:F,startOffset:H,pauseMsAfter:this.resolvePauseMsFromUnits(Q.get(B)||0)})}X=B}let Z=G.substring(X).match(/^\s*/)?.[0].length||0,q=X+Z;if(q<G.length)J.push({text:G.substring(q).trimEnd(),startOffset:q,pauseMsAfter:0});return J.filter((B)=>B.text.trim().length>0)}segmentSentences(G){let Q=this.ttsConfig.providerOptions?.locale||void 0;return S7(G,{locale:Q})}createSeekSegmentsFromText(G){return this.segmentSentences(G).map((Q)=>{let Y=Q.text.match(/^\s*/)?.[0].length||0;return{text:Q.text.trim(),startOffset:Q.offset+Y,pauseMsAfter:0}}).filter((Q)=>Q.text.length>0)}splitSegmentsAtBoundaries(G,Q,Y){if(G.length===0||Q.length===0)return G;let J=Array.from(new Set(Q)).filter((j)=>Number.isFinite(j)&&j>0).sort((j,Z)=>j-Z);if(J.length===0)return G;let X=[];for(let j of G){let Z=j.startOffset,q=j.startOffset+j.text.length,B=J.filter((W)=>W>Z&&W<q);if(B.length===0){X.push(j);continue}let K=Z;for(let W of[...B,q]){let $=Y.substring(K,W),H=$.match(/^\s*/)?.[0].length||0,N=$.match(/\s*$/)?.[0].length||0,F=K+H,O=W-N;if(O>F)X.push({text:Y.substring(F,O),startOffset:F,pauseMsAfter:0});K=W}}return X}createSentenceHighlightSegments(G){let Q=this.createSeekSegmentsFromText(G.contentToSpeak);if(!G.shouldUsePlan||G.playbackSegments.length===0)return Q;let Y=G.playbackSegments.map((J)=>J.startOffset).filter((J)=>J>0);return this.splitSegmentsAtBoundaries(Q,Y,G.contentToSpeak)}createSeekSegmentsFromSpeechChunks(G){let Q=0;return G.map((Y)=>{let J=Y.plainFallback?.speechText||(this.hasExplicitBreakSemantics(Y.speechText)?Y.visibleText:Y.speechText)||Y.visibleText,X=T(J)||Y.visibleText||"",j={text:X,startOffset:Q,pauseMsAfter:0};return Q+=Math.max(1,X.length+1),j})}getCurrentSeekSegmentIndex(){if(this.seekSegments.length===0)return 0;let G=0;for(let Q=0;Q<this.seekSegments.length;Q++)if(this.seekSegments[Q].startOffset<=this.currentBoundaryOffset)G=Q;else break;return G}async speakWithPlan(G,Q,Y){if(!this.provider||G.length===0)return;let J=Y?.highlightMode==="sentence",X=this.provider;if(!J&&typeof X.speakSegments==="function"){this.currentBoundaryOffset=0;let j=this.provider.onWordBoundary;this.provider.onWordBoundary=(Z,q,B)=>{if(j?.(Z,q,B),Number.isFinite(q))this.currentBoundaryOffset=q,this.currentSeekSegmentIndex=this.getCurrentSeekSegmentIndex()};try{await X.speakSegments(G)}finally{if(Q===this.speakRunId&&this.provider===X)this.provider.onWordBoundary=j}return}this.configureWordBoundaryHighlighting({highlightMode:Y?.highlightMode||"word",wordBoundaryOffset:this.activeWordBoundaryOffset});for(let j of G){if(Q!==this.speakRunId)return;let Z=this.seekSegments.findIndex((B)=>B.startOffset===j.startOffset);if(Z>=0)this.currentSeekSegmentIndex=Z;if(this.currentBoundaryOffset=j.startOffset,J)this.runWhenPlaybackStarts(Q,()=>{this.highlightSentenceSegment(j.startOffset,j.text)});await this.provider.speak(j.text);let q=j.pauseMsAfter??0;if(q>0)await new Promise((B)=>setTimeout(B,q))}}highlightSentenceSegment(G,Q){if(!this.highlightCoordinator||typeof document>"u")return;let Y=Q.trimEnd().length;if(Y<=0)return;let J=this.normalizedToDOM.get(G),X=this.normalizedToDOM.get(G+Y-1);if(!J||!X)return;let j=document.createRange();j.setStart(J.node,J.offset),j.setEnd(X.node,X.offset+1),this.paintTTSSentenceRanges([j]),this.activeSentenceStartOffset=G}getSegmentIndexForOffset(G,Q){if(G.length===0)return-1;let Y=-1;for(let J=0;J<G.length;J++)if(G[J].startOffset<=Q)Y=J;else break;return Y}highlightSentenceForOffset(G){let Q=this.sentenceHighlightSegments;if(!this.highlightCoordinator||Q.length===0)return;let Y=this.getSegmentIndexForOffset(Q,G);if(Y<0)return;let J=Q[Y];if(!J)return;if(this.activeSentenceStartOffset===J.startOffset)return;this.highlightSentenceSegment(J.startOffset,J.text)}findHighlightRange(G,Q){let Y=this.normalizedToDOM.get(G);if(!Y)return console.warn(`[TTSService] No mapping found for start position ${G}`,{totalMappings:this.normalizedToDOM.size,nearbyMappings:Array.from(this.normalizedToDOM.entries()).filter(([j])=>Math.abs(j-G)<5).map(([j,{offset:Z,node:q}])=>({pos:j,offset:Z,char:q.textContent?.[Z]}))}),null;let J=G+Q-1,X=this.normalizedToDOM.get(J);if(!X)return console.warn(`[TTSService] No mapping found for end position ${J}`,{startChar:G,length:Q,totalMappings:this.normalizedToDOM.size}),null;if(Y.node!==X.node)return console.warn("[TTSService] Word spans multiple nodes, highlighting in first node only"),{node:Y.node,start:Y.offset,end:(Y.node.textContent||"").length};return{node:Y.node,start:Y.offset,end:X.offset+1}}async speak(G,Q){if(!this.provider)throw Error("TTS service not initialized");let Y=++this.speakRunId;this.clearPlaybackStartBarrier();let J=null;try{if(await this.applyLanguageSettings(Q),Y!==this.speakRunId)return;let X=await this.resolveSpeechContent(G,Q);if(Y!==this.speakRunId)return;let{contentToSpeak:j,speechText:Z,highlightText:q,normalizedText:B,usedCatalogSpoken:K,speechSource:W,speechMatchesVisibleText:$,speechChunks:H}=X;this.logResolvedSpeechContent({contentToSpeak:j,speechSource:W,catalogId:Q?.catalogId}),this.initializeSpeakTracking(q,Q);let N=Q?.highlightModeOverride||($?this.resolveHighlightMode():"sentence");this.activeHighlightMode=N,this.activeWordBoundaryOffset=Q?.wordBoundaryOffset||0;let F=this.hasExplicitBreakSemantics(j),O=!!this.currentContentElement&&!K&&!F&&$;if(this.playbackChunks=H?.length?H:[],this.seekSegments=this.playbackChunks.length?this.createSeekSegmentsFromSpeechChunks(this.playbackChunks):F||!$?[]:O&&this.currentContentElement?this.createSpeechPlan(this.currentContentElement,B):this.createSeekSegmentsFromText(q),this.sentenceHighlightSegments=F?[]:this.createSentenceHighlightSegments({contentToSpeak:q,shouldUsePlan:O,playbackSegments:this.seekSegments}),this.setState(R.LOADING),J=this.installPlaybackStartBarrier(Y,!!this.playbackChunks[0]?.audio),this.prepareHighlightsForSpeak({contentToSpeak:q,options:Q,highlightMode:N,shouldUsePlan:O,runId:Y}),$)this.configureWordBoundaryHighlighting({highlightMode:N,wordBoundaryOffset:Q?.wordBoundaryOffset||0});else this.clearWordBoundaryHighlighting();if(!J)this.setState(R.PLAYING);if(this.activePlaybackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1)),await this.executeSpeakPlayback({shouldUsePlan:O,runId:Y,highlightMode:N,contentToSpeak:Z,speechChunks:H}),Y!==this.speakRunId)return;this.setState(R.IDLE),this.clearHighlightsAndTracking()}catch(X){let j=X;if(console.error("TTS error:",j),this.lastError=j instanceof Error?j.message:String(j),Y!==this.speakRunId)return;throw this.setState(R.ERROR),this.clearHighlightsAndTracking(),j}finally{this.clearPlaybackStartBarrier(J)}}async switchProviderToBrowser(G,Q){if(!this.currentProvider)return!1;let Y=new T7,J=this.currentProvider.providerId,X={};if(this.ttsConfig.rate!==void 0)X.rate=this.ttsConfig.rate;if(this.ttsConfig.pitch!==void 0)X.pitch=this.ttsConfig.pitch;if(this.ttsConfig.mathTokenHighlighting!==void 0)X.mathTokenHighlighting=this.ttsConfig.mathTokenHighlighting;let j=Q?.operation||"tts-initialize",Z=Q?.contentToSpeak??"",q=Z.replace(/\s+/g," ").trim().slice(0,120),B=Z.length>0?{textLength:Z.length,textPreview:q.length<Z.length?`${q}…`:q}:{};try{return this.provider?.stop(),this.currentProvider.destroy(),this.currentProvider=Y,this.provider=await Y.initialize(X),this.ttsConfig=X,await this.emitTelemetry("pie-tool-runtime-fallback",{toolId:"textToSpeech",operation:j,fromProvider:J,toProvider:Y.providerId,reason:G instanceof Error?G.message:String(G),...B}),console.warn("[TTSService] TTS provider initialization failed; switched to browser fallback",{fromProvider:J,reason:G,...B}),!0}catch(K){return await this.emitTelemetry("pie-tool-runtime-fallback-error",{toolId:"textToSpeech",operation:j,fromProvider:J,toProvider:"browser",errorType:"TTSRuntimeFallbackError",message:K instanceof Error?K.message:String(K)}),console.error("[TTSService] Failed to switch to browser fallback provider",K),!1}}isBrowserSpeechFallbackAvailable(){if(typeof window>"u")return!1;if(!("speechSynthesis"in window))return!1;return typeof globalThis.SpeechSynthesisUtterance==="function"}async applyLanguageSettings(G){if(!G?.language||!this.provider)return;let Q=this.ttsConfig.providerOptions||{},Y=Q.textNormalization||{},J=Q.segmenter||{},X={...Q,locale:G.language,textNormalization:{...Y,locale:G.language},segmenter:{...J,locale:G.language}};if(this.ttsConfig={...this.ttsConfig,providerOptions:X},"updateSettings"in this.provider&&typeof this.provider.updateSettings==="function")await this.provider.updateSettings({providerOptions:X})}async resolveSpeechContent(G,Q){let Y=T(G);if(Q?.ignoreCatalogs)return{contentToSpeak:Y,speechText:Y,visibleText:Y,highlightText:Y,usedCatalogSpoken:!1,speechSource:"dom-or-input",normalizedText:Y,containsMathMarkup:!1,speechMatchesVisibleText:!0};if(Q?.catalogId&&this.catalogResolver){let j=this.catalogResolver.getAlternative(Q.catalogId,{type:"spoken",language:Q.language||"en-US",useFallback:!0,context:Q.catalogContext,form:"content"}),Z=j?.content;if(j&&Z!==void 0){let q=Q?.contentElement?z7(Q.contentElement,this.getTextProcessingOptions(Q.language)).visibleText||Y:Y,B=T(Z);return this.debugLog(`[TTSService] Using catalog content for "${Q.catalogId}" (${j.language})`),{contentToSpeak:Z,speechText:Z,visibleText:q,highlightText:q,usedCatalogSpoken:!0,speechSource:"catalog-spoken",normalizedText:q,containsMathMarkup:!1,speechMatchesVisibleText:B===q}}this.debugLog(`[TTSService] No catalog found for "${Q.catalogId}", falling back to generated TTS`)}let J=Q?.contentElement?this.resolveCatalogComposedSpeechContent(Q.contentElement,Y,Q):null;if(J)return J;return{...Q?.contentElement?await this.resolveGeneratedSpeechContent(Q.contentElement,Y,Q.language):{contentToSpeak:Y,speechText:Y,visibleText:Y,highlightText:Y,normalizedText:Y,containsMathMarkup:!1,speechMatchesVisibleText:!0},usedCatalogSpoken:!1,speechSource:"dom-or-input"}}resolveCatalogComposedSpeechContent(G,Q,Y){if(!this.catalogResolver)return null;let J=this.collectCatalogSpeechChunks(G,Y);if(!J.some((Z)=>Z.sourceElement))return null;let X=T(J.map((Z)=>Z.speechText).join(" ")),j=z7(G,this.getTextProcessingOptions(Y.language)).visibleText||Q;return{contentToSpeak:X,speechText:X,visibleText:j,highlightText:j,usedCatalogSpoken:!0,speechSource:"catalog-spoken",normalizedText:j,containsMathMarkup:!1,speechMatchesVisibleText:J.every((Z)=>Z.speechMatchesVisibleText),speechChunks:J}}collectCatalogSpeechChunks(G,Q){let Y=[],J="",X=()=>{let K=T(J);if(J="",!K)return;Y.push({speechText:K,visibleText:K,sourceElement:null,speechMatchesVisibleText:!0})},j=(K)=>{let W=K.getAttribute("data-catalog-idref");if(!W)return null;let $={type:"spoken",language:Q.language||"en-US",useFallback:!0,context:Q.catalogContext},H=this.catalogResolver.getAlternative(W,{...$,form:"payload"}),N=H?.payload?w6({payload:H.payload})??void 0:void 0,O=this.catalogResolver.getAlternative(W,{...$,form:"content"})?.content;if(N===void 0&&O===void 0)return null;return{script:O,audio:N}},Z=(K,W)=>{let $=q(K);if($.length!==1)return null;let H=$[0],N=z7(H,this.getTextProcessingOptions(Q.language)).visibleText||T(H.textContent||""),F=(O)=>T(O).replace(/\s+/g,"");return F(N)===F(W)?H:null},q=(K)=>{let W=Array.from(K.querySelectorAll("math"));if(K.localName?.toLowerCase()==="math")return[K,...W];return W},B=(K)=>{if(H7(K,G))return;if(K.nodeType===Node.TEXT_NODE){J+=` ${K.textContent||""}`;return}if(K.nodeType!==Node.ELEMENT_NODE)return;let W=K,$=j(W);if($){X();let H=z7(W,this.getTextProcessingOptions(Q.language)),N=H.visibleText||T(W.textContent||""),F=N1(W,G),O=$.script!==void 0?(()=>{let L=$.script,D=V1({speechText:L,visibleText:N}),P=Z(W,N),S=P?x7({mathElement:P,speechText:L}):void 0,v=S?void 0:q(W).map((I)=>({element:I,alignment:x7({mathElement:I,speechText:L})}));return{speechText:L,visibleText:N,sourceElement:W,regionElement:F,speechMatchesVisibleText:T(L)===N,playbackMode:D.playbackMode,alignment:D,mathAlignment:S,mathAlignments:v,visibleMap:H.map}})():null;if($.audio){Y.push(O?{...O,audio:$.audio,plainFallback:O}:{speechText:N,visibleText:N,sourceElement:W,regionElement:F,speechMatchesVisibleText:!1,visibleMap:H.map,audio:$.audio});return}if(O)Y.push(O);return}for(let H of Array.from(W.childNodes))B(H)};return B(G),X(),Y}resolveGeneratedPlaybackFormat(){let G=this.currentProvider;if(!G)return"plain";if(G.providerId?.toLowerCase()==="browser")return"plain";return G.getCapabilities?.().supportsSSML?"ssml":"plain"}async resolveGeneratedSpeechContent(G,Q,Y){let J=this.resolveGeneratedPlaybackFormat(),{plan:X,containsMathMarkup:j,visibleText:Z}=await P8({contentRoot:G,language:Y,mathSpeech:this.getMathSpeechOptions(),textProcessingOptions:this.getTextProcessingOptions(Y),produceSsml:J==="ssml",resolveMathSpeech:this.generatedMathSpeechResolver}),q=Z||Q;if(!j)return{contentToSpeak:q,speechText:q,visibleText:q,highlightText:q,normalizedText:q,containsMathMarkup:!1,speechMatchesVisibleText:!0};let B=L8(X,{format:J}),K=X.plainSpeechText;return{contentToSpeak:K,speechText:K,visibleText:q,highlightText:q,normalizedText:q,containsMathMarkup:!0,speechMatchesVisibleText:K===q,speechChunks:B}}logResolvedSpeechContent(G){let Q=G.contentToSpeak.replace(/\s+/g," ").trim().slice(0,200);this.debugLog("[TTSService] Speak resolved content",{source:G.speechSource,catalogId:G.catalogId||null,length:G.contentToSpeak.length,preview:Q})}initializeSpeakTracking(G,Q){this.currentText=G,this.currentContentElement=Q?.contentElement||null,this.lastError=null,this.currentBoundaryOffset=0,this.playbackChunks=[],this.currentSeekSegmentIndex=0,this.activeSentenceStartOffset=null}prepareHighlightsForSpeak(G){if(!this.currentContentElement||!this.highlightCoordinator)return;if(this.buildPositionMap(this.currentContentElement,G.contentToSpeak,G.options?.language),G.highlightMode==="sentence"&&G.shouldUsePlan)return;let Q=this.sentenceHighlightSegments[0]||this.seekSegments[0];this.runWhenPlaybackStarts(G.runId,()=>{if(Q)this.highlightSentenceSegment(Q.startOffset,Q.text),this.debugLog("[TTSService] Applied initial sentence highlighting");else try{let Y=document.createRange();Y.selectNodeContents(this.currentContentElement),this.paintTTSSentenceRanges([Y])}catch{}})}configureWordBoundaryHighlighting(G){if(!this.provider||G.highlightMode!=="word"||!this.highlightCoordinator||!this.currentContentElement)return;this.provider.onWordBoundary=(Q,Y,J)=>{let X=J||Q.length,j=Y+this.currentBoundaryOffset+G.wordBoundaryOffset;this.highlightSentenceForOffset(j);let Z=this.findHighlightRange(j,X);if(Z&&this.highlightCoordinator){let q=Z.node.textContent?.substring(Z.start,Z.end)||"";this.debugLog(`[TTSService] Highlighting "${q}" (word: "${Q}") at position ${j}`);let B=this.createTextRange(Z.node,Z.start,Z.end);if(B)this.paintTTSWordRange(this.resolveWordHighlightRange(B).range);else this.highlightCoordinator.highlightTTSWord(Z.node,Z.start,Z.end)}else console.warn(`[TTSService] Could not find highlight range for position ${j}, length ${X}`)}}clearWordBoundaryHighlighting(){if(this.provider)this.provider.onWordBoundary=void 0}highlightCatalogRegion(G){let Q=G.regionElement||G.sourceElement;if(!Q&&!G.regionRange||!this.highlightCoordinator)return;try{if(this.lastRenderedRegionTarget=null,G.regionRange){this.highlightCoordinator.clearHighlights?.(u.TTS_WORD),this.paintTTSSentenceRanges([G.regionRange]);return}if(!Q)return;let Y=document.createRange();Y.selectNodeContents(Q),this.highlightCoordinator.clearHighlights?.(u.TTS_WORD),this.paintTTSSentenceRanges([Y])}catch{}}highlightCatalogActiveRange(G){if(!this.highlightCoordinator)return;this.paintTTSWordRange(this.resolveWordHighlightRange(G).range)}highlightRenderableRegionTarget(G){if(!this.highlightCoordinator||!G||typeof document>"u")return;if(!this.highlightTargetResolverProvider&&KQ(this.lastRenderedRegionTarget,G))return;try{let Q=document.createRange();if(G.type==="element")Q.selectNodeContents(G.element);else if(G.type==="range"){this.paintTTSSentenceRanges([G.range]),this.lastRenderedRegionTarget=G;return}else Q.setStart(G.node,G.startOffset),Q.setEnd(G.node,G.endOffset);this.paintTTSSentenceRanges([Q]),this.lastRenderedRegionTarget=G}catch{}}highlightRenderableActiveTarget(G){if(!this.highlightCoordinator||typeof document>"u")return;if(!G){this.highlightCoordinator.clearHighlights(u.TTS_WORD);return}if(G.type==="text-range"){let X=this.createTextRange(G.node,G.startOffset,G.endOffset);if(X)this.paintTTSWordRange(this.resolveWordHighlightRange(X).range);else this.highlightCoordinator.highlightTTSWord(G.node,G.startOffset,G.endOffset);return}if(G.type==="range"){this.highlightCatalogActiveRange(G.range);return}let Q=document.createRange();Q.selectNodeContents(G.element);let Y=this.resolveWordHighlightRange(Q);if(Y.remapped){this.paintTTSWordRange(Y.range);return}let J=G.element.childNodes.length===1?G.element.firstChild:null;if(G.quality==="semantic-token"&&J?.nodeType===Node.TEXT_NODE){this.highlightCoordinator.highlightTTSWord(J,0,J.textContent?.length||0);return}this.highlightCoordinator.highlightTTSWordElement?.(G.element)}renderHighlightDecision(G){this.highlightRenderableRegionTarget(G.regionTarget),this.highlightRenderableActiveTarget(G.activeTarget)}async speakCatalogChunk(G,Q){try{await this.speakCatalogChunkOnce(G,Q)}catch(Y){if(G.plainFallback&&Q===this.speakRunId){if(this.debugLog("[TTSService] SSML chunk speak failed; retrying plain text",{message:Y instanceof Error?Y.message:String(Y)}),this.playbackStartDeferredRunId===Q&&this.provider&&!("onPlaybackStart"in this.provider))this.pendingPlaybackStartHighlights=[],this.clearPlaybackStartBarrier(),this.setState(R.PLAYING);await this.speakCatalogChunkOnce(G.plainFallback,Q);return}throw Y}}async playRecordedAudio(G,Q){if(typeof document>"u")throw Error("[tts] no document available to play recorded audio");let Y=G.sources[0],J=document.createElement("audio");J.preload="auto",J.src=L6(Y.src,G.fragment),J.playbackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate||1)),await new Promise((X,j)=>{let Z,q=!1,B=!1,K=()=>{if(B||q)return;q=!0,Q?.()},W=()=>{if(J.removeEventListener("ended",$),J.removeEventListener("error",H),J.removeEventListener("playing",K),Z?.(),this.activeRecordedAudio?.element===J)this.activeRecordedAudio=null},$=()=>{if(B)return;B=!0,W(),X()},H=()=>{if(B)return;B=!0,W(),j(Error(`[tts] recorded audio failed to play: ${Y.src}`))};this.activeRecordedAudio={element:J,cancel:()=>{if(B)return;B=!0,W(),J.pause(),X()}},J.addEventListener("ended",$),J.addEventListener("error",H),J.addEventListener("playing",K),Z=P6(J,G.fragment,$),Promise.resolve(J.play()).then(K).catch(H)}).finally(()=>{if(this.activeRecordedAudio?.element===J)this.activeRecordedAudio=null;J.pause(),J.removeAttribute("src")})}cancelRecordedAudio(){let G=this.activeRecordedAudio;if(!G)return;this.activeRecordedAudio=null,G.cancel()}async speakCatalogChunkOnce(G,Q){if(!this.provider)return;if(this.lastRenderedRegionTarget=null,G.audio){this.runWhenPlaybackStarts(Q,()=>{this.highlightCatalogRegion(G)}),await this.playRecordedAudio(G.audio,()=>{this.notifyPlaybackStarted(Q)});return}let Y=G.regionElement||G.sourceElement||this.currentContentElement,J=Y?y0({contentRoot:Y,chunks:[G]})[0]:null,X=this.ttsConfig.mathTokenHighlighting!==!1,j=J?C0({chunks:[J],mathTokenHighlighting:X}):null;if(this.runWhenPlaybackStarts(Q,()=>{if(j&&J&&G.mathAlignment)this.renderHighlightDecision(j.resolveInitial(J.id));else this.highlightCatalogRegion(G)}),!(G.sourceElement&&(G.mathAlignment&&G.mathAlignment.speech.tokens.length>0||G.mathAlignments&&G.mathAlignments.length>0||G.alignment&&G.visibleMap&&(G.playbackMode==="exact-word"||G.playbackMode==="anchor-span")))){let W=this.provider,$=W.onWordBoundary;W.onWordBoundary=void 0;try{await W.speak(G.speechText)}finally{if(this.provider===W&&Q===this.speakRunId&&W.onWordBoundary===void 0)W.onWordBoundary=$}return}let q=this.provider,B=q.onWordBoundary,K=(W,$,H)=>{if(Q!==this.speakRunId)return;if(j&&J){let N=J.offsetSpace==="unsupported"?"unknown":J.offsetSpace;this.renderHighlightDecision(j.resolveBoundary({chunkId:J.id,word:W,position:$,length:H,providerOffsetSpace:N}));return}};q.onWordBoundary=K;try{await q.speak(G.speechText)}finally{if(this.provider===q&&Q===this.speakRunId&&q.onWordBoundary===K)q.onWordBoundary=B}}async executeSpeakPlayback(G){if(G.speechChunks?.length&&this.provider){for(let Q=0;Q<G.speechChunks.length;Q++){if(G.runId!==this.speakRunId)return;this.currentSeekSegmentIndex=Q;let Y=this.seekSegments[Q];if(Y)this.currentBoundaryOffset=Y.startOffset;let J=G.speechChunks[Q];await this.speakCatalogChunk(J,G.runId)}return}if(G.shouldUsePlan&&this.currentContentElement){let Q=this.seekSegments;if(Q.length>0)await this.speakWithPlan(Q,G.runId,{highlightMode:G.highlightMode});else if(this.provider)await this.provider.speak(G.contentToSpeak);return}if(this.provider)await this.provider.speak(G.contentToSpeak)}clearHighlightsAndTracking(){if(this.pendingPlaybackStartHighlights=[],this.activePlaybackRate=null,this.highlightCoordinator)this.highlightCoordinator.clearTTS();this.lastRenderedRegionTarget=null,this.currentContentElement=null,this.normalizedToDOM.clear(),this.currentBoundaryOffset=0,this.activeWordBoundaryOffset=0,this.seekSegments=[],this.playbackChunks=[],this.sentenceHighlightSegments=[],this.currentSeekSegmentIndex=0,this.activeSentenceStartOffset=null}async speakRange(G,Q){if(!this.provider)throw Error("TTS service not initialized");if(W1(G.commonAncestorContainer)){console.warn("[tts] selection lies inside content marked not-to-be-spoken; nothing was spoken. Selecting a node and pressing read-aloud must not become a way around suppression.");return}let J=Q?.contentRoot||null;if(!J){let W=G.commonAncestorContainer;J=W.nodeType===Node.ELEMENT_NODE?W:W.parentElement}if(!J)return;let X=j8(G,J),j=X.text.trim();if(!j){if(X.filtered)console.warn("[tts] every part of the selection is either hidden or marked not-to-be-spoken; nothing was spoken.");return}let Z=document.createRange();Z.selectNodeContents(J),Z.setEnd(G.startContainer,G.startOffset);let q=j8(Z,J).text,B=T(q),K=B.length+(/\s$/.test(q)&&B?1:0);this.debugLog("[TTSService] speakRange offset calculation:",{selectedText:j,textBeforeRange:q.substring(0,100),offset:K,rootTag:J.tagName}),await this.speak(j,{contentElement:J,ignoreCatalogs:!0,wordBoundaryOffset:K})}pause(){if(!this.provider)return;if(this.state===R.PLAYING)this.activeRecordedAudio?.element.pause(),this.provider.pause(),this.setState(R.PAUSED)}resume(){if(!this.provider)return;if(this.state===R.PAUSED){let G=this.activeRecordedAudio?.element;if(G)Promise.resolve(G.play()).catch(()=>{});this.provider.resume(),this.setState(R.PLAYING)}}normalizePlaybackRate(G){if(!Number.isFinite(G))return 1;return Math.max(0.25,Math.min(4,G))}async restartFromSeekIndex(G){if(!this.provider||this.seekSegments.length===0)return;let Q=Math.max(0,Math.min(this.seekSegments.length-1,G)),Y=this.playbackChunks.length?this.playbackChunks.slice(Q):null;this.speakRunId+=1,this.clearPlaybackStartBarrier(),this.cancelRecordedAudio(),this.provider.onWordBoundary=void 0,this.provider.stop(),this.currentSeekSegmentIndex=Q;let J=++this.speakRunId,X=this.seekSegments.slice(Q);this.highlightCoordinator?.clearTTS(),this.activeSentenceStartOffset=null,this.setState(R.LOADING);let j=this.installPlaybackStartBarrier(J,!!Y?.[0]?.audio);if(!j)this.setState(R.PLAYING);this.activePlaybackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1));try{if(this.configureWordBoundaryHighlighting({highlightMode:this.activeHighlightMode,wordBoundaryOffset:this.activeWordBoundaryOffset}),Y)for(let Z=0;Z<Y.length;Z++){if(J!==this.speakRunId)return;let q=Q+Z;this.currentSeekSegmentIndex=q;let B=this.seekSegments[q];if(B)this.currentBoundaryOffset=B.startOffset;await this.speakCatalogChunk(Y[Z],J)}else await this.speakWithPlan(X,J,{highlightMode:this.activeHighlightMode});if(J!==this.speakRunId)return;this.setState(R.IDLE),this.clearHighlightsAndTracking()}catch(Z){if(J!==this.speakRunId)return;throw this.lastError=Z instanceof Error?Z.message:String(Z),this.setState(R.ERROR),this.clearHighlightsAndTracking(),Z}finally{this.clearPlaybackStartBarrier(j)}}async setPlaybackRate(G){if(!this.provider)throw Error("TTSService not initialized. Call initialize() first.");let Q=this.normalizePlaybackRate(G),Y=this.pendingPlaybackRateRequest;if(Y?.rate===Q){await Y.promise;return}let J=++this.playbackRateRequestId,X=this.playbackRateWriteQueue.then(async()=>{let q=this.speakRunId;if(J!==this.playbackRateRequestId)return{didUpdate:!1,playbackRunId:q};let B=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1));if(Q===B)return{didUpdate:!1,playbackRunId:q};return await this.updateSettings({rate:Q}),{didUpdate:!0,playbackRunId:q}});this.playbackRateWriteQueue=X.then(()=>{return},()=>{return});let j=X.then(async(q)=>{if(J!==this.playbackRateRequestId||q.playbackRunId!==this.speakRunId)return;let B=this.activePlaybackRate!==null&&this.activePlaybackRate!==Q;if(!q.didUpdate&&!B)return;if(this.state!==R.PLAYING&&this.state!==R.LOADING||!this.currentText||this.seekSegments.length===0||this.hasExplicitBreakSemantics(this.currentText))return;await this.restartFromSeekIndex(this.getCurrentSeekSegmentIndex())}),Z;Z=j.finally(()=>{if(this.pendingPlaybackRateRequest?.promise===Z)this.pendingPlaybackRateRequest=null}),this.pendingPlaybackRateRequest={rate:Q,promise:Z},await Z}async seekBy(G){if(!this.provider||!this.currentText)return;if(this.state!==R.PLAYING&&this.state!==R.PAUSED)return;if(this.hasExplicitBreakSemantics(this.currentText))return;if(this.seekSegments.length===0)return;let Q=Number.isFinite(G)?Math.trunc(G):0;if(Q===0)return;let Y=this.getCurrentSeekSegmentIndex(),J=Math.max(0,Math.min(this.seekSegments.length-1,Y+Q));if(J===Y)return;await this.restartFromSeekIndex(J)}async seekForward(G=1){let Q=Number.isFinite(G)?Math.max(1,Math.trunc(G)):1;await this.seekBy(Q)}async seekBackward(G=1){let Q=Number.isFinite(G)?Math.max(1,Math.trunc(G)):1;await this.seekBy(-Q)}stop(){if(!this.provider)return;if(this.speakRunId+=1,this.clearPlaybackStartBarrier(),this.cancelRecordedAudio(),this.provider.onWordBoundary=void 0,this.provider.stop(),this.setState(R.IDLE),this.currentText=null,this.highlightCoordinator)this.highlightCoordinator.clearTTS();this.lastRenderedRegionTarget=null,this.currentContentElement=null,this.normalizedToDOM.clear(),this.currentBoundaryOffset=0,this.activeWordBoundaryOffset=0,this.seekSegments=[],this.playbackChunks=[],this.sentenceHighlightSegments=[],this.currentSeekSegmentIndex=0,this.activeSentenceStartOffset=null,this.activePlaybackRate=null}requestControlHandoff(){if(typeof window>"u")return;let G={source:"host"};window.dispatchEvent(new CustomEvent(f0,{detail:G}))}isPlaying(){return this.state===R.PLAYING}isPaused(){return this.state===R.PAUSED}getState(){return this.state}getCurrentText(){return this.currentText}getLastError(){return this.lastError}onStateChange(G,Q){if(!this.listeners.has(G))this.listeners.set(G,new Set);this.listeners.get(G).add(Q)}offStateChange(G,Q){let Y=this.listeners.get(G);if(Y){if(Y.delete(Q),Y.size===0)this.listeners.delete(G)}}setState(G){if(this.state===G)return;let Q=this.state;this.state=G;for(let Y of this.listeners.values())for(let J of Y)J(G);if(this.emitTelemetry("pie-tool-playback-state-changed",{toolId:"textToSpeech",providerId:"tts",previousState:Q,state:G}),G===R.PLAYING){let Y=Q===R.PAUSED?"pie-tool-playback-resume":"pie-tool-playback-start";this.emitTelemetry(Y,{toolId:"textToSpeech",providerId:"tts",previousState:Q,state:G});return}if(G===R.PAUSED){this.emitTelemetry("pie-tool-playback-pause",{toolId:"textToSpeech",providerId:"tts",previousState:Q,state:G});return}if(G===R.ERROR){this.emitTelemetry("pie-tool-playback-error",{toolId:"textToSpeech",providerId:"tts",previousState:Q,state:G,message:this.lastError||void 0});return}if(G===R.IDLE&&(Q===R.PLAYING||Q===R.PAUSED||Q===R.LOADING))this.emitTelemetry("pie-tool-playback-stop",{toolId:"textToSpeech",providerId:"tts",previousState:Q,state:G})}}var _Q=new Set(["reserved-row","expanding-row","floating-overlay","left-aligned"]),I0=(G)=>G&&typeof G==="object"?G:{},VQ=(G)=>G==="polly"||G==="google"||G==="server",l=(G,Q)=>G===void 0?Q:G,$Q=(G,Q="left-aligned")=>typeof G==="string"&&_Q.has(G)?G:Q,K4=Object.freeze([0.8,1.25]),_4=Object.freeze([{rate:0.8,label:"Slow",ariaLabel:"Slow speed"},{rate:1,label:"Normal",ariaLabel:"Normal speed",default:!0},{rate:1.25,label:"Fast",ariaLabel:"Fast speed"}]);var V4=Object.freeze([0.8,1,1.25]);var HQ=(G)=>{let Q={...G,layoutMode:$Q(G.layoutMode)},Y=G.backend||"browser";if(!VQ(Y))return Q;let J={...Q,apiEndpoint:l(Q.apiEndpoint,"/api/tts"),transportMode:l(Q.transportMode,"pie"),endpointValidationMode:l(Q.endpointValidationMode,"voices"),validateEndpoint:l(Q.validateEndpoint,!0),includeAuthOnAssetFetch:l(Q.includeAuthOnAssetFetch,!1),rate:l(Q.rate,1),language:l(Q.language,"en-US")};if(Y==="polly")return{...J,defaultVoice:l(J.defaultVoice,"Joanna"),engine:l(J.engine,"neural"),format:l(J.format,"mp3"),speechMarksMode:l(J.speechMarksMode,"word+sentence")};if(Y==="google")return{...J,defaultVoice:l(J.defaultVoice,"en-US-Wavenet-A")};return J},v0=(G)=>{let Q=I0(G),Y=I0(Q.settings);return HQ({...Q,...Y})},w8=(G)=>G.backend||"browser",DQ=(G,Q)=>{if(Q==="polly"||Q==="google")return Q;if(Q==="server")return G.serverProvider||G.provider;return G.serverProvider||G.provider},AQ=(G,Q)=>G.transportMode||(Q==="custom"?"custom":"pie"),h0=(G)=>{let Q=w8(G),Y=DQ(G,Q),J=AQ(G,Y),X=O7(G.mathSpeech);return{voice:G.defaultVoice,rate:G.rate,pitch:G.pitch,providerOptions:{...G.language?{locale:G.language}:{},...Q==="polly"&&G.engine?{engine:G.engine}:{},...Q==="polly"&&typeof G.sampleRate==="number"?{sampleRate:G.sampleRate}:{},...Q==="polly"&&G.format?{format:G.format}:{},...Q==="polly"?{speechMarkTypes:G.speechMarksMode==="word+sentence"?["word","sentence"]:["word"]}:{},...J==="custom"&&typeof G.cache==="boolean"?{cache:G.cache}:{},...J==="custom"&&G.speedRate?{speedRate:G.speedRate}:{},...J==="custom"&&G.lang_id?{lang_id:G.lang_id}:{},...X?{mathSpeech:X}:{}},apiEndpoint:G.apiEndpoint,provider:Y,language:G.language,transportMode:J,endpointMode:G.endpointMode,endpointValidationMode:G.endpointValidationMode,includeAuthOnAssetFetch:G.includeAuthOnAssetFetch,validateEndpoint:G.validateEndpoint,...typeof G.mathTokenHighlighting==="boolean"?{mathTokenHighlighting:G.mathTokenHighlighting}:{}}};class F1{providers=new Map;configs=new Map;initialized=new Map;initializationPromises=new Map;async emitTelemetry(G,Q,Y){try{await G.onTelemetry?.(Q,Y)}catch(J){console.warn("[ToolProviderRegistry] Telemetry callback failed:",J)}}register(G,Q){if(this.providers.has(G)){console.warn(`[ToolProviderRegistry] Provider "${G}" already registered, skipping`);return}if(this.providers.set(G,Q.provider),this.configs.set(G,Q),this.initialized.set(G,!1),console.log(`[ToolProviderRegistry] Registered provider "${G}" (${Q.provider.providerName})`),Q.lazy===!1)this.initialize(G).catch((Y)=>{console.error(`[ToolProviderRegistry] Failed to initialize provider "${G}":`,Y)})}async initialize(G){if(this.initialized.get(G))return;let Q=this.initializationPromises.get(G);if(Q)return Q;let Y=this._doInitialize(G);this.initializationPromises.set(G,Y);try{await Y}finally{this.initializationPromises.delete(G)}}async _doInitialize(G){let Q=this.providers.get(G),Y=this.configs.get(G);if(!Q||!Y)throw Error(`[ToolProviderRegistry] Provider "${G}" not registered`);let J={...Y.config},X=(Z)=>{if(!Z||typeof Z!=="object")return"unknown";let q=Z;return(typeof q.backend==="string"?q.backend:typeof q.provider==="string"?q.provider:typeof q.serverProvider==="string"?q.serverProvider:typeof q.providerId==="string"?q.providerId:"")||"unknown"},j=Date.now();if(await this.emitTelemetry(Y,"pie-tool-init-start",{toolId:G,providerId:G,backend:X(J),operation:"provider-initialize"}),Q.requiresAuth&&Y.authFetcher){let Z=Date.now();await this.emitTelemetry(Y,"pie-tool-backend-call-start",{toolId:G,providerId:G,backend:X(J),operation:"auth-fetch"}),console.log(`[ToolProviderRegistry] Fetching auth for "${G}"...`);try{let q=await Y.authFetcher();J={...J,...q},await this.emitTelemetry(Y,"pie-tool-backend-call-success",{toolId:G,providerId:G,backend:X(J),operation:"auth-fetch",duration:Date.now()-Z})}catch(q){throw await this.emitTelemetry(Y,"pie-tool-backend-call-error",{toolId:G,providerId:G,backend:X(J),operation:"auth-fetch",duration:Date.now()-Z,errorType:"ProviderAuthFetchError",message:q instanceof Error?q.message:String(q)}),console.error(`[ToolProviderRegistry] Auth fetch failed for "${G}":`,q),Error(`Failed to fetch auth credentials for provider "${G}"`)}}try{await Q.initialize(J),this.initialized.set(G,!0),await this.emitTelemetry(Y,"pie-tool-init-success",{toolId:G,providerId:G,backend:X(J),operation:"provider-initialize",duration:Date.now()-j}),console.log(`[ToolProviderRegistry] Provider "${G}" initialized`)}catch(Z){throw await this.emitTelemetry(Y,"pie-tool-init-error",{toolId:G,providerId:G,backend:X(J),operation:"provider-initialize",duration:Date.now()-j,errorType:"ProviderInitializationError",message:Z instanceof Error?Z.message:String(Z)}),console.error(`[ToolProviderRegistry] Initialization failed for "${G}":`,Z),Z}}async getProvider(G,Q=!0){console.log("[ToolProviderRegistry] getProvider called",{providerId:G,autoInitialize:Q,isRegistered:this.providers.has(G),isInitialized:this.initialized.get(G),allProviderIds:Array.from(this.providers.keys())});let Y=this.providers.get(G);if(!Y)throw console.error("[ToolProviderRegistry] Provider not found:",{requestedId:G,availableProviders:Array.from(this.providers.keys())}),Error(`[ToolProviderRegistry] Provider "${G}" not registered`);if(Q&&!this.initialized.get(G))console.log("[ToolProviderRegistry] Auto-initializing provider:",G),await this.initialize(G);return console.log("[ToolProviderRegistry] Returning provider:",{providerId:G,providerName:Y.providerName,isReady:Y.isReady()}),Y}getProvidersByCategory(G){return Array.from(this.providers.entries()).filter(([Q,Y])=>Y.category===G).map(([Q])=>Q)}getProviderIds(){return Array.from(this.providers.keys())}has(G){return this.providers.has(G)}isInitialized(G){return this.initialized.get(G)===!0}isInitializing(G){return this.initializationPromises.has(G)}async unregister(G){let Q=this.providers.get(G);if(Q){let Y=this.initializationPromises.get(G);if(Y)try{await Y}catch{}Q.destroy(),this.providers.delete(G),this.configs.delete(G),this.initialized.delete(G),this.initializationPromises.delete(G),console.log(`[ToolProviderRegistry] Unregistered provider "${G}"`)}}async destroy(){let G=Array.from(this.providers.keys());await Promise.all(G.map((Q)=>this.unregister(Q))),console.log("[ToolProviderRegistry] Registry destroyed")}}class R8{targets=new Set;changeListeners=new Set;registerTarget(G){return this.targets.add(G),this.notifyChange(),()=>{if(!this.targets.delete(G))return;this.notifyChange()}}canRequest(G,Q){return this.findTarget(G,Q)!==null}request(G){let Q=this.findTarget(G.toolId,G.level);if(!Q)return!1;try{Q.open(G.toolId,G.params)}catch(Y){return console.error(`[ToolRequestRegistry] Target failed to open "${G.toolId}":`,Y),!1}return!0}onTargetsChange(G){return this.changeListeners.add(G),()=>{this.changeListeners.delete(G)}}findTarget(G,Q){let Y=this.findTargetAtLevel(G,Q??"section");if(Y||Q!==void 0)return Y;for(let J of this.targets){if(J.level==="section")continue;if(this.hostsTool(J,G))return J}return null}findTargetAtLevel(G,Q){for(let Y of this.targets){if(Y.level!==Q)continue;if(this.hostsTool(Y,G))return Y}return null}hostsTool(G,Q){try{return G.hostsTool(Q)===!0}catch(Y){return console.warn(`[ToolRequestRegistry] Target at level "${G.level}" failed the host check for "${Q}":`,Y),!1}}notifyChange(){for(let G of this.changeListeners)try{G()}catch(Q){console.warn("[ToolRequestRegistry] Target change listener threw:",Q)}}dispose(){this.targets.clear(),this.changeListeners.clear()}}var NQ=(G)=>`No assessment is bound, so no policy source could grant "${G}"`;function E8(G,Q,Y,J){return{featureId:G,granted:!1,action:"block",rule:Q,precedence:0,sourceType:"host",reason:Q==="host-blocked"?"Listed in tools.policy.blocked":`Not listed in tools.policy.allowed (${Y.join(", ")})`,required:!1,assessmentBound:J.assessmentBound}}function u0(G,Q,Y){let J=Q.decisions[0],X=Array.from(Q.perToolFlags.values())[0],j=J?.action==="enable",Z=J?.reason??`Feature "${G}" not configured`;return{featureId:G,granted:j,action:J?.action??"skip",rule:J?.rule??"pnp-support",precedence:J?.precedence??6,sourceType:J?.sourceType??"system",reason:Y.assessmentBound||j?Z:NQ(G),required:Boolean(X?.required),parameters:X?.settings,assessmentBound:Y.assessmentBound}}class M1{provenance;stepCounter=0;constructor(G){this.provenance={contextId:G,resolvedAt:new Date,sources:{},features:new Map,decisionLog:[],summary:{totalFeatures:0,enabled:0,blocked:0,notConfigured:0,bySource:{},byRule:{}}}}addSource(G,Q){let Y={id:Q.id,name:Q.name??Q.id};switch(G){case"organization":this.provenance.sources.organization={...Y,pnpDefaults:Q.config};break;case"assessment":this.provenance.sources.assessment={...Y,settings:Q.config};break;case"section":this.provenance.sources.section={...Y,settings:Q.config};break;case"item":this.provenance.sources.item={...Y,settings:Q.config};break;case"student":this.provenance.sources.student={id:Q.id,pnpProfile:Q.config};break;case"host":this.provenance.sources.host={id:Q.id,config:Q.config};break}return this}addDecision(G){let Q={step:++this.stepCounter,precedence:G.precedence,rule:G.rule,featureId:G.featureId,action:G.action,source:{type:G.sourceType,id:G.sourceId,name:G.sourceName},reason:G.reason,value:G.value,timestamp:new Date};this.provenance.decisionLog.push(Q);let Y=this.provenance.features.get(G.featureId);if(!Y)Y={featureId:G.featureId,finalState:"not-configured",allDecisions:[],explanation:""},this.provenance.features.set(G.featureId,Y);if(Y.allDecisions.push(Q),G.action==="advisory"){if(Y.finalState==="not-configured")Y.finalState="advisory-only"}else if(G.action!=="skip"){if(!Y.winningDecision||Q.precedence<Y.winningDecision.precedence)Y.winningDecision=Q,Y.finalState=Q.action==="enable"?"enabled":"blocked"}return this.provenance.summary.bySource[G.sourceType]=(this.provenance.summary.bySource[G.sourceType]||0)+1,this.provenance.summary.byRule[G.rule]=(this.provenance.summary.byRule[G.rule]||0)+1,this}reconcileFinalStates(G){for(let Q of G){let Y=this.provenance.features.get(Q);if(!Y){Y={featureId:Q,finalState:"enabled",allDecisions:[],explanation:""},this.provenance.features.set(Q,Y);continue}Y.finalState="enabled"}for(let Q of this.provenance.features.values()){if(G.has(Q.featureId))continue;let Y=Q.allDecisions.some((X)=>X.action!=="skip"&&X.action!=="advisory"),J=Q.allDecisions.some((X)=>X.action==="advisory");if(Y)Q.finalState="blocked";else if(J)Q.finalState="advisory-only";else Q.finalState="not-configured"}return this}build(){for(let G of this.provenance.features.values())G.explanation=FQ(G);for(let G of this.provenance.features.values())if(this.provenance.summary.totalFeatures++,G.finalState==="enabled")this.provenance.summary.enabled++;else if(G.finalState==="blocked")this.provenance.summary.blocked++;else this.provenance.summary.notConfigured++;return this.provenance}}function FQ(G){if(!G.winningDecision){if(G.finalState==="advisory-only"){let j=G.allDecisions.find((Z)=>Z.action==="advisory");return j?`Feature "${G.featureId}" was kept in its host-decided state; ${j.reason}`:`Feature "${G.featureId}" carries an advisory note.`}return`Feature "${G.featureId}" was not configured at any level.`}let Q=G.winningDecision,Y=Q.source.name||Q.source.type,J=`Feature "${G.featureId}" is ${G.finalState}.
|
|
215
|
+
`,document.head.appendChild(Q)}highlightTTSWord(Q,Y,J){if(!this.ttsWordHighlight)return;this.applyAdaptiveTTSStyle(Q.parentElement),this.clearTTSWord();let G=document.createRange();G.setStart(Q,Y),G.setEnd(Q,J),this.ttsWordHighlight.add(G)}highlightTTSWordElement(Q){if(!this.ttsWordHighlight)return;this.applyAdaptiveTTSStyle(Q),this.clearTTSWord(),Q.setAttribute("data-pie-tts-word-element","true"),this.ttsWordElementHighlights.add(Q)}highlightTTSSentence(Q){if(!this.ttsSentenceHighlight)return;let Y=Q[0]?.startContainer,J=Y?.nodeType===Node.ELEMENT_NODE?Y:Y?.parentElement;this.applyAdaptiveTTSStyle(J),this.clearTTSSentence();for(let G of Q)this.ttsSentenceHighlight.add(G);this.highlightTTSElementFallbacks(Q)}highlightTTSSentenceElements(Q){if(!this.ttsSentenceHighlight)return;this.applyAdaptiveTTSStyle(Q[0]||null),this.clearTTSSentence();for(let Y of Q)Y.setAttribute("data-pie-tts-sentence-element","true"),this.ttsSentenceElementHighlights.add(Y)}static SENTENCE_FALLBACK_SELECTOR="math, mjx-container, svg, img, canvas, [role='img']";static WORD_FALLBACK_SELECTOR="svg, img, canvas, [role='img']";highlightTTSElementFallbacks(Q){if(typeof Element>"u")return;this.highlightElementFallbacks(Q,"data-pie-tts-sentence-element",this.ttsSentenceElementHighlights,p7.SENTENCE_FALLBACK_SELECTOR)}highlightTTSWordElementFallbacks(Q){if(typeof Element>"u")return;this.highlightElementFallbacks(Q,"data-pie-tts-word-element",this.ttsWordElementHighlights,p7.WORD_FALLBACK_SELECTOR)}highlightElementFallbacks(Q,Y,J,G){for(let X of Q){let j=X.commonAncestorContainer.nodeType===Node.ELEMENT_NODE?X.commonAncestorContainer:X.commonAncestorContainer.parentElement;if(!j)continue;let Z=[],B=X.startContainer.nodeType===Node.ELEMENT_NODE?X.startContainer:X.startContainer.parentElement,W=X.endContainer.nodeType===Node.ELEMENT_NODE?X.endContainer:X.endContainer.parentElement;for(let K of[B,W]){let U=K;while(U){if(U.matches?.(G))Z.push(U);U=U.parentElement}}if(j.matches?.(G))Z.push(j);Z.push(...Array.from(j.querySelectorAll(G)));for(let K of new Set(Z)){try{if(!X.intersectsNode(K)&&!K.contains(B)&&!K.contains(W))continue}catch{continue}K.setAttribute(Y,"true"),J.add(K)}}}clearTTSWord(){if(!this.ttsWordHighlight)return;this.ttsWordHighlight.clear();for(let Q of this.ttsWordElementHighlights)Q.removeAttribute("data-pie-tts-word-element");this.ttsWordElementHighlights.clear()}clearTTSSentence(){if(!this.ttsSentenceHighlight)return;this.ttsSentenceHighlight.clear();for(let Q of this.ttsSentenceElementHighlights)Q.removeAttribute("data-pie-tts-sentence-element");this.ttsSentenceElementHighlights.clear()}clearTTS(){this.clearTTSWord(),this.clearTTSSentence()}addAnnotation(Q,Y=_7.YELLOW){let J=`annotation-${this.nextAnnotationId++}`,G=Q.cloneRange(),X={id:J,range:G,type:u.ANNOTATION,color:Y,timestamp:Date.now()};this.annotations.set(J,X);let j=this.colorHighlights.get(Y);if(j)j.add(G);return J}removeAnnotation(Q){let Y=this.annotations.get(Q);if(!Y){console.warn(`[HighlightCoordinator] Annotation ${Q} not found`);return}console.log(`[HighlightCoordinator] Removing annotation ${Q} (color: ${Y.color})`);let J=this.colorHighlights.get(Y.color);if(J){let G=J.delete(Y.range);console.log("[HighlightCoordinator] Highlight.delete() returned:",G)}this.annotations.delete(Q),console.log(`[HighlightCoordinator] Annotation ${Q} removed from map. Remaining:`,this.annotations.size)}clearAnnotations(){for(let Q of this.colorHighlights.values())Q.clear();this.annotations.clear()}getAnnotations(){return Array.from(this.annotations.values())}getAnnotation(Q){return this.annotations.get(Q)??null}changeAnnotationColor(Q,Y){let J=this.annotations.get(Q);if(!J)return;let G=J.color;if(G===Y)return;let X=this.colorHighlights.get(G);if(X)X.delete(J.range);J.color=Y;let j=this.colorHighlights.get(Y);if(j)j.add(J.range)}exportAnnotations(Q=document.body){return this.getAnnotations().map((Y)=>({...this.rangeSerializer.serialize(Y.range,Q),id:Y.id,color:Y.color,timestamp:Y.timestamp}))}importAnnotations(Q,Y=document.body){let J=0;for(let G of Q){let X=this.rangeSerializer.deserialize(G,Y);if(X)this.addAnnotation(X,G.color),J++}return J}highlightRange(Q,Y,J=_7.YELLOW){if(!this.supported)return;switch(Y){case u.TTS_WORD:case u.TTS_SENTENCE:{let G=Y===u.TTS_WORD?this.ttsWordHighlight:this.ttsSentenceHighlight;if(G){if(G.clear(),G.add(Q),Y===u.TTS_WORD){for(let X of this.ttsWordElementHighlights)X.removeAttribute("data-pie-tts-word-element");this.ttsWordElementHighlights.clear(),this.highlightTTSWordElementFallbacks([Q])}}break}case u.ANNOTATION:this.addAnnotation(Q,J);break}}clearHighlights(Q){if(!this.supported)return;switch(Q){case u.TTS_WORD:this.clearTTSWord();break;case u.TTS_SENTENCE:this.clearTTSSentence();break;case u.ANNOTATION:this.clearAnnotations();break}}clearAll(){if(!this.supported)return;this.clearTTS(),this.clearAnnotations()}isSupported(){return this.supported}updateTTSHighlightStyle(Q,Y){if(!this.supported)return;if(typeof document>"u")return;if(!document.getElementById("pie-highlight-styles"))return;let X=((j)=>{let Z=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(j);return Z?{r:parseInt(Z[1],16),g:parseInt(Z[2],16),b:parseInt(Z[3],16)}:null})(Q);if(!X)return;this.explicitTTSColorOverride={color:`rgb(${X.r}, ${X.g}, ${X.b})`,opacity:Math.max(0.2,Math.min(0.95,Y))},this.applyAdaptiveTTSStyle()}destroy(){if(!this.supported)return;this.clearTTS(),this.clearAnnotations(),this.themeObserver?.disconnect(),this.themeObserver=null}}function L0(Q){return(...Y)=>{console.debug(`[${Q}]`,...Y)}}var a=L0("ToolCoordinator"),Z7;(function(Q){Q[Q.BASE=0]="BASE",Q[Q.TOOL=1000]="TOOL",Q[Q.MODAL=2000]="MODAL",Q[Q.CONTROL=3000]="CONTROL",Q[Q.HIGHLIGHT=4000]="HIGHLIGHT"})(Z7||(Z7={}));class G9{tools=new Map;layerCounters=new Map;listeners=new Set;visibilityState=new Map;constructor(){this.layerCounters.set(Z7.BASE,0),this.layerCounters.set(Z7.TOOL,0),this.layerCounters.set(Z7.MODAL,0),this.layerCounters.set(Z7.CONTROL,0),this.layerCounters.set(Z7.HIGHLIGHT,0)}subscribe(Q){return this.listeners.add(Q),()=>{this.listeners.delete(Q)}}notifyListeners(){this.listeners.forEach((Q)=>Q())}registerTool(Q,Y,J,G=Z7.MODAL){if(a("registerTool called:",{id:Q,name:Y,hasElement:!!J,layer:G}),this.tools.has(Q)){a(`Tool ${Q} is already registered`);return}let X=this.visibilityState.get(Q)??!1;if(!J){this.tools.set(Q,{id:Q,name:Y,element:null,layer:G,isVisible:X,baseZIndex:G}),a("Tool registered without element:",Q);return}let j=G+this.getNextLayerOffset(G);J.style.zIndex=String(j),J.style.display=X?"":"none";let Z=()=>this.bringToFront(J);if(J.addEventListener("mousedown",Z),this.tools.set(Q,{id:Q,name:Y,element:J,layer:G,isVisible:X,baseZIndex:j,mouseDownHandler:Z}),X)this.bringToFront(J);a("Tool registered with element:",Q)}unregisterTool(Q){let Y=this.tools.get(Q);if(!Y)return;if(Y.element&&Y.mouseDownHandler)Y.element.removeEventListener("mousedown",Y.mouseDownHandler);this.tools.delete(Q)}releaseTool(Q){this.unregisterTool(Q),this.visibilityState.delete(Q)}showTool(Q){let Y=this.tools.get(Q);if(!Y){a(`Tool ${Q} not found`);return}if(Y.element)Y.element.style.display="",this.bringToFront(Y.element);Y.isVisible=!0,this.visibilityState.set(Q,!0),this.notifyListeners()}hideTool(Q){let Y=this.tools.get(Q);if(!Y){a(`Tool ${Q} not found`);return}if(Y.element)Y.element.style.display="none";Y.isVisible=!1,this.visibilityState.set(Q,!1),this.notifyListeners()}toggleTool(Q){a("toggleTool called for:",Q);let Y=this.tools.get(Q);if(!Y){a(`Tool ${Q} not found. Registered tools:`,Array.from(this.tools.keys()));return}if(a("Tool found, current visibility:",Y.isVisible),Y.isVisible)this.hideTool(Q);else this.showTool(Q)}isToolVisible(Q){let Y=this.tools.get(Q);if(Y)return Y.isVisible;return this.visibilityState.get(Q)??!1}bringToFront(Q){let Y=Array.from(this.tools.values()).find((X)=>X.element===Q);if(!Y)return;let J=this.getMaxZIndexInLayer(Y.layer),G=Math.max(J+1,Y.layer+1);Q.style.zIndex=String(G),Y.baseZIndex=G}getRegisteredTools(){return Array.from(this.tools.keys())}getToolElement(Q){return this.tools.get(Q)?.element??null}getNextLayerOffset(Q){let Y=this.layerCounters.get(Q)??0;return this.layerCounters.set(Q,Y+1),Y}getMaxZIndexInLayer(Q){let Y=Q;for(let J of this.tools.values())if(J.layer===Q)Y=Math.max(Y,J.baseZIndex);return Y}resetZIndices(){for(let Q of this.tools.values())if(Q.element)Q.element.style.zIndex=String(Q.baseZIndex)}updateToolElement(Q,Y){let J=this.tools.get(Q);if(!J){a(`Tool ${Q} not found`);return}if(J.element&&J.mouseDownHandler)J.element.removeEventListener("mousedown",J.mouseDownHandler);let G=()=>this.bringToFront(Y);if(Y.addEventListener("mousedown",G),J.element=Y,J.mouseDownHandler=G,Y.style.zIndex=String(J.baseZIndex),J.isVisible)Y.style.display="";else Y.style.display="none"}hideAllTools(){for(let Q of this.tools.keys())this.hideTool(Q);this.notifyListeners()}getToolState(Q){let Y=this.tools.get(Q);if(!Y)return;return{id:Y.id,name:Y.name,isVisible:Y.isVisible,element:Y.element??null,layer:Y.layer}}getVisibleTools(){return Array.from(this.tools.values()).filter((Q)=>Q.isVisible).map((Q)=>({id:Q.id,name:Q.name,isVisible:Q.isVisible,element:Q.element??null,layer:Q.layer}))}}import{applyMediaFragment as q2,enforceMediaFragment as W2}from"@pie-players/pie-players-shared/media";import{isUnsupportedMediaAssetVersion as b3,normalizeMediaFragment as S3,normalizeMediaSources as C3,trimmedOrUndefined as T3}from"@pie-players/pie-players-shared/media";function w0(Q){if(!Q)return null;let Y=Q.payload;if(!Y||typeof Y!=="object")return null;let J=Y.media;if(!J||typeof J!=="object")return console.warn("[spoken-audio] card carries a `payload` with no `media`; recorded speech needs `media.sources`, so this card is ignored and read-aloud falls back to the script or generated speech"),null;if(b3(J.version))return console.warn(`[spoken-audio] card's media declares version ${String(J.version)}, which this build does not render; the card is ignored and read-aloud falls back to the script or generated speech`),null;if(J.kind!==void 0&&J.kind!=="audio")return console.warn(`[spoken-audio] card's media is kind "${J.kind}", not "audio"; a spoken card carries recorded speech, so this card is ignored`),null;let G=C3(J.sources);if(G.length===0)return console.warn("[spoken-audio] card's `media.sources` yielded no usable URL; read-aloud falls back to the script or generated speech"),null;return{sources:G,fragment:S3(Y.fragment),label:T3(J.label)}}var S7=(Q,Y)=>{let J=Y?.useSentenceSegmenter!==!1;try{if(!J)throw Error("Segmenter disabled by policy");let B=globalThis.Intl?.Segmenter;if(typeof B==="function"){let W=new B(Y?.locale,{granularity:"sentence"}),K=Array.from(W.segment(Q)).map((U)=>({text:U.segment,offset:U.index})).filter((U)=>U.text.trim().length>0);if(K.length>0)return K}}catch{}let G=/[^.!?]+(?:[.!?]+|$)/g,X=Q.match(G)||[Q],j=[],Z=0;for(let B of X){let W=Q.indexOf(B,Z);if(W===-1)continue;j.push({text:B,offset:W}),Z=W+B.length}return j.length>0?j:[{text:Q,offset:0}]};var R0=5000,E0=2000,b0=(Q)=>String(Q||"").trim().toLowerCase(),y3=()=>{let Q=typeof navigator<"u"?navigator.language||navigator.languages?.[0]:"";return b0(Q||"en-US")},f3=(Q,Y)=>{if(Y)return Q.find((Z)=>Z.voiceURI===Y)||Q.find((Z)=>Z.name===Y)||null;let J=y3(),G=J.split("-")[0]||"en",X=(Z)=>{let B=b0(Z.lang);return B===J||B.startsWith(`${G}-`)},j=[(Z)=>Z.localService&&X(Z),(Z)=>Z.default&&X(Z),(Z)=>X(Z),(Z)=>Z.localService,(Z)=>Z.default];for(let Z of j){let B=Q.find(Z);if(B)return B}return Q[0]||null},x3=(Q)=>!Q.default;class g7{providerId="browser";providerName="Browser Speech Synthesis";version="1.0.0";async initialize(Q){if(typeof window>"u")throw Error("BrowserTTSProvider requires browser environment");if(!("speechSynthesis"in window))throw Error("Browser does not support Speech Synthesis API");return new S0(Q)}supportsFeature(Q){return!0}getCapabilities(){return{supportsPause:!0,supportsResume:!0,supportsWordBoundary:!0,supportsVoiceSelection:!0,supportsRateControl:!0,supportsPitchControl:!0,supportsSSML:!1}}destroy(){}}class S0{utterance=null;config=null;_isPlaying=!1;_isPaused=!1;speakRunId=0;settlePendingVoiceWait=null;settlePendingChunk=null;onPlaybackStart=void 0;constructor(Q){this.config=Q}waitForBrowserVoices(Q,Y){return new Promise((J,G)=>{let X=speechSynthesis,j=typeof X.addEventListener==="function"&&typeof X.removeEventListener==="function",Z=j?null:X.onvoiceschanged,B=!1,W=null,K=null,U=()=>{if(W!==null)clearTimeout(W),W=null;if(j)X.removeEventListener("voiceschanged",N);else if(X.onvoiceschanged===D)X.onvoiceschanged=Z;if(K&&this.settlePendingVoiceWait===K)this.settlePendingVoiceWait=null},_=(O,P)=>{if(B)return;if(B=!0,U(),P)G(P);else J(O)},$=()=>{if(Q!==this.speakRunId){_(!1);return}if(X.getVoices().length>0)_(!0)},N=()=>$(),D=(O)=>{try{Z?.call(X,O)}finally{$()}};if(K=()=>_(!1),this.settlePendingVoiceWait=K,W=setTimeout(()=>_(!1,Error(`Configured browser voice "${Y}" could not be resolved because the browser did not publish its voice inventory within ${E0/1000} seconds.`)),E0),j)X.addEventListener("voiceschanged",N);else X.onvoiceschanged=D;$()})}async resolveBrowserVoice(Q){let Y=typeof this.config?.voice==="string"?this.config.voice.trim():"",J=speechSynthesis.getVoices();if(Y&&J.length===0){if(!await this.waitForBrowserVoices(Q,Y)||Q!==this.speakRunId)return{shouldContinue:!1,voice:null};J=speechSynthesis.getVoices()}if(Q!==this.speakRunId)return{shouldContinue:!1,voice:null};let G=f3(J,Y||void 0);if(Y&&!G)throw Error(`Configured browser voice "${Y}" is unavailable. Select a voice exposed by this browser using its voiceURI or name.`);return{shouldContinue:!0,voice:G}}async speak(Q){if(!this.config)throw Error("TTS not initialized");this.stop();let Y=this.speakRunId,J=await this.resolveBrowserVoice(Y);if(!J.shouldContinue)return;let G=this.splitIntoChunks(Q);for(let X of G){if(Y!==this.speakRunId)break;if(!await this.speakChunk(X.text,X.offset,Y,J.voice))break}}async speakSegments(Q){if(!this.config)throw Error("TTS not initialized");this.stop();let Y=this.speakRunId,J=await this.resolveBrowserVoice(Y);if(!J.shouldContinue)return;for(let G of Q){if(Y!==this.speakRunId)break;let X=this.splitIntoChunks(G.text);for(let Z of X){if(Y!==this.speakRunId)break;if(!await this.speakChunk(Z.text,G.startOffset+Z.offset,Y,J.voice))break}let j=Math.max(0,Number(G.pauseMsAfter||0));if(j>0&&Y===this.speakRunId){if(!await this.waitForPause(j,Y))break}}}async waitForPause(Q,Y){return await new Promise((J)=>setTimeout(J,Q)),Y===this.speakRunId}splitIntoChunks(Q){if(Q.length<=260)return[{text:Q,offset:0}];let J=this.segmentSentences(Q),G=[],X="",j=0;for(let Z of J){let B=Z.text.trim();if(!B)continue;let W=Z.text.search(/\S/),K=Z.offset+(W===-1?0:W);if(!X){X=B,j=K;continue}let U=`${X} ${B}`;if(U.length<=260)X=U;else G.push({text:X,offset:j}),X=B,j=K}if(X)G.push({text:X,offset:j});return G.length?G:[{text:Q,offset:0}]}getHighlightMode(){return(this.config?.providerOptions||{}).highlightMode==="word"?"word":"sentence"}getSegmentationPolicy(){let Q=this.config?.providerOptions||{},Y=Q.segmenter||{},G=Y.mode!=="regexOnly",X=typeof Y.locale==="string"&&Y.locale.trim().length>0?Y.locale:typeof Q.locale==="string"&&Q.locale.trim().length>0?Q.locale:void 0;return{useSentenceSegmenter:G,useWordSegmenter:G,locale:X}}segmentSentences(Q){let Y=this.getSegmentationPolicy();return S7(Q,{locale:Y.locale,useSentenceSegmenter:Y.useSentenceSegmenter})}inferWordLength(Q,Y){let J=Math.max(0,Math.min(Y,Math.max(0,Q.length-1)));return Q.slice(J).match(/^\s*([^\s]+)/)?.[1]?.length||1}async speakChunk(Q,Y,J,G){return new Promise((X,j)=>{if(J!==this.speakRunId){X(!1);return}let Z=new SpeechSynthesisUtterance(Q);if(this.utterance=Z,G&&x3(G))Z.voice=G;if(this.config?.rate)Z.rate=this.config.rate;if(this.config?.pitch)Z.pitch=this.config.pitch;let B=!1,W=!1,K=null,U=null,_=()=>{if(this.utterance===Z)this.utterance=null},$=()=>{if(K!==null)clearTimeout(K),K=null},N=()=>{Z.onstart=null,Z.onend=null,Z.onerror=null,Z.onpause=null,Z.onresume=null,Z.onboundary=null},D=(P,F)=>{if(W)return;if(W=!0,$(),N(),_(),U&&this.settlePendingChunk===U)this.settlePendingChunk=null;if(J===this.speakRunId)this._isPlaying=!1,this._isPaused=!1;if(F)j(F);else X(P)},O=(P)=>Error(P==="ended"?"Browser speech synthesis ended before audio started. The browser speech engine may be unavailable or stuck; try another voice or restart the browser.":`Browser speech synthesis did not start within ${R0/1000} seconds. The browser speech engine may be unavailable or stuck; try another voice or restart the browser.`);U=()=>D(!1),this.settlePendingChunk=U,Z.onstart=()=>{if(J!==this.speakRunId){D(!1);return}B=!0,$(),this._isPlaying=!0,this._isPaused=!1;try{this.onPlaybackStart?.()}catch(P){console.error("Browser TTS playback-start callback failed",P)}},Z.onend=()=>{if(J!==this.speakRunId){D(!1);return}if(!B){D(!1,O("ended"));return}D(!0)},Z.onerror=(P)=>{if(J!==this.speakRunId){D(!1);return}if(P.error==="interrupted"||P.error==="canceled"){D(!1);return}D(!1,Error(`Speech synthesis error: ${P.error}`))},Z.onpause=()=>{if(J!==this.speakRunId)return;this._isPaused=!0},Z.onresume=()=>{if(J!==this.speakRunId)return;this._isPaused=!1},Z.onboundary=(P)=>{if(J!==this.speakRunId)return;if(console.log("[BrowserProvider] Boundary event:",P.name,"charIndex:",P.charIndex,"charLength:",P.charLength),P.name!=="word"||!this.onWordBoundary)return;if(this.getHighlightMode()==="sentence")return;let F=Math.max(0,Math.min(P.charIndex,Math.max(0,Q.length-1))),L=Number(P.charLength||0),C=this.inferWordLength(Q,F),v=Number.isFinite(L)&&L>0&&L<=80&&F+L<=Q.length?L:C,k=Q.substring(F,Math.min(Q.length,F+v)).trim(),p=Y+F;console.log("[BrowserProvider] Calling onWordBoundary with word:",k,"at position:",p),this.onWordBoundary(k,p,v)},K=setTimeout(()=>{if(W||B||J!==this.speakRunId)return;D(!1,O("timedOut")),speechSynthesis.cancel()},R0);try{speechSynthesis.speak(Z)}catch(P){D(!1,P instanceof Error?P:Error("Browser speech synthesis failed to queue speech"))}})}pause(){if(this._isPlaying&&!this._isPaused)speechSynthesis.pause()}resume(){if(this._isPlaying&&this._isPaused)speechSynthesis.resume()}stop(){let Q=this.utterance,Y=this._isPlaying||Q!==null;if(this.speakRunId+=1,this.settlePendingVoiceWait?.(),this.settlePendingChunk?.(),Y)speechSynthesis.cancel();this.utterance=null,this._isPlaying=!1,this._isPaused=!1}isPlaying(){return this._isPlaying&&!this._isPaused}isPaused(){return this._isPaused}updateSettings(Q){if(!this.config)this.config={};if(Q.rate!==void 0)this.config.rate=Q.rate;if(Q.pitch!==void 0)this.config.pitch=Q.pitch;if(Q.voice!==void 0)this.config.voice=Q.voice;if(Q.providerOptions!==void 0)this.config.providerOptions={...this.config.providerOptions||{},...Q.providerOptions||{}}}onWordBoundary}var T=(Q)=>Q.trim().replace(/\s+/g," "),y0=()=>/[\p{L}]+|\d+(?:\.\d+)?|[±√=+\-*/()²³^×÷≤≥≠≈<>|%°'′\u2062]/gu,X9=(Q)=>{if(Q.hidden)return!0;if(Q.tagName?.toLowerCase()==="mjx-assistive-mml")return!0;if(Q.getAttribute("aria-hidden")==="true")return!0;if(Q.hasAttribute("inert"))return!0;let Y=Q.classList;if(Y?.contains("sr-only")||Y?.contains("pie-sr-only")||Y?.contains("visually-hidden"))return!0;if(typeof window<"u"){let J=window.getComputedStyle(Q);if(J.display==="none"||J.visibility==="hidden")return!0;let G=Number.parseFloat(J.width||"0"),X=Number.parseFloat(J.height||"0"),j=Number.isFinite(G)&&Number.isFinite(X)&&G<=1&&X<=1,Z=J.clipPath.includes("inset(50%")||J.clipPath.includes("inset(100%")||J.clip.includes("rect(0px, 0px, 0px, 0px)")||J.clip.includes("rect(0 0 0 0)");if((J.position==="absolute"||J.position==="fixed")&&j&&(J.overflow==="hidden"||Z))return!0;if(J.opacity==="0"&&j)return!0}return!1},C7=(Q,Y)=>{let J=Q.nodeType===1?Q:Q.parentElement;while(J){if(X9(J))return!0;if(Y&&J===Y)break;J=J.parentElement}return!1};var f0=new Set(["computer-read-aloud","all"]),C0=new Set([...f0,"screen-reader"]),T0=new Set,k3=(Q)=>{let Y=Q.getAttribute?.("data-tts-suppress");if(Y===null||Y===void 0)return!1;let J=Y.trim().toLowerCase();if(f0.has(J))return!0;if(C0.has(J))return!1;if(!T0.has(J))T0.add(J),console.warn(`[tts] data-tts-suppress="${Y}" is not one of ${Array.from(C0).join(", ")}; suppressing read-aloud for this content anyway, because a suppression attribute that fails open would leak the answer to items where reading is the construct. Correct the value to silence this.`);return!0},W1=(Q,Y)=>{let J=Q.nodeType===1?Q:Q.parentElement;while(J){if(k3(J))return!0;if(Y&&J===Y)break;J=J.parentElement}return!1},$7=(Q,Y)=>C7(Q,Y)||W1(Q),Z9=(Q,Y)=>{if(typeof document>"u"||typeof document.createTreeWalker!=="function"||typeof NodeFilter>"u"||typeof Q.intersectsNode!=="function")return{text:Q.toString(),filtered:!1};let J=[],G=!1,X=document.createTreeWalker(Y,NodeFilter.SHOW_TEXT),j=X.nextNode();while(j){let Z=j;if(Q.intersectsNode(Z))if($7(Z,Y))G=!0;else{let B=Z.textContent||"",W=Z===Q.startContainer?Q.startOffset:0,K=Z===Q.endContainer?Q.endOffset:B.length;J.push(B.slice(W,K))}j=X.nextNode()}return{text:J.join(""),filtered:G}},j9=(Q,Y,J)=>{if(!Q||!Y)return!1;if(/\s/.test(Q)||/\s/.test(Y))return!1;let G=J?.boundarySpacingMode??"segmenterPreferred";if(G==="none")return!1;if(G==="segmenterPreferred")try{let Z=globalThis.Intl?.Segmenter;if(typeof Z==="function"){let B=new Z(J?.locale,{granularity:"word"});if(Array.from(B.segment(`${Q}${Y}`)).filter((U)=>U.isWordLike!==!1&&U.segment.trim().length>0).length>=2)return!0}}catch{}let X=/[A-Za-z0-9]/.test(Q),j=/[A-Za-z0-9]/.test(Y);return X&&j},F7=(Q,Y)=>{let J=new Map;if(typeof document>"u"||typeof document.createTreeWalker!=="function"||typeof NodeFilter>"u")return{text:"",map:J};let G=[],X=0,j=!0,Z=!1,B=null,W=null,K=document.createTreeWalker(Q,NodeFilter.SHOW_TEXT),U=K.nextNode();while(U){let $=U;if($.parentElement&&!$7($,Q)){let D=$.textContent||"",O=D.match(/\S/),P=O?O[0]:null;if(!j&&!Z&&j9(W,P,Y)){if(G.push(" "),B)J.set(X,B);X++,Z=!0}for(let F=0;F<D.length;F++){let L=D[F],C=/\s/.test(L);if(j){if(!C)j=!1,G.push(L),J.set(X,{node:$,offset:F}),B={node:$,offset:F},X++,Z=!1,W=L}else if(C){if(!Z)G.push(" "),J.set(X,{node:$,offset:F}),B={node:$,offset:F},X++;Z=!0}else G.push(L),J.set(X,{node:$,offset:F}),B={node:$,offset:F},X++,Z=!1,W=L}}U=K.nextNode()}let _=G.join("").trimEnd();while(J.has(_.length))J.delete(_.length);return{text:_,map:J}};var I3=new Set(["speak","p","s","emphasis","prosody","say-as","voice","lang"]),x0=new Set(["audio","phoneme"]),I0=(Q)=>Q.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/ /g," ").replace(/ /g," ").replace(/&/g,"&"),K1=(Q,Y,J)=>{for(let G=0;G<Y.length;G++)Q.push({char:Y[G],rawOffset:J===null?null:J+G})},v3=(Q,Y,J)=>{let G=Y.slice(J).match(/^&(quot|apos|lt|gt|nbsp|amp|#160);/i);if(!G)return 0;return K1(Q,I0(G[0]),J),G[0].length},k0=(Q)=>{Q.push({char:" ",rawOffset:null})},h3=(Q)=>{let Y=new Map,J=[],G=!0;for(let X of Q){if(/\s/.test(X.char)){if(!G&&J.length>0){if(J.push(" "),X.rawOffset!==null)Y.set(X.rawOffset,J.length-1)}G=!0;continue}if(J.push(X.char),X.rawOffset!==null)Y.set(X.rawOffset,J.length-1);G=!1}while(J.length>0&&J[J.length-1]===" ")J.pop();for(let[X,j]of Y)if(j>=J.length)Y.delete(X);return{text:J.join(""),rawToSpokenOffsetMap:Y}},m3=(Q)=>{return Q.match(/^<\/?\s*([A-Za-z0-9:-]+)/)?.[1]?.toLowerCase()||""},u3=(Q,Y)=>{let J=new RegExp(`${Y}\\s*=\\s*("([^"]*)"|'([^']*)')`,"i"),G=Q.match(J);return I0(G?.[2]??G?.[3]??"")||null},v0=(Q)=>{let Y=[],J=!1,G=!1,X=0;while(X<Q.length){let Z=Q[X];if(Z!=="<"){if(Z==="&"){let $=v3(Y,Q,X);if($>0){X+=$;continue}}K1(Y,Z,X),X++;continue}let B=Q.indexOf(">",X+1);if(B<0){K1(Y,Z,X),X++;continue}G=!0;let W=Q.slice(X,B+1),K=m3(W),U=/^<\s*\//.test(W),_=/\/\s*>$/.test(W);if(!U&&K==="sub"){let $=u3(W,"alias");if(!$){J=!0,X=B+1;continue}K1(Y,$,null);let N=Q.toLowerCase().indexOf("</sub>",B+1);X=N>=0?N+6:B+1;continue}if(!U&&K==="break"){k0(Y),X=B+1;continue}if(!U&&x0.has(K)){if(J=!0,_){X=B+1;continue}}if(K&&!I3.has(K)&&!x0.has(K)&&K!=="break"&&K!=="sub")J=!0;if(!U&&(K==="p"||K==="s"))k0(Y);X=B+1}let j=h3(Y);return{spokenText:T(j.text),rawToSpokenOffsetMap:j.rawToSpokenOffsetMap,unsupportedSemantic:J,hasMarkup:G}};var p3=y0(),g3=new Map([["zero","0"],["one","1"],["two","2"],["three","3"],["four","4"],["five","5"],["six","6"],["seven","7"],["eight","8"],["nine","9"],["ten","10"]]),c3=(Q)=>{let Y=Q.toLowerCase();return g3.get(Y)||Y},W9=(Q)=>{let Y=[];for(let J of Q.matchAll(p3)){let G=J[0],X=J.index??0;Y.push({text:G,normalized:c3(G),start:X,end:X+G.length})}return Y},d3=(Q)=>W9(Q).map((Y,J)=>({...Y,id:`speech-token-${J}`,sourceStart:Y.start,sourceEnd:Y.end,coordinateSystem:"normalized-speech"})),H7=(Q)=>{let Y=v0(Q.speechText);return{speechText:Q.speechText,spokenText:Y.spokenText,tokens:d3(Y.spokenText),rawToSpokenOffsetMap:Y.rawToSpokenOffsetMap,boundaryOffsetSpace:Y.unsupportedSemantic?"unsupported":Y.hasMarkup?"raw-ssml":"plain-spoken-text",unsupportedSemantic:Y.unsupportedSemantic,hasMarkup:Y.hasMarkup}},K9=(Q)=>Boolean(Q&&/^<[^>]+>$/.test(Q.trim())),T7=(Q)=>{if(!Q||K9(Q))return null;return H7({speechText:Q}).tokens[0]?.normalized??null},l3=(Q,Y)=>Q.find((J)=>J.start<=Y&&Y<J.end)||null,i3=(Q,Y)=>{let J=Q.rawToSpokenOffsetMap.get(Y);if(J!==void 0)return J;for(let G=Y;G<Q.speechText.length;G++){let X=Q.rawToSpokenOffsetMap.get(G);if(X!==void 0)return X;if(Q.speechText[G]===">")break}return null},B9=(Q,Y,J)=>{if(Y===null)return null;let G=l3(Q.tokens,Y);if(!G)return null;return{token:G,start:Y,length:Math.max(1,Math.min(J,G.end-Y)),confidence:0.75}},q9=(Q,Y)=>Boolean(Q&&Y&&Q.token.normalized===Y),U9=(Q)=>{if(Q.tokenization.boundaryOffsetSpace==="unsupported"||!Number.isFinite(Q.position)||K9(Q.boundaryWord))return null;let Y=Math.max(1,Number.isFinite(Q.length)?Q.length:1),J=T7(Q.boundaryWord),G=B9(Q.tokenization,i3(Q.tokenization,Q.position),Y),X=B9(Q.tokenization,Q.position>=0&&Q.position<Q.tokenization.spokenText.length?Q.position:null,Y);if(q9(G,J))return{...G,confidence:1};if(q9(X,J))return{...X,confidence:1};if(J)return null;return Q.tokenization.boundaryOffsetSpace==="raw-ssml"?G||X:X||G},h0=(Q)=>{if(Q.tokenization.boundaryOffsetSpace==="unsupported"||!Number.isFinite(Q.position)||K9(Q.boundaryWord))return null;let Y=Math.max(1,Number.isFinite(Q.length)?Q.length:1),J=T7(Q.boundaryWord),G=B9(Q.tokenization,Q.position>=0&&Q.position<Q.tokenization.spokenText.length?Q.position:null,Y);if(q9(G,J))return{...G,confidence:1};if(J)return null;return G};var s3=[{phrase:["plus","or","minus"],visible:"±",score:8},{phrase:["square","root"],visible:"√",score:8},{phrase:["divided","by"],visible:"/",score:7},{phrase:["all","over"],visible:"/",score:7},{phrase:["equals"],visible:"=",score:7},{phrase:["equal"],visible:"=",score:7},{phrase:["times"],visible:"",score:7},{phrase:["multiplied","by"],visible:"",score:7},{phrase:["over"],visible:"/",score:6},{phrase:["squared"],visible:"²",score:6},{phrase:["squared"],visible:"2",score:4},{phrase:["negative"],visible:"-",score:5},{phrase:["minus"],visible:"-",score:5},{phrase:["plus"],visible:"+",score:5}],n3=(Q,Y)=>{let J=[];for(let G=0;G<Q.length;G++){for(let X=0;X<Y.length;X++)if(Q[G].normalized===Y[X].normalized)J.push({spokenStartToken:G,spokenEndToken:G+1,visibleToken:X,score:10});for(let X of s3){let j=Q.slice(G,G+X.phrase.length);if(j.length!==X.phrase.length)continue;if(!j.every((Z,B)=>Z.normalized===X.phrase[B]))continue;for(let Z=0;Z<Y.length;Z++){if(Y[Z].text!==X.visible)continue;J.push({spokenStartToken:G,spokenEndToken:G+X.phrase.length,visibleToken:Z,score:X.score})}}}return J},r3=(Q,Y)=>{let J=n3(Q,Y).sort((W,K)=>Q[W.spokenStartToken].start-Q[K.spokenStartToken].start||Y[W.visibleToken].start-Y[K.visibleToken].start),G=Array(J.length).fill(0),X=Array(J.length).fill(-1);for(let W=0;W<J.length;W++){let K=J[W];G[W]=K.score;for(let U=0;U<W;U++){let _=J[U];if(_.spokenEndToken<=K.spokenStartToken&&_.visibleToken<K.visibleToken){let $=K.spokenStartToken-_.spokenEndToken,N=K.visibleToken-_.visibleToken-1,D=Math.max(0,Math.abs($-N)-2),O=G[U]+K.score-D;if(O>G[W])G[W]=O,X[W]=U}}}let j=-1;for(let W=0;W<G.length;W++)if(j<0||G[W]>G[j])j=W;if(j<0)return[];let Z=[],B=j;while(B>=0)Z.unshift(J[B]),B=X[B];return Z.map((W)=>{let K=Q[W.spokenStartToken],U=Q[W.spokenEndToken-1],_=Y[W.visibleToken];return{spokenStart:K.start,spokenEnd:U.end,visibleStart:_.start,visibleEnd:_.end,score:W.score}})},o3=(Q,Y,J)=>{if(Q.length===0)return 0;let G=Q.length/Math.max(1,Math.min(Y.length,J.length)),X=Q.reduce((j,Z)=>j+Z.score,0)/Q.length/10;return Math.min(1,G*X)},U1=(Q)=>{let Y=H7({speechText:Q.speechText}),J=T(Q.visibleText),G=Y.tokens,X=W9(J),j=Y.unsupportedSemantic?[]:r3(G,X),Z=o3(j,G,X),B=Y.spokenText===J&&Y.spokenText.length>0,W=j.length===1&&j[0].score===10&&G.length<=2&&X.length<=2,K=Y.unsupportedSemantic?"region-fallback":B?"exact-word":j.length>=2||W?Z>=0.12?"anchor-span":"region-fallback":"region-fallback";return{speech:Y,visibleText:J,playbackMode:K,anchors:j,confidence:Z}},m0=(Q,Y)=>{if(Q.playbackMode==="region-fallback")return null;let J=Q.anchors.find((j)=>j.spokenStart<=Y&&Y<j.spokenEnd);if(J)return{start:J.visibleStart,end:J.visibleEnd};let G=null,X=null;for(let j of Q.anchors){if(j.spokenEnd<=Y){G=j;continue}if(j.spokenStart>Y){X=j;break}}if(G&&X)return{start:Math.min(G.visibleStart,X.visibleStart),end:Math.max(G.visibleEnd,X.visibleEnd)};return null};var a3=new Map([["+",["plus"]],["-",["minus","negative"]],["−",["minus","negative"]],["×",["times","multiplied by"]],["÷",["divided by"]],["=",["equals","equal to"]],["≠",["is not equal to","not equal to"]],["≈",["approximately equals"]],["≤",["less than or equal to"]],["≥",["greater than or equal to"]],["<",["less than"]],[">",["greater than"]],["∠",["angle"]],["△",["triangle"]],["□",["box"]],["○",["circle"]],["°",["degrees","degree"]],["%",["percent"]],["'",["prime"]],["′",["prime"]],["•",["times"]],["·",["times"]],["",["times","multiplied by"]]]),t3=new Map([["","function-application"],["","implicit-multiply"],["","invisible-separator"],["","invisible-plus"]]),u0=new Map([["2",["squared"]],["3",["cubed"]]]),e3=new Map([["msqrt","radical"],["mroot","radical"],["msub","subscript"],["msubsup","subsupscript"],["munder","underscript"],["mover","overscript"],["munderover","underoverscript"],["mmultiscripts","multiscript"],["menclose","enclosure"]]),Q5=(Q)=>Q.replace(/\s+/g," ").trim(),D7=(Q)=>(Q.localName||Q.tagName||"").toLowerCase(),Y5=(Q)=>Q.nodeType===Node.ELEMENT_NODE,y7=(Q)=>Array.from(Q.childNodes).filter(Y5),V9=(Q)=>Q5(Q.textContent||""),Y7=(Q,Y)=>({type:"element-range",quality:Y,element:Q}),J5=(Q)=>{switch(Q){case"mi":return"identifier";case"mn":return"number";case"mo":return"operator";case"mtext":case"ms":return"text";case"mspace":return"space";default:return"unknown"}},G5=(Q,Y)=>{if(Y==="operator"){if(Q==="−")return"-";return Q}return Q.toLowerCase()},X5=(Q,Y,J)=>{if(J==="fraction")return["over","divided by"];if(J==="superscript")return u0.get(Q)??[];if(Q==="|")return["absolute value"];if(Y==="operator")return a3.get(Q)||[];return[]},N7=(Q)=>{let Y=Q.normalized??G5(Q.text,Q.kind||"unknown");return{id:`math-token-${Q.state.nextId++}`,kind:Q.kind,role:Q.role,text:Q.text,normalized:Y,spokenAliases:X5(Q.text,Q.kind,Q.role),sourceElement:Q.sourceElement,path:Q.path,target:Q.target||Y7(Q.sourceElement,"element-range"),optional:Q.optional}},M7=(Q,Y,J="tokens")=>{Q[J].push(Y)},p0=(Q,Y,J)=>{y7(Q).forEach((G,X)=>J7(G,Y,`${J}/${D7(G)}[${X}]`))},Z5=(Q,Y,J)=>{let G=y7(Q);if(G[0])J7(G[0],Y,`${J}/numerator`);if(M7(Y,N7({state:Y,kind:"structure",role:"fraction",text:"/",sourceElement:Q,path:J,target:Y7(Q,"element-range")})),G[1])J7(G[1],Y,`${J}/denominator`)},j5=(Q,Y,J)=>{let G=Q.getAttribute("open")||"(",X=Q.getAttribute("close")||")";M7(Y,N7({state:Y,kind:"operator",role:G==="|"?"absolute-value-fence":"open-fence",text:G,sourceElement:Q,path:`${J}/open`,target:Y7(Q,"element-range")})),p0(Q,Y,J),M7(Y,N7({state:Y,kind:"operator",role:X==="|"?"absolute-value-fence":"close-fence",text:X,sourceElement:Q,path:`${J}/close`,target:Y7(Q,"element-range")}))},B5=(Q,Y,J)=>{let G=y7(Q);if(G[0])J7(G[0],Y,`${J}/base`);let X=G[1];if(!X)return;let j=V9(X);if(u0.has(j)){M7(Y,N7({state:Y,kind:"structure",role:"superscript",text:j,normalized:j,sourceElement:X,path:`${J}/exponent`,target:Y7(Q,"element-range")}));return}J7(X,Y,`${J}/exponent`)},q5=(Q,Y,J,G)=>{M7(Y,N7({state:Y,kind:"structure",role:G,text:V9(Q)||G,normalized:`\x00${G}`,sourceElement:Q,path:J,target:Y7(Q,"element-range")}))},W5=(Q,Y,J)=>{let G=0;for(let X of y7(Q)){if(D7(X)==="mtr"||D7(X)==="mlabeledtr")G++,M7(Y,N7({state:Y,kind:"layout",role:"table-row",text:`row-${G}`,normalized:`row-${G}`,sourceElement:X,path:`${J}/row[${G}]`,target:Y7(X,"region-fallback")}),"layoutTargets");J7(X,Y,`${J}/${D7(X)}[${G}]`)}},K5=(Q,Y,J)=>{let G=V9(Q);if(!G)return;let X=J5(D7(Q)),j=X==="operator"?t3.get(G):void 0,Z=j??(X==="operator"&&(G==="("||G===")")?"grouping-fence":X);M7(Y,N7({state:Y,kind:X,role:Z,text:G,sourceElement:Q,path:J,target:j&&Q.parentElement?Y7(Q.parentElement,"region-fallback"):void 0,optional:Boolean(j)||Z==="grouping-fence"}))},J7=(Q,Y,J)=>{let G=D7(Q);switch(G){case"annotation":case"annotation-xml":return;case"semantics":{let X=y7(Q).find((j)=>{let Z=D7(j);return Z!=="annotation"&&Z!=="annotation-xml"});if(X)J7(X,Y,`${J}/presentation`);return}case"mi":case"mn":case"mo":case"mtext":case"ms":case"mspace":K5(Q,Y,J);return;case"mfrac":Z5(Q,Y,J);return;case"msup":B5(Q,Y,J);return;case"mfenced":j5(Q,Y,J);return;case"mtable":W5(Q,Y,J);return;case"mphantom":return;case"maction":{let X=y7(Q)[0];if(X)J7(X,Y,`${J}/action`);return}default:{let X=e3.get(G);if(X){q5(Q,Y,J,X);return}p0(Q,Y,J)}}},g0=(Q)=>{let Y={tokens:[],layoutTargets:[],nextId:0};return J7(Q,Y,"/math"),{tokens:Y.tokens,layoutTargets:Y.layoutTargets,expressionTarget:Y7(Q,"region-fallback")}};var c0=(Q)=>{if(!Q.boundary)return null;return Q.alignment.segments.find((J)=>J.speechTokenIds.includes(Q.boundary.token.id))?.target||null};var U5=(Q)=>{let Y=[],J=new Set,G=(X)=>{let j=X.toLowerCase().trim().split(/\s+/).filter(Boolean);if(j.length===0)return;let Z=j.join(" ");if(J.has(Z))return;J.add(Z),Y.push(j)};G(Q.normalized);for(let X of Q.spokenAliases)G(X);return Y},d0=(Q,Y,J)=>{let G=0;for(let X of J){if(X.length<=G)continue;let j=!0;for(let Z=0;Z<X.length;Z++){let B=Q[Y+Z];if(!B||B.normalized.toLowerCase()!==X[Z]){j=!1;break}}if(j)G=X.length}return G},V5=(Q,Y)=>{let J=[],G=0;for(let X of Y){let j=U5(X);if(X.optional){let Z=d0(Q,G,j);if(Z>0)J.push({speechTokens:Q.slice(G,G+Z),math:X}),G+=Z;continue}while(G<Q.length){let Z=d0(Q,G,j);if(Z>0){J.push({speechTokens:Q.slice(G,G+Z),math:X}),G+=Z;break}G++}}return J},A5=(Q,Y,J)=>{let G=J.filter((Z)=>!Z.optional).length,X=Q.filter((Z)=>!Z.math.optional).length,j=Q.reduce((Z,B)=>Z+B.speechTokens.length,0);return G>0&&X===G&&j===Y.length},_5=(Q)=>Q.map(({speechTokens:Y,math:J})=>({speechTokenIds:Y.map((G)=>G.id),mathTokenIds:[J.id],score:1,confidence:1,target:J.target})),l0=(Q)=>{let Y=Q.minExactWordConfidence??0.95,J=V5(Q.speech.tokens,Q.math.tokens),G=A5(J,Q.speech.tokens,Q.math.tokens)?1:0;return{segments:G>=Y?_5(J):[],confidence:G,fallbackTarget:Q.math.expressionTarget}};var f7=(Q)=>{let Y=H7({speechText:Q.speechText}),J=g0(Q.mathElement);return{speech:Y,math:J,result:l0({speech:Y,math:J})}};var i0=(Q,Y)=>{let J=h0({tokenization:Q.speech,position:Y.position,length:Y.length,boundaryWord:Y.boundaryWord});return c0({alignment:Q.result,boundary:J})},s0=(Q,Y)=>{let J=T7(Y.boundaryWord);if(!J)return null;let G=Q.math.tokens.filter((X)=>X.normalized.toLowerCase()===J||X.spokenAliases.some((j)=>j.toLowerCase()===J));return G.length===1?G[0].target:null};var $5=new Set(["math","maction","menclose","merror","mfenced","mfrac","mi","mmultiscripts","mn","mo","mover","mpadded","mphantom","mprescripts","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msubsup","msup","mtable","mtd","mtext","mtr","munder","munderover","none","semantics","annotation","annotation-xml"]),F5=new Set(["accent","accentunder","align","bevelled","class","close","columnalign","columnlines","columnspacing","columnspan","denomalign","depth","dir","display","encoding","fence","height","href","id","largeop","length","linethickness","lspace","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","width","xmlns","xml:lang"]),n0=(Q)=>Q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),H5=(Q)=>n0(Q).replace(/"/g,"""),D5=(Q,Y)=>{let J=Q.toLowerCase(),G=Y.trim().toLowerCase();if(J.startsWith("on"))return!0;if(!F5.has(J))return!0;if(G.includes("javascript:"))return!0;if(G.includes("data:text/html"))return!0;return!1},N5=(Q)=>{let Y=Q.localName.toLowerCase();if(!$5.has(Y))return!1;let J=Q.namespaceURI;return!J||J==="http://www.w3.org/1998/Math/MathML"||J==="http://www.w3.org/1999/xhtml"},r0=(Q)=>{if(Q.nodeType===Node.TEXT_NODE)return n0(Q.textContent||"");if(Q.nodeType===Node.COMMENT_NODE)return"";if(Q.nodeType!==Node.ELEMENT_NODE)return null;let Y=Q;if(!N5(Y))return null;let J=Y.localName.toLowerCase(),G=[];for(let Z of Array.from(Y.attributes)){let B=Z.name.toLowerCase();if(D5(B,Z.value))continue;if(B==="xmlns"&&Z.value!=="http://www.w3.org/1998/Math/MathML")return null;G.push(`${B}="${H5(Z.value)}"`)}if(J==="math"&&!G.some((Z)=>Z.startsWith("xmlns=")))G.unshift('xmlns="http://www.w3.org/1998/Math/MathML"');let X=[];for(let Z of Array.from(Y.childNodes)){let B=r0(Z);if(B===null)return null;X.push(B)}let j=G.length>0?` ${G.join(" ")}`:"";return`<${J}${j}>${X.join("")}</${J}>`},M5=(Q)=>{if(typeof DOMParser<"u")return new DOMParser().parseFromString(Q,"application/xml");return null},V1=(Q)=>{let Y=String(Q||"").trim();if(!Y)return null;let J=M5(Y);if(!J)return null;if(J.getElementsByTagName("parsererror").length>0)return null;let G=J.documentElement;if(!G||G.localName.toLowerCase()!=="math")return null;return r0(G)};var o0=(Q)=>({chars:[],map:new Map,position:0,inLeadingWhitespace:!0,lastCharWasWhitespace:!1,lastMapped:null,options:Q}),A9=(Q)=>Q.classList?.contains("MathJax")||Q.tagName?.toLowerCase()==="mjx-container",a0=(Q)=>Q.tagName?.toLowerCase()==="mjx-assistive-mml",_9=(Q)=>{let Y=Q.tagName?.toLowerCase();return Y==="annotation"||Y==="annotation-xml"},z5=(Q)=>{let Y=Q.getAttribute("data-mathml");return Y&&Y.trim()?Y:null},O5=(Q)=>{return Q.querySelector("mjx-assistive-mml math")?.outerHTML||null},P5=(Q)=>{if(Q.tagName.toLowerCase()==="math")return V1(Q.outerHTML);let Y=z5(Q);if(Y){let J=V1(Y);if(J)return J}if(A9(Q)){let J=O5(Q);if(J){let G=V1(J);if(G)return G}}return null},L5=new Set(["P","H1","H2","H3","H4","H5","H6","LI","TD","TH","DD","DT","FIGCAPTION","LABEL","BUTTON"]),w5=new Set(["heading","listitem","option","radio","row","cell","columnheader","rowheader"]),R5=(Q,Y)=>{let J=Q.parentElement,G=null;while(J&&J!==Y){let X=(J.getAttribute("role")||"").toLowerCase(),j=J.tagName.toUpperCase();if(L5.has(j)||w5.has(X)){G=J;break}J=J.parentElement}return G||Y},E5=(Q)=>Boolean(typeof Q.querySelector==="function"&&Q.querySelector("math, [data-mathml], .MathJax, mjx-container, mjx-assistive-mml"))||Q.tagName?.toLowerCase()==="math"||Q.hasAttribute?.("data-mathml")||A9(Q),z7=(Q,Y,J)=>{if(/[.,;:!?]/.test(Y)&&Q.chars.length>0&&Q.chars[Q.chars.length-1]===" ")Q.chars.pop(),Q.position--,Q.map.delete(Q.position);if(Q.chars.push(Y),J)Q.map.set(Q.position,J),Q.lastMapped=J;else if(Q.lastMapped)Q.map.set(Q.position,Q.lastMapped);Q.position++},t0=(Q,Y)=>{if(Q.inLeadingWhitespace||Q.lastCharWasWhitespace||Q.chars.length===0)return!1;let J=Q.chars[Q.chars.length-1];return j9(J,Y,Q.options)},e0=(Q,Y)=>{let J=Y.textContent||"",G=!1;for(let X=0;X<J.length;X++){let j=J[X],Z=/\s/.test(j);if(Q.inLeadingWhitespace){if(!Z)Q.inLeadingWhitespace=!1,z7(Q,j,{node:Y,offset:X}),G=!0,Q.lastCharWasWhitespace=!1;continue}if(Z){if(!Q.lastCharWasWhitespace)z7(Q," ",{node:Y,offset:X});Q.lastCharWasWhitespace=!0;continue}if(!G&&t0(Q,j))z7(Q," ",{node:Y,offset:X});z7(Q,j,{node:Y,offset:X}),G=!0,Q.lastCharWasWhitespace=!1}},b5=(Q,Y)=>{for(let J=0;J<Y.text.length;J++){let G=Y.text[J],X=/\s/.test(G),j=Y.map.get(J)||null,Z=j?.node||Q.lastMapped?.node||null,B=j?.offset??Q.lastMapped?.offset??0,W=j?{node:j.node,offset:j.offset}:Z?{node:Z,offset:B}:null;if(Q.inLeadingWhitespace){if(X)continue;Q.inLeadingWhitespace=!1}if(X){if(!Q.lastCharWasWhitespace)z7(Q," ",W);Q.lastCharWasWhitespace=!0;continue}if(J===0&&t0(Q,G))z7(Q," ",W);if(z7(Q,G,W),Q.lastCharWasWhitespace=!1,j)Q.map.set(Q.position-1,{node:j.node,offset:j.offset}),Q.lastMapped={node:j.node,offset:j.offset};else if(Z)Q.map.set(Q.position-1,{node:Z,offset:B})}},S5=(Q)=>{if(typeof DOMParser>"u")return"";let Y=new DOMParser().parseFromString(Q,"application/xml");if(Y.getElementsByTagName("parsererror").length>0)return"";let J=[],G=(X)=>{if(X.nodeType===3){let Z=X.textContent||"";if(Z.trim())J.push(Z);return}if(X.nodeType!==1)return;let j=X;if(_9(j))return;for(let Z of Array.from(j.childNodes))G(Z)};return G(Y.documentElement),T(J.join(" "))},C5=(Q,Y)=>{let J=new Map,G=A9(Q)?Q.querySelector("mjx-assistive-mml math"):null;if(!G)return J;let X=[],j=(B)=>{if(B.nodeType===3){let W=B.textContent||"";for(let K=0;K<W.length;K++)if(!/\s/.test(W[K]))X.push({node:B,offset:K});return}if(B.nodeType!==1||_9(B))return;for(let W of Array.from(B.childNodes))j(W)};j(G);let Z=0;for(let B=0;B<Y.length;B++){if(/\s/.test(Y[B]))continue;let W=X[Z];if(W?.node.textContent?.[W.offset]!==Y[B])return new Map;J.set(B,W),Z++}return Z===X.length?J:new Map},T5=(Q,Y,J)=>{let G=o0(J),X=(B)=>{if($7(B,Q))return;if(B.nodeType===3){e0(G,B);return}if(B.nodeType!==1)return;let W=B;if(a0(W)||_9(W))return;for(let K of Array.from(W.childNodes))X(K)};X(Q),Q8(G);let j=T(G.chars.join(""));if(j)return{text:j,map:G.map};let Z=S5(Y);if(!Z)return F7(Q,J);return{text:Z,map:C5(Q,Z)}},Q8=(Q)=>{while(Q.chars.length>0&&/\s/.test(Q.chars[Q.chars.length-1]))Q.chars.pop(),Q.position--,Q.map.delete(Q.position)},y5=(Q,Y)=>{let J=o0(Y),G=[],X=0,j,Z=!1,B=()=>{let U=T(J.chars.slice(X,J.chars.length).join(""));if(U)G.push({type:"text",text:U,sourceElement:j});X=J.chars.length,j=void 0},W=(U)=>{if($7(U,Q))return;if(U.nodeType===Node.TEXT_NODE){let N=R5(U,Q);if(j&&N!==j)B();j=N,e0(J,U);return}if(U.nodeType!==Node.ELEMENT_NODE)return;let _=U;if(a0(_))return;let $=P5(_);if($){B();let N=T5(_,$,Y);b5(J,N);let D=T(N.text);G.push({type:"math",mathml:$,fallbackText:D,sourceElement:_}),X=J.chars.length,Z=!0;return}for(let N of Array.from(_.childNodes))W(N)};for(let U of Array.from(Q.childNodes))W(U);Q8(J),B();let K=J.chars.join("");while(J.map.has(K.length))J.map.delete(K.length);return{visibleText:K,map:J.map,chunks:G,containsMathMarkup:Z}},O7=(Q,Y)=>{if(!E5(Q)){let{text:J,map:G}=F7(Q,Y);return{visibleText:J,map:G,chunks:J?[{type:"text",text:J}]:[],containsMathMarkup:!1}}return y5(Q,Y)};var $9=null,Y8=Promise.resolve(),x5=(Q)=>(Q||"en").split("-")[0].toLowerCase()||"en",k5=async(Q)=>{if(!$9)Z8(Q),$9=import("./chunks/sre-engine-wf9s43gg.js").then(({default:Y})=>{if(!Y||typeof Y.toSpeech!=="function")throw Error("speech-rule-engine did not expose toSpeech");return Y});return $9},I5=(Q)=>Q==="en"?"clearspeak":"mathspeak",J8=(Q)=>!!Q&&typeof Q==="object"&&!Array.isArray(Q),G8=(Q)=>typeof Q==="string"&&Q.trim()?Q.trim():void 0,j7=(Q)=>{if(!J8(Q))return;let Y=G8(Q.domain),J=G8(Q.style),G=J8(Q.engineOptions)?Q.engineOptions:void 0;if(!Y&&!J&&!G)return;return{...Y?{domain:Y}:{},...J?{style:J}:{},...G?{engineOptions:G}:{}}},v5=async(Q,Y,J,G)=>{let X=x5(Y),j=j7(G),Z=j?.engineOptions||{};await Q.setupEngine?.({...X8(Z),...Z,locale:X,domain:j?.domain||I5(X),...j?.style?{style:j.style}:{},modality:"speech",markup:J}),await Q.engineReady?.()},h5=async(Q)=>{let Y=Y8.then(Q,Q);return Y8=Y.then(()=>{return},()=>{return}),Y},j8=async(Q,Y,J,G,X)=>h5(async()=>{return await v5(Q,J,G,X),Q.toSpeech(Y)}),m5=(Q)=>Q.replace(/^\s*<\?xml[^>]*\?>\s*/i,""),u5=async(Q,Y,J,G)=>{try{let X=m5(await j8(Q,Y,J,"ssml",G));return X.includes("<speak")?X:null}catch(X){return console.debug("[TTSService] Math SSML generation failed; using plain",{message:X instanceof Error?X.message:String(X)}),null}},A1=async(Q,Y={})=>{if(!Q.some((K)=>K.type==="math"))return{speechText:T(Q.map((K)=>K.type==="text"?K.text:K.fallbackText).join(" ")),usedMathSpeech:!1,usedFallback:!1};let J=null,G=!1,X=!1,j=Y.loadSre||(()=>k5(j7(Y.mathSpeech)?.engineOptions)),Z=[];for(let K of Q){if(K.type==="text"){Z.push(K.text);continue}try{if(!J)J=await j();let U=T(await j8(J,K.mathml,Y.language,"none",Y.mathSpeech));if(U){Z.push(U),G=!0;continue}X=!0,Z.push(K.fallbackText)}catch(U){X=!0,console.debug("[TTSService] Math speech generation failed; using visible fallback",{message:U instanceof Error?U.message:String(U)}),Z.push(K.fallbackText)}}let B=T(Z.join(" ")),W;if(Y.produceSsml&&J&&G&&Q.length===1&&Q[0].type==="math")W=await u5(J,Q[0].mathml,Y.language,Y.mathSpeech)??void 0;return{speechText:B,usedMathSpeech:G,usedFallback:X,ssml:W}};var p5=(Q)=>(Q||"en").split("-")[0].toLowerCase()||"en",g5="sre-v1",c5=256,F9=(Q)=>{if(Array.isArray(Q))return`array:[${Q.map(F9).join(",")}]`;if(Q&&typeof Q==="object")return`object:{${Object.entries(Q).sort(([Y],[J])=>Y.localeCompare(J)).map(([Y,J])=>`${JSON.stringify(Y)}:${F9(J)}`).join(",")}}`;if(Q===null)return"null:null";if(typeof Q>"u")return"undefined:";if(typeof Q==="function")return`function:${Q.name||"anonymous"}`;if(typeof Q==="symbol")return`symbol:${String(Q)}`;if(typeof Q==="bigint")return`bigint:${Q.toString()}`;if(typeof Q==="number")return Number.isFinite(Q)?`number:${Q}`:`number:${String(Q)}`;return`${typeof Q}:${JSON.stringify(Q)}`},B8=(Q,Y,J,G)=>`${g5}\x00${p5(Q)}\x00${Y?"ssml":"plain"}\x00${F9(J??null)}\x00${G}`,H9=(Q={})=>{let Y=Math.max(1,Q.maxEntries??c5),J=Q.resolve??((j,Z)=>A1([j],Z)),G=new Map,X=(j,Z)=>{G.delete(j),G.set(j,Z);while(G.size>Y){let B=G.keys().next().value;if(B!==void 0)G.delete(B)}};return async(j,Z)=>{let B=j7(Z.mathSpeech),W=Z.produceSsml===!0,K=B8(Z.language,W,B,j.mathml),U=G.get(K);if(U)return G.delete(K),G.set(K,U),U;let _=await J(j,{...Z,mathSpeech:B});if(W&&_.ssml&&Y>1)X(B8(Z.language,!1,B,j.mathml),{speechText:_.speechText,usedMathSpeech:_.usedMathSpeech,usedFallback:_.usedFallback});return X(K,_),_}};var q8=(Q,Y)=>{let J=T7(Y.word);if(Q.id!==Y.chunkId)return{chunkId:Y.chunkId,normalizedWord:J,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"boundary chunk id did not match highlight chunk"};if(Y.providerOffsetSpace==="unknown"||Q.offsetSpace==="unsupported")return{chunkId:Q.id,normalizedWord:J,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"boundary offset space is unsupported"};let G=U9({tokenization:Q.catalogAlignment?.speech??H7({speechText:Q.speechText}),position:Y.position,length:Y.length,boundaryWord:Y.word});if(!G)return{chunkId:Q.id,normalizedWord:J,chunkSpokenStart:null,chunkSpokenEnd:null,confidence:0,reason:"could not resolve provider boundary to chunk speech"};return{chunkId:Q.id,normalizedWord:J,chunkSpokenStart:G.start,chunkSpokenEnd:G.start+G.length,confidence:G.confidence,reason:Q.catalogAlignment?"resolved through catalog alignment":"resolved through speech tokenization"}};var P7=(Q)=>{if(Q.semanticTarget)return{activeTarget:Q.semanticTarget,regionTarget:Q.regionTarget,quality:Q.semanticTarget.quality==="exact-word"?"exact-word":Q.semanticTarget.quality==="expression"?"expression":"semantic-token",confidence:Q.confidence,reason:Q.reason};if(Q.expressionTarget)return{activeTarget:Q.expressionTarget,regionTarget:Q.regionTarget,quality:"expression",confidence:Q.confidence,reason:Q.reason};return{activeTarget:null,regionTarget:Q.regionTarget,quality:"region",confidence:Q.confidence,reason:Q.reason}};var K8=new Map([["mi","mjx-mi"],["mn","mjx-mn"],["mo","mjx-mo"],["mtext","mjx-mtext"]]),D9="mi,mn,mo,mtext",U8="mjx-mi,mjx-mn,mjx-mo,mjx-mtext",V8=["mjx-mfrac","mjx-msqrt","mjx-mroot","mjx-mtable","mjx-munder","mjx-mover","mjx-munderover"].join(","),A8=(Q)=>{if(Q.type==="text-range")return Q.node.parentElement;return Q.element},_1=(Q)=>{let Y=Q;while(Y){if(Y.localName?.toLowerCase()==="mjx-container")return Y;Y=Y.parentElement}return null},W8=(Q)=>{if(!Q)return!1;if(_1(Q))return!1;return!C7(Q)},_8=(Q)=>{let Y=Q.getBoundingClientRect?.();return Boolean(Y&&Y.width>0&&Y.height>0)},N9=(Q)=>{let Y=Q;while(Y){if(Y.localName?.toLowerCase()==="math")return Y;Y=Y.parentElement}return null},$8=(Q,Y)=>{if(Q.length===0)return!1;if(Q.length!==Y.length)return!1;for(let J=0;J<Q.length;J+=1){let G=K8.get(Q[J].localName.toLowerCase());if(!G)return!1;if(Y[J].localName.toLowerCase()!==G)return!1}return!0},d5=(Q,Y)=>{if(!Q)return null;if(!K8.has(Q.localName.toLowerCase()))return null;if(Y.querySelector(V8))return null;let J=N9(Q),G=Y.querySelector("mjx-math");if(!J||!G)return null;let X=Array.from(J.querySelectorAll(D9)),j=X.indexOf(Q);if(j<0)return null;let Z=Array.from(G.querySelectorAll(U8));if(!$8(X,Z))return null;let B=Z[j];if(!B||!_8(B))return null;return B},F8=(Q)=>{let Y=_1(Q);if(Y){if(Y.querySelector(V8))return"expression";let X=N9(Q)??Q,j=Y.querySelector("mjx-math");if(!j)return"expression";let Z=Array.from(X.querySelectorAll(D9)),B=Array.from(j.querySelectorAll(U8));if(!$8(Z,B))return"expression";return B.some((W)=>_8(W))?"token":"expression"}let J=N9(Q)??Q;return Array.from(J.querySelectorAll(D9)).some((X)=>!C7(X))?"token":"expression"},M9=(Q)=>{let Y=A8(Q),J=_1(Y);if(J){let G=d5(Y,J);if(G)return{type:"element",quality:"semantic-token",element:G};return{type:"element",quality:"expression",element:J}}if(Q.type==="text-range"){if(!W8(Q.node.parentElement))return null;return{type:"text-range",quality:"semantic-token",node:Q.node,startOffset:Q.startOffset,endOffset:Q.endOffset}}if(!W8(Q.element))return null;return{type:"element",quality:Q.quality==="region-fallback"?"expression":"semantic-token",element:Q.element}},H8=M9,D8=()=>{let Q=new WeakMap;return(Y)=>{let J=A8(Y),G=_1(J);if(!J||!G)return M9(Y);if(Q.has(J))return Q.get(J)??null;let X=M9(Y);return Q.set(J,X),X}};var N8=(Q,Y,J,G=Q.mathAlignments,X=H8)=>{if(Y.chunkSpokenStart===null||Y.chunkSpokenEnd===null)return null;let j=null;for(let Z of G){let B=i0(Z.alignment,{position:Y.chunkSpokenStart,length:Math.max(1,Y.chunkSpokenEnd-Y.chunkSpokenStart),boundaryWord:J.word})||s0(Z.alignment,{boundaryWord:J.word});if(!B)continue;let W=X(B);if(!W)continue;if(W.quality==="semantic-token")return W;j??=W}return j};var $1=(Q,Y,J)=>{if(!Q||typeof document>"u")return null;if(J<=Y)return null;let G=Q.get(Y),X=Q.get(Math.max(Y,J-1));if(!G)return null;if(!X)X=G;try{let j=document.createRange();return j.setStart(G.node,G.offset),j.setEnd(X.node,X.offset+1),j}catch{return null}};var M8=(Q,Y)=>{if(!Q.catalogAlignment||Y.chunkSpokenStart===null)return null;let J=m0(Q.catalogAlignment,Y.chunkSpokenStart);if(!J)return null;let G=$1(Q.visibleMap,J.start,J.end);if(!G)return null;return{type:"range",quality:Q.catalogAlignment.playbackMode==="exact-word"?"exact-word":"semantic-token",range:G}};var l5=(Q)=>Q.regionRange?{type:"range",quality:"region",range:Q.regionRange}:Q.regionElement?{type:"element",quality:"region",element:Q.regionElement}:null,z8=(Q,Y=Q.chunk.mathAlignments)=>{if(Y.length!==1)return null;let J=Y[0]?.alignment.result.fallbackTarget;return J?Q.renderedMathTargetResolver(J):null},i5=(Q,Y)=>{if(!Q)return Y.mathAlignments;return Y.mathAlignments.filter(({element:J})=>{try{if(Q.type==="range")return Q.range.intersectsNode(J);if(Q.type==="element")return Q.element===J||Q.element.contains(J);return Q.node.parentElement?.contains(J)||!1}catch{return!1}})},O8=()=>({activeTarget:null,regionTarget:null,quality:"region",confidence:0,reason:"boundary chunk id was not found"}),P8=(Q)=>Q.length===1?Q[0].element:null,s5=(Q,Y)=>Y.length>0&&Y.every(({element:J})=>Q.mathCapabilityByElement.get(J)==="token"),L8=3,n5=(Q,Y,J)=>{if(!Y||Y.type!=="range")return!1;let{startContainer:G,endContainer:X}=Y.range;if(G===X&&G.nodeType===L8)return!1;return J.some(({element:Z})=>Q.mathCapabilityByElement.get(Z)==="token"&&Z.contains(G)&&Z.contains(X))},w8=(Q)=>Q?.type==="range"&&C7(Q.range.startContainer),r5=(Q,Y)=>{if(!w8(Y))return null;let{startContainer:J,endContainer:G,startOffset:X,endOffset:j}=Y.range;if(J!==G||J.nodeType!==L8)return null;return Q.renderedMathTargetResolver({type:"text-range",quality:"exact-word",node:J,startOffset:X,endOffset:j})},o5=(Q,Y)=>({chunk:Q,regionTarget:l5(Q),renderedMathTargetResolver:D8(),mathCapabilityByElement:new Map(Q.mathAlignments.map(({element:J})=>[J,Y?F8(J):"expression"])),heldTokenByElement:new Map}),R8=(Q)=>{let Y=Q.mathTokenHighlighting!==!1,J=new Map(Q.chunks.map((G)=>[G.id,o5(G,Y)]));return{chunks:Q.chunks,resolveInitial(G){let X=J.get(G);if(!X)return O8();let j=X.chunk.mathAlignments,Z=j.length===1?j[0].element:null,B=Z?X.mathCapabilityByElement.get(Z):null;if(B==="expression")return P7({semanticTarget:null,expressionTarget:z8(X),regionTarget:X.regionTarget,confidence:0.5,reason:"initial expression (sticky expression mode)"});return P7({semanticTarget:null,expressionTarget:null,regionTarget:X.regionTarget,confidence:0,reason:B==="token"?"initial region (sticky token mode, awaiting first token)":"initial region fallback"})},resolveBoundary(G){let X=J.get(G.chunkId);if(!X)return O8();let{chunk:j}=X,Z=q8(j,G),B=M8(j,Z),W=i5(B,j),K=(!B||W.length>0?N8(j,Z,G,W,X.renderedMathTargetResolver):null)||null,U=K?.quality==="semantic-token"?K:r5(X,B)??K,_=Y&&U&&U.quality!=="expression"?U:null,$=U&&U.quality==="expression"?U:null;if(_){let N=P8(W);if(N)X.heldTokenByElement.set(N,_);return P7({semanticTarget:_,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason})}if(B&&!w8(B)&&(Y?!n5(X,B,W):W.length===0))return P7({semanticTarget:B,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason});if(s5(X,W)){let N=P8(W),D=N?X.heldTokenByElement.get(N)??null:null;return P7({semanticTarget:D,expressionTarget:null,regionTarget:X.regionTarget,confidence:Z.confidence,reason:D?"hold last token (sticky token mode)":"region (sticky token mode, awaiting first token)"})}return P7({semanticTarget:null,expressionTarget:$??z8(X,W),regionTarget:X.regionTarget,confidence:Z.confidence,reason:Z.reason})}}};var a5=(Q)=>{return Q.alignment?.speech.boundaryOffsetSpace??Q.mathAlignment?.speech.boundaryOffsetSpace??"plain-spoken-text"},t5=(Q)=>{if(Q.mathAlignments?.length)return Q.mathAlignments;if(Q.mathAlignment&&Q.sourceElement)return[{element:Q.sourceElement,alignment:Q.mathAlignment}];return[]},E8=(Q)=>{return(Q.chunks&&Q.chunks.length?Q.chunks:[{speechText:Q.speechText||"",visibleText:Q.visibleText||Q.speechText||"",sourceElement:Q.sourceElement||Q.contentRoot,regionElement:Q.regionElement||Q.sourceElement||Q.contentRoot,regionRange:Q.regionRange,visibleMap:Q.visibleMap}]).map((J,G)=>({id:`tts-chunk-${G}`,speechText:J.speechText,visibleText:J.visibleText,sourceElement:J.sourceElement,contentRoot:Q.contentRoot,regionElement:J.regionElement??J.sourceElement,regionRange:J.regionRange,visibleMap:J.visibleMap,catalogAlignment:J.alignment,mathAlignments:t5(J),offsetSpace:a5(J)}))};var e5=["[data-pie-tts-region]","[data-catalog-region]","li","p","label","section","[role='group']","[role='region']","div"].join(","),F1=(Q,Y)=>{let J=Q.closest(e5);if(J&&Y.contains(J))return J;return Q};var Q2=(Q,Y)=>A1([Q],Y),Y2=(Q)=>(Q||"en").split("-")[0].toLowerCase()||"en",J2=new Set(["H1","H2","H3","H4","H5","H6","LI","LABEL","BUTTON"]),G2=new Set(["heading","listitem","option","radio"]),X2=(Q)=>{if(Q.type!=="text"||!Q.sourceElement)return!1;let Y=Q.sourceElement.tagName.toUpperCase(),J=(Q.sourceElement.getAttribute("role")||"").toLowerCase();return J2.has(Y)||G2.has(J)},b8=async(Q)=>{let Y=Q.resolveMathSpeech??Q2,{visibleText:J}=Q,G=[],X=0,j=(B)=>{let W=T(B),K=J.indexOf(W,X),U=K>=0?K:X,_=U+W.length;return X=_,{start:U,end:_}},Z=[];for(let B=0;B<Q.chunks.length;B++){let W=Q.chunks[B];if(W.type==="text"){let N=X2(W)?[{text:W.text,offset:0}]:S7(W.text,{locale:Q.language});for(let D of N){let O=T(D.text);if(!O)continue;let P=j(O);G.push({sourceChunkIndex:B,segment:{kind:"prose",spokenText:O,visibleText:O,visibleSpan:P}}),Z.push(O)}continue}let K=j(W.fallbackText),U=await Y(W,{language:Q.language,produceSsml:Q.produceSsml,mathSpeech:Q.mathSpeech}),_=!U.speechText,$=U.speechText||W.fallbackText;G.push({sourceChunkIndex:B,segment:{kind:"math",spokenText:$,mathml:W.mathml,fallbackText:W.fallbackText,visibleSpan:K,usedFallback:_,ssml:U.ssml}}),Z.push($)}return{segments:G,locale:Y2(Q.language),visibleText:J,plainSpeechText:T(Z.join(" "))}};var Z2=(Q,Y,J)=>{let G=new Map;for(let X=Y;X<J;X++){let j=Q.get(X);if(j)G.set(X-Y,j)}return G},z9=async(Q)=>{let Y=O7(Q.contentRoot,Q.textProcessingOptions),J=await b8({chunks:Y.chunks,visibleText:Y.visibleText,language:Q.language,mathSpeech:Q.mathSpeech,produceSsml:Q.produceSsml,resolveMathSpeech:Q.resolveMathSpeech});return{plan:{items:J.segments.map(({segment:X,sourceChunkIndex:j})=>{let Z=Y.chunks[j];if(X.kind==="prose"){let W=Z?.type==="text"?Z.sourceElement??Q.contentRoot:Q.contentRoot;return{segment:X,anchor:{sourceElement:W,regionElement:F1(W,Q.contentRoot),visibleMap:Z2(Y.map,X.visibleSpan.start,X.visibleSpan.end)}}}let B=Z?.type==="math"?Z.sourceElement??null:null;return{segment:X,anchor:{sourceElement:B,regionElement:B}}}),locale:J.locale,visibleText:J.visibleText,plainSpeechText:J.plainSpeechText},containsMathMarkup:Y.containsMathMarkup,visibleText:Y.visibleText}};var j2=(Q,Y)=>{let J=U1({speechText:Q.spokenText,visibleText:Q.spokenText});return{speechText:Q.spokenText,visibleText:Q.visibleText,sourceElement:Y.sourceElement,regionElement:Y.regionElement,regionRange:$1(Y.visibleMap,0,Q.visibleText.length)??void 0,speechMatchesVisibleText:!0,playbackMode:J.playbackMode,alignment:J,visibleMap:Y.visibleMap}},S8=(Q,Y)=>{let J=Y.sourceElement;return{speechText:Q.spokenText,visibleText:Q.fallbackText,sourceElement:J,regionElement:Y.regionElement,speechMatchesVisibleText:Q.spokenText===Q.fallbackText,mathAlignment:J?f7({mathElement:J,speechText:Q.spokenText}):void 0}},B2=(Q,Y,J)=>{let G=Y.sourceElement;return{speechText:J,visibleText:Q.fallbackText,sourceElement:G,regionElement:Y.regionElement,speechMatchesVisibleText:!1,mathAlignment:G?f7({mathElement:G,speechText:J}):void 0,plainFallback:S8(Q,Y)}},O9=(Q,Y={})=>Q.items.map(({segment:J,anchor:G})=>{if(J.kind==="prose")return j2(J,G);if(Y.format==="ssml"&&J.ssml)return B2(J,G,J.ssml);return S8(J,G)});var C8="pie-tts-control-handoff";var w;(function(Q){Q.IDLE="idle",Q.LOADING="loading",Q.PLAYING="playing",Q.PAUSED="paused",Q.ERROR="error"})(w||(w={}));var T8=(Q,Y)=>Q===Y||Q.startContainer===Y.startContainer&&Q.startOffset===Y.startOffset&&Q.endContainer===Y.endContainer&&Q.endOffset===Y.endOffset,K2=(Q,Y)=>{if(Q===Y)return!0;if(!Q||!Y||Q.type!==Y.type||Q.quality!==Y.quality)return!1;if(Q.type==="range"&&Y.type==="range")return T8(Q.range,Y.range);if(Q.type==="element"&&Y.type==="element")return Q.element===Y.element;if(Q.type==="text-range"&&Y.type==="text-range")return Q.node===Y.node&&Q.startOffset===Y.startOffset&&Q.endOffset===Y.endOffset;return!1};class c7{currentProvider=null;provider=null;highlightCoordinator=null;highlightTargetResolverProvider=null;catalogResolver=null;state=w.IDLE;ttsConfig={};currentText=null;currentContentElement=null;normalizedToDOM=new Map;listeners=new Map;lastError=null;speakRunId=0;currentBoundaryOffset=0;activeWordBoundaryOffset=0;seekSegments=[];playbackChunks=[];activeRecordedAudio=null;sentenceHighlightSegments=[];activeSentenceStartOffset=null;playbackStartDeferredRunId=null;pendingPlaybackStartHighlights=[];playbackStartBarrierCleanup=null;playbackRateWriteQueue=Promise.resolve();playbackRateRequestId=0;pendingPlaybackRateRequest=null;activePlaybackRate=null;activeHighlightMode="word";lastRenderedRegionTarget=null;telemetryReporter=null;generatedMathSpeechResolver=H9();static debugEnabled=(()=>{try{if(typeof process<"u"&&process.env?.PIE_TTS_DEBUG==="1")return!0}catch{}return globalThis.__PIE_TTS_DEBUG__===!0})();constructor(){}debugLog(Q,Y){if(!c7.debugEnabled)return;if(Y===void 0)console.debug(Q);else console.debug(Q,Y)}clearPlaybackStartBarrier(Q=this.playbackStartBarrierCleanup){if(Q?.(),this.playbackStartBarrierCleanup===Q)this.playbackStartBarrierCleanup=null}notifyPlaybackStarted(Q){if(this.playbackStartDeferredRunId!==Q||Q!==this.speakRunId)return;this.setState(w.PLAYING);let Y=this.pendingPlaybackStartHighlights.splice(0);for(let J of Y)J()}installPlaybackStartBarrier(Q,Y=!1){this.clearPlaybackStartBarrier();let J=this.provider,G=J&&"onPlaybackStart"in J?J:null;if(!G&&!Y)return null;let X=G?.onPlaybackStart,j=()=>{try{this.notifyPlaybackStarted(Q)}finally{X?.()}};if(G)G.onPlaybackStart=j;this.playbackStartDeferredRunId=Q;let Z=()=>{if(G?.onPlaybackStart===j)G.onPlaybackStart=X;if(this.playbackStartDeferredRunId===Q)this.playbackStartDeferredRunId=null,this.pendingPlaybackStartHighlights=[]};return this.playbackStartBarrierCleanup=Z,Z}runWhenPlaybackStarts(Q,Y){if(this.playbackStartDeferredRunId===Q){this.pendingPlaybackStartHighlights.push(Y);return}Y()}async emitTelemetry(Q,Y){try{await this.telemetryReporter?.(Q,Y)}catch(J){console.warn("[TTSService] telemetry callback failed:",J)}}async initialize(Q,Y={}){this.currentProvider=Q,this.ttsConfig={...Y};let J=Y.providerOptions&&typeof Y.providerOptions==="object"?Y.providerOptions:{};this.telemetryReporter=typeof J.__pieTelemetry==="function"?J.__pieTelemetry:null;try{this.provider=await Q.initialize(Y)}catch(G){if(Q.providerId.toLowerCase()==="browser")throw G;if(!this.isBrowserSpeechFallbackAvailable())throw G;if(!await this.switchProviderToBrowser(G,{operation:"tts-initialize"}))throw G}}async updateSettings(Q){if(!this.provider)throw Error("TTSService not initialized. Call initialize() first.");let Y=this.provider;if(typeof Y.updateSettings==="function"){let J={...Q,...Q.providerOptions?{providerOptions:{...this.ttsConfig.providerOptions||{},...Q.providerOptions}}:{}};await Y.updateSettings(J),this.ttsConfig={...this.ttsConfig,...J}}else console.warn("[TTSService] Provider does not support dynamic settings updates. Some settings may require reinitialization.")}setHighlightCoordinator(Q){this.highlightCoordinator=Q}setHighlightTargetResolverProvider(Q){return this.highlightTargetResolverProvider=Q,()=>{if(this.highlightTargetResolverProvider===Q)this.highlightTargetResolverProvider=null}}setCatalogResolver(Q){this.catalogResolver=Q}hasSpokenAlternate(Q,Y="en-US"){if(!Q||!this.catalogResolver)return!1;return this.catalogResolver.getAlternative(Q,{type:"spoken",language:Y,useFallback:!0,form:"content"})?.content!==void 0}getHighlightResolverRuntime(){let Q=null;try{Q=this.highlightTargetResolverProvider?.()??null}catch{Q=null}let Y=Q?.context??{},J=typeof HTMLElement<"u"&&this.currentContentElement instanceof HTMLElement?this.currentContentElement:null;return{context:{...Y,scopeElement:Y.scopeElement??J},resolver:Q?.resolver??null}}getNodeElement(Q){if(!Q)return null;return Q.nodeType===Node.ELEMENT_NODE?Q:Q.parentElement}isElementWithinScope(Q,Y){if(!Y)return!0;return Q===Y||Y.contains(Q)}isRangeWithinScope(Q,Y){let J=this.getNodeElement(Q.startContainer),G=this.getNodeElement(Q.endContainer);if(!J||!G)return!1;return this.isElementWithinScope(J,Y)&&this.isElementWithinScope(G,Y)}resolveWordHighlightRange(Q){let{context:Y,resolver:J}=this.getHighlightResolverRuntime(),G=Y.scopeElement??this.currentContentElement;try{let X=J?.resolveWordRange?.(Q,Y);if(X&&this.isRangeWithinScope(X,G))return{range:X,remapped:!T8(Q,X)}}catch{}return{range:Q,remapped:!1}}resolveSentenceHighlightTargets(Q){let{context:Y,resolver:J}=this.getHighlightResolverRuntime(),G=Y.scopeElement??this.currentContentElement;try{let X=J?.resolveSentenceRanges?.(Q,Y);if(!X)return{ranges:Q,elements:[]};let j=[],Z=[];for(let B of X){if(typeof Range<"u"&&B instanceof Range){if(!this.isRangeWithinScope(B,G))return{ranges:Q,elements:[]};j.push(B);continue}if(typeof Element<"u"&&B instanceof Element){if(!this.isElementWithinScope(B,G))return{ranges:Q,elements:[]};Z.push(B);continue}return{ranges:Q,elements:[]}}return{ranges:j,elements:Z}}catch{return{ranges:Q,elements:[]}}}createTextRange(Q,Y,J){if(typeof document>"u")return null;if(typeof document.createRange!=="function")return null;try{let G=document.createRange();if(G.setStart(Q,Y),G.setEnd(Q,J),G.startContainer!==Q||G.endContainer!==Q)return null;return G}catch{return null}}paintTTSWordRange(Q){if(!this.highlightCoordinator)return;try{if(Q.startContainer===Q.endContainer&&Q.startContainer.nodeType===Node.TEXT_NODE){this.highlightCoordinator.highlightTTSWord(Q.startContainer,Q.startOffset,Q.endOffset);return}}catch{}this.highlightCoordinator.highlightRange(Q,u.TTS_WORD,_7.YELLOW)}paintTTSSentenceRanges(Q){if(!this.highlightCoordinator)return;let{ranges:Y,elements:J}=this.resolveSentenceHighlightTargets(Q);if(J.length>0&&Y.length===0&&this.highlightCoordinator.highlightTTSSentenceElements){this.highlightCoordinator.highlightTTSSentenceElements(J);return}let G=[...Y];for(let X of J){let j=document.createRange();j.selectNodeContents(X),G.push(j)}this.highlightCoordinator.highlightTTSSentence(G)}getCapabilities(){return this.currentProvider?.getCapabilities()||null}getTextProcessingOptions(Q){let J=(this.ttsConfig.providerOptions||{}).textNormalization||{},G=J.boundarySpacingMode,X=G==="none"||G==="alnum"||G==="segmenterPreferred"?G:void 0;return{locale:Q||(typeof J.locale==="string"?J.locale:void 0),boundarySpacingMode:X}}getMathSpeechOptions(){let Y=(this.ttsConfig.providerOptions||{}).mathSpeech;return j7(Y)}buildPositionMap(Q,Y,J){this.normalizedToDOM.clear();let{text:G,map:X}=F7(Q,this.getTextProcessingOptions(J));if(this.normalizedToDOM=X,!c7.debugEnabled)return;this.debugLog("[TTSService] Text comparison:",{spokenLength:Y.length,normalizedDomLength:G.length,match:Y===G,spokenPreview:Y.substring(0,150),normalizedPreview:G.substring(0,150),differAtIndex:Y===G?null:(()=>{for(let j=0;j<Math.min(Y.length,G.length);j++)if(Y[j]!==G[j])return{index:j,spokenChar:Y[j],normalizedChar:G[j],spokenContext:Y.substring(Math.max(0,j-20),j+20),normalizedContext:G.substring(Math.max(0,j-20),j+20)};return null})()}),this.debugLog("[TTSService] Position map built:",{entries:this.normalizedToDOM.size,spokenTextLength:Y.length,normalizedDomLength:G.length,mapLengthMatchesSpoken:this.normalizedToDOM.size===Y.length,firstFewMappings:Array.from(this.normalizedToDOM.entries()).slice(0,10).map(([j,{node:Z,offset:B}])=>({pos:j,offset:B,char:Z.textContent?.[B],expected:Y[j]}))})}getStructuralPauseProfile(){let Y=(this.ttsConfig.providerOptions||{}).structuralPauses||{},J=Y.units||{},G=(X,j)=>{if(typeof X==="number"&&Number.isFinite(X))return X;if(typeof X==="string"&&X.trim()){let Z=Number(X);return Number.isFinite(Z)?Z:j}return j};return{baseMs:G(Y.baseMs,280),units:{minor:G(J.minor,0.65),section:G(J.section,1),major:G(J.major,1.35)},minMs:G(Y.minMs,120),maxMs:G(Y.maxMs,900)}}resolvePauseMsFromUnits(Q){let Y=this.getStructuralPauseProfile(),J=Math.max(0.25,Math.min(4,Number(this.ttsConfig.rate||1))),G=Y.baseMs*Math.max(0,Q)/J;return Math.max(Y.minMs,Math.min(Y.maxMs,Math.round(G)))}resolveHighlightMode(){let Y=(this.ttsConfig.providerOptions||{}).highlightMode;if(Y==="word"||Y==="sentence")return Y;if((this.currentProvider?.providerId||"").toLowerCase()==="browser")return"sentence";return this.currentProvider?.getCapabilities().supportsWordBoundary??!1?"word":"sentence"}hasExplicitBreakSemantics(Q){if(!Q.includes("<"))return!1;return/<\s*break\b|<\s*speak\b|<\s*prosody\b|<\s*p\b|<\s*s\b/i.test(Q)}isElementHidden(Q){return X9(Q)}getBoundaryStrength(Q){let Y=Number(Q.getAttribute("data-tts-break-ms"));if(Number.isFinite(Y)&&Y>0)return"major";let J=Q.tagName.toUpperCase();if(J.match(/^H[1-6]$/))return"major";let G=(Q.getAttribute("role")||"").toLowerCase();if(G==="heading")return"major";if(G==="listitem"||G==="row"||G==="option"||G==="radio"||J==="LI")return"section";if(typeof window<"u"){let X=window.getComputedStyle(Q).display;if(X==="block"||X==="list-item"||X.startsWith("table")||X==="flex"||X==="grid")return"minor"}return"minor"}getBoundaryAnchor(Q,Y){let J=Q.parentElement,G=null;while(J&&J!==Y){if(this.isElementHidden(J))return null;let j=Number(J.getAttribute("data-tts-break-ms"));if(Number.isFinite(j)&&j>0)return{anchor:J,units:j/this.getStructuralPauseProfile().baseMs};let Z=(J.getAttribute("role")||"").toLowerCase(),B=J.tagName.toUpperCase();if(B.match(/^H[1-6]$/)||Z==="heading"||Z==="listitem"||B==="LI"){G=J;break}if(!G){if(typeof window<"u"){let W=window.getComputedStyle(J).display;if(W==="block"||W==="list-item"||W.startsWith("table")||W==="flex"||W==="grid")G=J}}J=J.parentElement}if(!G)return null;let X=this.getBoundaryStrength(G);return{anchor:G,units:this.getStructuralPauseProfile().units[X]}}createSpeechPlan(Q,Y,J=0){let G=this.collectSpeechPlanBoundaries(Q,Y);if(J===0)return this.createSpeechPlanSegments(Y,G);let X=new Map;for(let[j,Z]of G)X.set(j-J,Z);return this.createSpeechPlanSegments(Y,X)}collectSpeechPlanBoundaries(Q,Y){let J=new Map,{map:G}=F7(Q,this.getTextProcessingOptions()),X=this.createNodeStartOffsets(G),j=document.createTreeWalker(Q,NodeFilter.SHOW_TEXT),Z=j.nextNode(),B=null;while(Z){let W=Z,K=W.parentElement;if(K&&!this.isElementHidden(K)&&!W1(W)){let U=this.getBoundaryAnchor(W,Q),_=X.get(W);if(U&&_!==void 0&&U.anchor!==B&&_>0)J.set(_,Math.max(J.get(_)||0,U.units)),B=U.anchor}Z=j.nextNode()}return J}createNodeStartOffsets(Q){let Y=new Map;for(let[J,G]of Q.entries())if(!Y.has(G.node))Y.set(G.node,J);return Y}createSpeechPlanSegments(Q,Y){let J=Array.from(Y.keys()).filter((W)=>W>0&&W<Q.length).sort((W,K)=>W-K),G=[],X=0;for(let W of J){let K=Q.substring(X,W),U=K.match(/^\s*/)?.[0].length||0,_=K.match(/\s*$/)?.[0].length||0,$=X+U,N=W-_;if(N>$){let D=Q.substring($,N);G.push({text:D,startOffset:$,pauseMsAfter:this.resolvePauseMsFromUnits(Y.get(W)||0)})}X=W}let Z=Q.substring(X).match(/^\s*/)?.[0].length||0,B=X+Z;if(B<Q.length)G.push({text:Q.substring(B).trimEnd(),startOffset:B,pauseMsAfter:0});return G.filter((W)=>W.text.trim().length>0)}segmentSentences(Q){let Y=this.ttsConfig.providerOptions?.locale||void 0;return S7(Q,{locale:Y})}createSeekSegmentsFromText(Q){return this.segmentSentences(Q).map((Y)=>{let J=Y.text.match(/^\s*/)?.[0].length||0;return{text:Y.text.trim(),startOffset:Y.offset+J,pauseMsAfter:0}}).filter((Y)=>Y.text.length>0)}splitSegmentsAtBoundaries(Q,Y,J){if(Q.length===0||Y.length===0)return Q;let G=Array.from(new Set(Y)).filter((j)=>Number.isFinite(j)&&j>0).sort((j,Z)=>j-Z);if(G.length===0)return Q;let X=[];for(let j of Q){let Z=j.startOffset,B=j.startOffset+j.text.length,W=G.filter((U)=>U>Z&&U<B);if(W.length===0){X.push(j);continue}let K=Z;for(let U of[...W,B]){let _=J.substring(K,U),$=_.match(/^\s*/)?.[0].length||0,N=_.match(/\s*$/)?.[0].length||0,D=K+$,O=U-N;if(O>D)X.push({text:J.substring(D,O),startOffset:D,pauseMsAfter:0});K=U}}return X}createSentenceHighlightSegments(Q){let Y=this.createSeekSegmentsFromText(Q.contentToSpeak);if(!Q.shouldUsePlan||Q.playbackSegments.length===0)return Y;let J=Q.playbackSegments.map((G)=>G.startOffset).filter((G)=>G>0);return this.splitSegmentsAtBoundaries(Y,J,Q.contentToSpeak)}createSeekSegmentsFromSpeechChunks(Q){let Y=0;return Q.map((J)=>{let G=J.plainFallback?.speechText||(this.hasExplicitBreakSemantics(J.speechText)?J.visibleText:J.speechText)||J.visibleText,X=T(G)||J.visibleText||"",j={text:X,startOffset:Y,pauseMsAfter:0};return Y+=Math.max(1,X.length+1),j})}getCurrentSeekSegmentIndex(){if(this.seekSegments.length===0)return 0;let Q=0;for(let Y=0;Y<this.seekSegments.length;Y++)if(this.seekSegments[Y].startOffset<=this.currentBoundaryOffset)Q=Y;else break;return Q}async speakWithPlan(Q,Y,J){if(!this.provider||Q.length===0)return;let G=J?.highlightMode==="sentence",X=this.provider;if(!G&&typeof X.speakSegments==="function"){this.currentBoundaryOffset=0;let j=this.provider.onWordBoundary;this.provider.onWordBoundary=(Z,B,W)=>{if(j?.(Z,B,W),Number.isFinite(B))this.currentBoundaryOffset=B};try{await X.speakSegments(Q)}finally{if(Y===this.speakRunId&&this.provider===X)this.provider.onWordBoundary=j}return}this.configureWordBoundaryHighlighting({highlightMode:J?.highlightMode||"word",wordBoundaryOffset:this.activeWordBoundaryOffset});for(let j of Q){if(Y!==this.speakRunId)return;if(this.currentBoundaryOffset=j.startOffset,G)this.runWhenPlaybackStarts(Y,()=>{this.highlightSentenceSegment(j.startOffset,j.text)});await this.provider.speak(j.text);let Z=j.pauseMsAfter??0;if(Z>0)await new Promise((B)=>setTimeout(B,Z))}}highlightSentenceSegment(Q,Y){if(!this.highlightCoordinator||typeof document>"u")return;let J=Y.trimEnd().length;if(J<=0)return;let G=Q+this.activeWordBoundaryOffset,X=this.normalizedToDOM.get(G),j=this.normalizedToDOM.get(G+J-1);if(!X||!j)return;let Z=document.createRange();Z.setStart(X.node,X.offset),Z.setEnd(j.node,j.offset+1),this.paintTTSSentenceRanges([Z]),this.activeSentenceStartOffset=Q}getSegmentIndexForOffset(Q,Y){if(Q.length===0)return-1;let J=-1;for(let G=0;G<Q.length;G++)if(Q[G].startOffset<=Y)J=G;else break;return J}highlightSentenceForOffset(Q){let Y=this.sentenceHighlightSegments;if(!this.highlightCoordinator||Y.length===0)return;let J=this.getSegmentIndexForOffset(Y,Q);if(J<0)return;let G=Y[J];if(!G)return;if(this.activeSentenceStartOffset===G.startOffset)return;this.highlightSentenceSegment(G.startOffset,G.text)}findHighlightRange(Q,Y){let J=this.normalizedToDOM.get(Q);if(!J)return console.warn(`[TTSService] No mapping found for start position ${Q}`,{totalMappings:this.normalizedToDOM.size,nearbyMappings:Array.from(this.normalizedToDOM.entries()).filter(([j])=>Math.abs(j-Q)<5).map(([j,{offset:Z,node:B}])=>({pos:j,offset:Z,char:B.textContent?.[Z]}))}),null;let G=Q+Y-1,X=this.normalizedToDOM.get(G);if(!X)return console.warn(`[TTSService] No mapping found for end position ${G}`,{startChar:Q,length:Y,totalMappings:this.normalizedToDOM.size}),null;if(J.node!==X.node)return console.warn("[TTSService] Word spans multiple nodes, highlighting in first node only"),{node:J.node,start:J.offset,end:(J.node.textContent||"").length};return{node:J.node,start:J.offset,end:X.offset+1}}async speak(Q,Y){if(!this.provider)throw Error("TTS service not initialized");let J=++this.speakRunId;this.clearPlaybackStartBarrier();let G=null;try{if(await this.applyLanguageSettings(Y),J!==this.speakRunId)return;let X=await this.resolveSpeechContent(Q,Y);if(J!==this.speakRunId)return;let{contentToSpeak:j,speechText:Z,highlightText:B,normalizedText:W,usedCatalogSpoken:K,speechSource:U,speechMatchesVisibleText:_,speechChunks:$}=X;this.logResolvedSpeechContent({contentToSpeak:j,speechSource:U,catalogId:Y?.catalogId}),this.initializeSpeakTracking(B,Y);let N=Y?.highlightModeOverride||(_?this.resolveHighlightMode():"sentence");this.activeHighlightMode=N,this.activeWordBoundaryOffset=Y?.wordBoundaryOffset||0;let D=this.hasExplicitBreakSemantics(j),O=!!this.currentContentElement&&!K&&!D&&_;if(this.playbackChunks=$?.length?$:[],this.seekSegments=this.playbackChunks.length?this.createSeekSegmentsFromSpeechChunks(this.playbackChunks):D||!_?[]:O&&this.currentContentElement?this.createSpeechPlan(this.currentContentElement,W,Y?.wordBoundaryOffset||0):this.createSeekSegmentsFromText(B),this.sentenceHighlightSegments=D?[]:this.createSentenceHighlightSegments({contentToSpeak:B,shouldUsePlan:O,playbackSegments:this.seekSegments}),this.setState(w.LOADING),G=this.installPlaybackStartBarrier(J,!!this.playbackChunks[0]?.audio),this.prepareHighlightsForSpeak({contentToSpeak:B,options:Y,highlightMode:N,shouldUsePlan:O,runId:J}),_)this.configureWordBoundaryHighlighting({highlightMode:N,wordBoundaryOffset:Y?.wordBoundaryOffset||0});else this.clearWordBoundaryHighlighting();if(!G)this.setState(w.PLAYING);if(this.activePlaybackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1)),await this.executeSpeakPlayback({shouldUsePlan:O,runId:J,highlightMode:N,contentToSpeak:Z,speechChunks:$}),J!==this.speakRunId)return;this.setState(w.IDLE),this.clearHighlightsAndTracking()}catch(X){let j=X;if(console.error("TTS error:",j),this.lastError=j instanceof Error?j.message:String(j),J!==this.speakRunId)return;throw this.setState(w.ERROR),this.clearHighlightsAndTracking(),j}finally{this.clearPlaybackStartBarrier(G)}}async switchProviderToBrowser(Q,Y){if(!this.currentProvider)return!1;let J=new g7,G=this.currentProvider.providerId,X={};if(this.ttsConfig.rate!==void 0)X.rate=this.ttsConfig.rate;if(this.ttsConfig.pitch!==void 0)X.pitch=this.ttsConfig.pitch;if(this.ttsConfig.mathTokenHighlighting!==void 0)X.mathTokenHighlighting=this.ttsConfig.mathTokenHighlighting;let j=Y?.operation||"tts-initialize",Z=Y?.contentToSpeak??"",B=Z.replace(/\s+/g," ").trim().slice(0,120),W=Z.length>0?{textLength:Z.length,textPreview:B.length<Z.length?`${B}…`:B}:{};try{return this.provider?.stop(),this.currentProvider.destroy(),this.currentProvider=J,this.provider=await J.initialize(X),this.ttsConfig=X,await this.emitTelemetry("pie-tool-runtime-fallback",{toolId:"textToSpeech",operation:j,fromProvider:G,toProvider:J.providerId,reason:Q instanceof Error?Q.message:String(Q),...W}),console.warn("[TTSService] TTS provider initialization failed; switched to browser fallback",{fromProvider:G,reason:Q,...W}),!0}catch(K){return await this.emitTelemetry("pie-tool-runtime-fallback-error",{toolId:"textToSpeech",operation:j,fromProvider:G,toProvider:"browser",errorType:"TTSRuntimeFallbackError",message:K instanceof Error?K.message:String(K)}),console.error("[TTSService] Failed to switch to browser fallback provider",K),!1}}isBrowserSpeechFallbackAvailable(){if(typeof window>"u")return!1;if(!("speechSynthesis"in window))return!1;return typeof globalThis.SpeechSynthesisUtterance==="function"}async applyLanguageSettings(Q){if(!Q?.language||!this.provider)return;let Y=this.ttsConfig.providerOptions||{},J=Y.textNormalization||{},G=Y.segmenter||{},X={...Y,locale:Q.language,textNormalization:{...J,locale:Q.language},segmenter:{...G,locale:Q.language}};if(this.ttsConfig={...this.ttsConfig,providerOptions:X},"updateSettings"in this.provider&&typeof this.provider.updateSettings==="function")await this.provider.updateSettings({providerOptions:X})}async resolveSpeechContent(Q,Y){let J=T(Q);if(Y?.ignoreCatalogs)return{contentToSpeak:J,speechText:J,visibleText:J,highlightText:J,usedCatalogSpoken:!1,speechSource:"dom-or-input",normalizedText:J,containsMathMarkup:!1,speechMatchesVisibleText:!0};if(Y?.catalogId&&this.catalogResolver){let j=this.catalogResolver.getAlternative(Y.catalogId,{type:"spoken",language:Y.language||"en-US",useFallback:!0,context:Y.catalogContext,form:"content"}),Z=j?.content;if(j&&Z!==void 0){let B=Y?.contentElement?O7(Y.contentElement,this.getTextProcessingOptions(Y.language)).visibleText||J:J,W=T(Z);return this.debugLog(`[TTSService] Using catalog content for "${Y.catalogId}" (${j.language})`),{contentToSpeak:Z,speechText:Z,visibleText:B,highlightText:B,usedCatalogSpoken:!0,speechSource:"catalog-spoken",normalizedText:B,containsMathMarkup:!1,speechMatchesVisibleText:W===B}}this.debugLog(`[TTSService] No catalog found for "${Y.catalogId}", falling back to generated TTS`)}let G=Y?.contentElement?this.resolveCatalogComposedSpeechContent(Y.contentElement,J,Y):null;if(G)return G;return{...Y?.contentElement?await this.resolveGeneratedSpeechContent(Y.contentElement,J,Y.language):{contentToSpeak:J,speechText:J,visibleText:J,highlightText:J,normalizedText:J,containsMathMarkup:!1,speechMatchesVisibleText:!0},usedCatalogSpoken:!1,speechSource:"dom-or-input"}}resolveCatalogComposedSpeechContent(Q,Y,J){if(!this.catalogResolver)return null;let G=this.collectCatalogSpeechChunks(Q,J);if(!G.some((Z)=>Z.sourceElement))return null;let X=T(G.map((Z)=>Z.speechText).join(" ")),j=O7(Q,this.getTextProcessingOptions(J.language)).visibleText||Y;return{contentToSpeak:X,speechText:X,visibleText:j,highlightText:j,usedCatalogSpoken:!0,speechSource:"catalog-spoken",normalizedText:j,containsMathMarkup:!1,speechMatchesVisibleText:G.every((Z)=>Z.speechMatchesVisibleText),speechChunks:G}}collectCatalogSpeechChunks(Q,Y){let J=[],G="",X=()=>{let K=T(G);if(G="",!K)return;J.push({speechText:K,visibleText:K,sourceElement:null,speechMatchesVisibleText:!0})},j=(K)=>{let U=K.getAttribute("data-catalog-idref");if(!U)return null;let _={type:"spoken",language:Y.language||"en-US",useFallback:!0,context:Y.catalogContext},$=this.catalogResolver.getAlternative(U,{..._,form:"payload"}),N=$?.payload?w0({payload:$.payload})??void 0:void 0,O=this.catalogResolver.getAlternative(U,{..._,form:"content"})?.content;if(N===void 0&&O===void 0)return null;return{script:O,audio:N}},Z=(K,U)=>{let _=B(K);if(_.length!==1)return null;let $=_[0],N=O7($,this.getTextProcessingOptions(Y.language)).visibleText||T($.textContent||""),D=(O)=>T(O).replace(/\s+/g,"");return D(N)===D(U)?$:null},B=(K)=>{let U=Array.from(K.querySelectorAll("math"));if(K.localName?.toLowerCase()==="math")return[K,...U];return U},W=(K)=>{if($7(K,Q))return;if(K.nodeType===Node.TEXT_NODE){G+=` ${K.textContent||""}`;return}if(K.nodeType!==Node.ELEMENT_NODE)return;let U=K,_=j(U);if(_){X();let $=O7(U,this.getTextProcessingOptions(Y.language)),N=$.visibleText||T(U.textContent||""),D=F1(U,Q),O=_.script!==void 0?(()=>{let P=_.script,F=U1({speechText:P,visibleText:N}),L=Z(U,N),C=L?f7({mathElement:L,speechText:P}):void 0,v=C?void 0:B(U).map((k)=>({element:k,alignment:f7({mathElement:k,speechText:P})}));return{speechText:P,visibleText:N,sourceElement:U,regionElement:D,speechMatchesVisibleText:T(P)===N,playbackMode:F.playbackMode,alignment:F,mathAlignment:C,mathAlignments:v,visibleMap:$.map}})():null;if(_.audio){J.push(O?{...O,audio:_.audio,plainFallback:O}:{speechText:N,visibleText:N,sourceElement:U,regionElement:D,speechMatchesVisibleText:!1,visibleMap:$.map,audio:_.audio});return}if(O)J.push(O);return}for(let $ of Array.from(U.childNodes))W($)};return W(Q),X(),J}resolveGeneratedPlaybackFormat(){let Q=this.currentProvider;if(!Q)return"plain";if(Q.providerId?.toLowerCase()==="browser")return"plain";return Q.getCapabilities?.().supportsSSML?"ssml":"plain"}async resolveGeneratedSpeechContent(Q,Y,J){let G=this.resolveGeneratedPlaybackFormat(),{plan:X,containsMathMarkup:j,visibleText:Z}=await z9({contentRoot:Q,language:J,mathSpeech:this.getMathSpeechOptions(),textProcessingOptions:this.getTextProcessingOptions(J),produceSsml:G==="ssml",resolveMathSpeech:this.generatedMathSpeechResolver}),B=Z||Y;if(!j)return{contentToSpeak:B,speechText:B,visibleText:B,highlightText:B,normalizedText:B,containsMathMarkup:!1,speechMatchesVisibleText:!0};let W=O9(X,{format:G}),K=X.plainSpeechText;return{contentToSpeak:K,speechText:K,visibleText:B,highlightText:B,normalizedText:B,containsMathMarkup:!0,speechMatchesVisibleText:K===B,speechChunks:W}}logResolvedSpeechContent(Q){let Y=Q.contentToSpeak.replace(/\s+/g," ").trim().slice(0,200);this.debugLog("[TTSService] Speak resolved content",{source:Q.speechSource,catalogId:Q.catalogId||null,length:Q.contentToSpeak.length,preview:Y})}initializeSpeakTracking(Q,Y){this.currentText=Q,this.currentContentElement=Y?.contentElement||null,this.lastError=null,this.currentBoundaryOffset=0,this.playbackChunks=[],this.activeSentenceStartOffset=null}prepareHighlightsForSpeak(Q){if(!this.currentContentElement||!this.highlightCoordinator)return;if(this.buildPositionMap(this.currentContentElement,Q.contentToSpeak,Q.options?.language),Q.highlightMode==="sentence"&&Q.shouldUsePlan)return;let Y=this.sentenceHighlightSegments[0]||this.seekSegments[0];this.runWhenPlaybackStarts(Q.runId,()=>{if(Y)this.highlightSentenceSegment(Y.startOffset,Y.text),this.debugLog("[TTSService] Applied initial sentence highlighting");else try{let J=document.createRange();J.selectNodeContents(this.currentContentElement),this.paintTTSSentenceRanges([J])}catch{}})}configureWordBoundaryHighlighting(Q){if(!this.provider||Q.highlightMode!=="word"||!this.highlightCoordinator||!this.currentContentElement)return;this.provider.onWordBoundary=(Y,J,G)=>{let X=G||Y.length,j=J+this.currentBoundaryOffset,Z=j+Q.wordBoundaryOffset;this.highlightSentenceForOffset(j);let B=this.findHighlightRange(Z,X);if(B&&this.highlightCoordinator){let W=B.node.textContent?.substring(B.start,B.end)||"";this.debugLog(`[TTSService] Highlighting "${W}" (word: "${Y}") at position ${Z}`);let K=this.createTextRange(B.node,B.start,B.end);if(K)this.paintTTSWordRange(this.resolveWordHighlightRange(K).range);else this.highlightCoordinator.highlightTTSWord(B.node,B.start,B.end)}else console.warn(`[TTSService] Could not find highlight range for position ${Z}, length ${X}`)}}clearWordBoundaryHighlighting(){if(this.provider)this.provider.onWordBoundary=void 0}highlightCatalogRegion(Q){let Y=Q.regionElement||Q.sourceElement;if(!Y&&!Q.regionRange||!this.highlightCoordinator)return;try{if(this.lastRenderedRegionTarget=null,Q.regionRange){this.highlightCoordinator.clearHighlights?.(u.TTS_WORD),this.paintTTSSentenceRanges([Q.regionRange]);return}if(!Y)return;let J=document.createRange();J.selectNodeContents(Y),this.highlightCoordinator.clearHighlights?.(u.TTS_WORD),this.paintTTSSentenceRanges([J])}catch{}}highlightCatalogActiveRange(Q){if(!this.highlightCoordinator)return;this.paintTTSWordRange(this.resolveWordHighlightRange(Q).range)}highlightRenderableRegionTarget(Q){if(!this.highlightCoordinator||!Q||typeof document>"u")return;if(!this.highlightTargetResolverProvider&&K2(this.lastRenderedRegionTarget,Q))return;try{let Y=document.createRange();if(Q.type==="element")Y.selectNodeContents(Q.element);else if(Q.type==="range"){this.paintTTSSentenceRanges([Q.range]),this.lastRenderedRegionTarget=Q;return}else Y.setStart(Q.node,Q.startOffset),Y.setEnd(Q.node,Q.endOffset);this.paintTTSSentenceRanges([Y]),this.lastRenderedRegionTarget=Q}catch{}}highlightRenderableActiveTarget(Q){if(!this.highlightCoordinator||typeof document>"u")return;if(!Q){this.highlightCoordinator.clearHighlights(u.TTS_WORD);return}if(Q.type==="text-range"){let X=this.createTextRange(Q.node,Q.startOffset,Q.endOffset);if(X)this.paintTTSWordRange(this.resolveWordHighlightRange(X).range);else this.highlightCoordinator.highlightTTSWord(Q.node,Q.startOffset,Q.endOffset);return}if(Q.type==="range"){this.highlightCatalogActiveRange(Q.range);return}let Y=document.createRange();Y.selectNodeContents(Q.element);let J=this.resolveWordHighlightRange(Y);if(J.remapped){this.paintTTSWordRange(J.range);return}let G=Q.element.childNodes.length===1?Q.element.firstChild:null;if(Q.quality==="semantic-token"&&G?.nodeType===Node.TEXT_NODE){this.highlightCoordinator.highlightTTSWord(G,0,G.textContent?.length||0);return}this.highlightCoordinator.highlightTTSWordElement?.(Q.element)}renderHighlightDecision(Q){this.highlightRenderableRegionTarget(Q.regionTarget),this.highlightRenderableActiveTarget(Q.activeTarget)}async speakCatalogChunk(Q,Y){try{await this.speakCatalogChunkOnce(Q,Y)}catch(J){if(Q.plainFallback&&Y===this.speakRunId){if(this.debugLog("[TTSService] SSML chunk speak failed; retrying plain text",{message:J instanceof Error?J.message:String(J)}),this.playbackStartDeferredRunId===Y&&this.provider&&!("onPlaybackStart"in this.provider))this.pendingPlaybackStartHighlights=[],this.clearPlaybackStartBarrier(),this.setState(w.PLAYING);await this.speakCatalogChunkOnce(Q.plainFallback,Y);return}throw J}}async playRecordedAudio(Q,Y){if(typeof document>"u")throw Error("[tts] no document available to play recorded audio");let J=Q.sources[0],G=document.createElement("audio");G.preload="auto",G.src=q2(J.src,Q.fragment),G.playbackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate||1)),await new Promise((X,j)=>{let Z,B=!1,W=!1,K=()=>{if(W||B)return;B=!0,Y?.()},U=()=>{if(G.removeEventListener("ended",_),G.removeEventListener("error",$),G.removeEventListener("playing",K),Z?.(),this.activeRecordedAudio?.element===G)this.activeRecordedAudio=null},_=()=>{if(W)return;W=!0,U(),X()},$=()=>{if(W)return;W=!0,U(),j(Error(`[tts] recorded audio failed to play: ${J.src}`))};this.activeRecordedAudio={element:G,cancel:()=>{if(W)return;W=!0,U(),G.pause(),X()}},G.addEventListener("ended",_),G.addEventListener("error",$),G.addEventListener("playing",K),Z=W2(G,Q.fragment,_),Promise.resolve(G.play()).then(K).catch($)}).finally(()=>{if(this.activeRecordedAudio?.element===G)this.activeRecordedAudio=null;G.pause(),G.removeAttribute("src")})}cancelRecordedAudio(){let Q=this.activeRecordedAudio;if(!Q)return;this.activeRecordedAudio=null,Q.cancel()}async speakCatalogChunkOnce(Q,Y){if(!this.provider)return;if(this.lastRenderedRegionTarget=null,Q.audio){this.runWhenPlaybackStarts(Y,()=>{this.highlightCatalogRegion(Q)}),await this.playRecordedAudio(Q.audio,()=>{this.notifyPlaybackStarted(Y)});return}let J=Q.regionElement||Q.sourceElement||this.currentContentElement,G=J?E8({contentRoot:J,chunks:[Q]})[0]:null,X=this.ttsConfig.mathTokenHighlighting!==!1,j=G?R8({chunks:[G],mathTokenHighlighting:X}):null;if(this.runWhenPlaybackStarts(Y,()=>{if(j&&G&&Q.mathAlignment)this.renderHighlightDecision(j.resolveInitial(G.id));else this.highlightCatalogRegion(Q)}),!(Q.sourceElement&&(Q.mathAlignment&&Q.mathAlignment.speech.tokens.length>0||Q.mathAlignments&&Q.mathAlignments.length>0||Q.alignment&&Q.visibleMap&&(Q.playbackMode==="exact-word"||Q.playbackMode==="anchor-span")))){let U=this.provider,_=U.onWordBoundary;U.onWordBoundary=void 0;try{await U.speak(Q.speechText)}finally{if(this.provider===U&&Y===this.speakRunId&&U.onWordBoundary===void 0)U.onWordBoundary=_}return}let B=this.provider,W=B.onWordBoundary,K=(U,_,$)=>{if(Y!==this.speakRunId)return;if(j&&G){let N=G.offsetSpace==="unsupported"?"unknown":G.offsetSpace;this.renderHighlightDecision(j.resolveBoundary({chunkId:G.id,word:U,position:_,length:$,providerOffsetSpace:N}));return}};B.onWordBoundary=K;try{await B.speak(Q.speechText)}finally{if(this.provider===B&&Y===this.speakRunId&&B.onWordBoundary===K)B.onWordBoundary=W}}async executeSpeakPlayback(Q){if(Q.speechChunks?.length&&this.provider){for(let Y=0;Y<Q.speechChunks.length;Y++){if(Q.runId!==this.speakRunId)return;let J=this.seekSegments[Y];if(J)this.currentBoundaryOffset=J.startOffset;let G=Q.speechChunks[Y];await this.speakCatalogChunk(G,Q.runId)}return}if(Q.shouldUsePlan&&this.currentContentElement){let Y=this.seekSegments;if(Y.length>0)await this.speakWithPlan(Y,Q.runId,{highlightMode:Q.highlightMode});else if(this.provider)await this.provider.speak(Q.contentToSpeak);return}if(this.provider)await this.provider.speak(Q.contentToSpeak)}clearHighlightsAndTracking(){if(this.pendingPlaybackStartHighlights=[],this.activePlaybackRate=null,this.highlightCoordinator)this.highlightCoordinator.clearTTS();this.lastRenderedRegionTarget=null,this.currentContentElement=null,this.normalizedToDOM.clear(),this.currentBoundaryOffset=0,this.activeWordBoundaryOffset=0,this.seekSegments=[],this.playbackChunks=[],this.sentenceHighlightSegments=[],this.activeSentenceStartOffset=null}selectMappedRangeText(Q,Y){if(typeof Q.comparePoint!=="function")return null;let{text:J,map:G}=F7(Y,this.getTextProcessingOptions()),X=-1,j=-1;for(let[K,{node:U,offset:_}]of G){if(K>=J.length)continue;let $=!1;try{$=Q.comparePoint(U,_)===0&&Q.comparePoint(U,Math.min(_+1,U.length))===0}catch{$=!1}if(!$)continue;if(X===-1||K<X)X=K;if(K>j)j=K}if(X===-1)return null;let Z=J.slice(X,j+1),B=Z.length-Z.trimStart().length,W=Z.trim();return W?{text:W,offset:X+B}:null}async speakRange(Q,Y){if(!this.provider)throw Error("TTS service not initialized");if(W1(Q.commonAncestorContainer)){console.warn("[tts] selection lies inside content marked not-to-be-spoken; nothing was spoken. Selecting a node and pressing read-aloud must not become a way around suppression.");return}let G=Y?.contentRoot||null;if(!G){let K=Q.commonAncestorContainer;G=K.nodeType===Node.ELEMENT_NODE?K:K.parentElement}if(!G)return;let X=Z9(Q,G),j=X.text.trim();if(!j){if(X.filtered)console.warn("[tts] every part of the selection is either hidden or marked not-to-be-spoken; nothing was spoken.");return}let Z=this.selectMappedRangeText(Q,G),B=j,W=Z?.offset??0;if(Z)B=Z.text;else{let K=document.createRange();K.selectNodeContents(G),K.setEnd(Q.startContainer,Q.startOffset);let U=Z9(K,G).text,_=T(U);W=_.length+(/\s$/.test(U)&&_?1:0)}this.debugLog("[TTSService] speakRange offset calculation:",{selectedText:B,mapped:!!Z,offset:W,rootTag:G.tagName}),await this.speak(B,{contentElement:G,ignoreCatalogs:!0,wordBoundaryOffset:W})}pause(){if(!this.provider)return;if(this.state===w.PLAYING)this.activeRecordedAudio?.element.pause(),this.provider.pause(),this.setState(w.PAUSED)}resume(){if(!this.provider)return;if(this.state===w.PAUSED){let Q=this.activeRecordedAudio?.element;if(Q)Promise.resolve(Q.play()).catch(()=>{});this.provider.resume(),this.setState(w.PLAYING)}}normalizePlaybackRate(Q){if(!Number.isFinite(Q))return 1;return Math.max(0.25,Math.min(4,Q))}async restartFromSeekIndex(Q){if(!this.provider||this.seekSegments.length===0)return;let Y=Math.max(0,Math.min(this.seekSegments.length-1,Q)),J=this.playbackChunks.length?this.playbackChunks.slice(Y):null;this.speakRunId+=1,this.clearPlaybackStartBarrier(),this.cancelRecordedAudio(),this.provider.onWordBoundary=void 0,this.provider.stop();let G=++this.speakRunId,X=this.seekSegments.slice(Y);this.highlightCoordinator?.clearTTS(),this.activeSentenceStartOffset=null,this.setState(w.LOADING);let j=this.installPlaybackStartBarrier(G,!!J?.[0]?.audio);if(!j)this.setState(w.PLAYING);this.activePlaybackRate=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1));try{if(this.configureWordBoundaryHighlighting({highlightMode:this.activeHighlightMode,wordBoundaryOffset:this.activeWordBoundaryOffset}),J)for(let Z=0;Z<J.length;Z++){if(G!==this.speakRunId)return;let B=Y+Z,W=this.seekSegments[B];if(W)this.currentBoundaryOffset=W.startOffset;await this.speakCatalogChunk(J[Z],G)}else await this.speakWithPlan(X,G,{highlightMode:this.activeHighlightMode});if(G!==this.speakRunId)return;this.setState(w.IDLE),this.clearHighlightsAndTracking()}catch(Z){if(G!==this.speakRunId)return;throw this.lastError=Z instanceof Error?Z.message:String(Z),this.setState(w.ERROR),this.clearHighlightsAndTracking(),Z}finally{this.clearPlaybackStartBarrier(j)}}async setPlaybackRate(Q){if(!this.provider)throw Error("TTSService not initialized. Call initialize() first.");let Y=this.normalizePlaybackRate(Q),J=this.pendingPlaybackRateRequest;if(J?.rate===Y){await J.promise;return}let G=++this.playbackRateRequestId,X=this.playbackRateWriteQueue.then(async()=>{let B=this.speakRunId;if(G!==this.playbackRateRequestId)return{didUpdate:!1,playbackRunId:B};let W=this.normalizePlaybackRate(Number(this.ttsConfig.rate??1));if(Y===W)return{didUpdate:!1,playbackRunId:B};return await this.updateSettings({rate:Y}),{didUpdate:!0,playbackRunId:B}});this.playbackRateWriteQueue=X.then(()=>{return},()=>{return});let j=X.then(async(B)=>{if(G!==this.playbackRateRequestId||B.playbackRunId!==this.speakRunId)return;let W=this.activePlaybackRate!==null&&this.activePlaybackRate!==Y;if(!B.didUpdate&&!W)return;if(this.state!==w.PLAYING&&this.state!==w.LOADING||!this.currentText||this.seekSegments.length===0||this.hasExplicitBreakSemantics(this.currentText))return;await this.restartFromSeekIndex(this.getCurrentSeekSegmentIndex())}),Z;Z=j.finally(()=>{if(this.pendingPlaybackRateRequest?.promise===Z)this.pendingPlaybackRateRequest=null}),this.pendingPlaybackRateRequest={rate:Y,promise:Z},await Z}async seekBy(Q){if(!this.provider||!this.currentText)return;if(this.state!==w.PLAYING&&this.state!==w.PAUSED)return;if(this.hasExplicitBreakSemantics(this.currentText))return;if(this.seekSegments.length===0)return;let Y=Number.isFinite(Q)?Math.trunc(Q):0;if(Y===0)return;let J=this.getCurrentSeekSegmentIndex(),G=Math.max(0,Math.min(this.seekSegments.length-1,J+Y));if(G===J)return;await this.restartFromSeekIndex(G)}async seekForward(Q=1){let Y=Number.isFinite(Q)?Math.max(1,Math.trunc(Q)):1;await this.seekBy(Y)}async seekBackward(Q=1){let Y=Number.isFinite(Q)?Math.max(1,Math.trunc(Q)):1;await this.seekBy(-Y)}stop(){if(!this.provider)return;if(this.speakRunId+=1,this.clearPlaybackStartBarrier(),this.cancelRecordedAudio(),this.provider.onWordBoundary=void 0,this.provider.stop(),this.setState(w.IDLE),this.currentText=null,this.highlightCoordinator)this.highlightCoordinator.clearTTS();this.lastRenderedRegionTarget=null,this.currentContentElement=null,this.normalizedToDOM.clear(),this.currentBoundaryOffset=0,this.activeWordBoundaryOffset=0,this.seekSegments=[],this.playbackChunks=[],this.sentenceHighlightSegments=[],this.activeSentenceStartOffset=null,this.activePlaybackRate=null}requestControlHandoff(){if(typeof window>"u")return;let Q={source:"host"};window.dispatchEvent(new CustomEvent(C8,{detail:Q}))}isPlaying(){return this.state===w.PLAYING}isPaused(){return this.state===w.PAUSED}getState(){return this.state}getCurrentText(){return this.currentText}getLastError(){return this.lastError}onStateChange(Q,Y){if(!this.listeners.has(Q))this.listeners.set(Q,new Set);this.listeners.get(Q).add(Y)}offStateChange(Q,Y){let J=this.listeners.get(Q);if(J){if(J.delete(Y),J.size===0)this.listeners.delete(Q)}}setState(Q){if(this.state===Q)return;let Y=this.state;this.state=Q;for(let J of this.listeners.values())for(let G of J)G(Q);if(this.emitTelemetry("pie-tool-playback-state-changed",{toolId:"textToSpeech",providerId:"tts",previousState:Y,state:Q}),Q===w.PLAYING){let J=Y===w.PAUSED?"pie-tool-playback-resume":"pie-tool-playback-start";this.emitTelemetry(J,{toolId:"textToSpeech",providerId:"tts",previousState:Y,state:Q});return}if(Q===w.PAUSED){this.emitTelemetry("pie-tool-playback-pause",{toolId:"textToSpeech",providerId:"tts",previousState:Y,state:Q});return}if(Q===w.ERROR){this.emitTelemetry("pie-tool-playback-error",{toolId:"textToSpeech",providerId:"tts",previousState:Y,state:Q,message:this.lastError||void 0});return}if(Q===w.IDLE&&(Y===w.PLAYING||Y===w.PAUSED||Y===w.LOADING))this.emitTelemetry("pie-tool-playback-stop",{toolId:"textToSpeech",providerId:"tts",previousState:Y,state:Q})}}var U2=new Set(["reserved-row","expanding-row","floating-overlay","left-aligned"]),P9=(Q)=>Q&&typeof Q==="object"?Q:{},V2=(Q)=>Q==="polly"||Q==="google"||Q==="server",i=(Q,Y)=>Q===void 0?Y:Q,A2=(Q,Y="left-aligned")=>typeof Q==="string"&&U2.has(Q)?Q:Y,YY=Object.freeze([0.8,1.25]),JY=Object.freeze([{rate:0.8,label:"Slow",ariaLabel:"Slow speed"},{rate:1,label:"Normal",ariaLabel:"Normal speed",default:!0},{rate:1.25,label:"Fast",ariaLabel:"Fast speed"}]);var GY=Object.freeze([0.8,1,1.25]);var _2=(Q)=>{let Y={...Q,layoutMode:A2(Q.layoutMode)},J=Q.backend||"browser";if(!V2(J))return Y;let G={...Y,apiEndpoint:i(Y.apiEndpoint,"/api/tts"),transportMode:i(Y.transportMode,"pie"),endpointValidationMode:i(Y.endpointValidationMode,"voices"),validateEndpoint:i(Y.validateEndpoint,!0),includeAuthOnAssetFetch:i(Y.includeAuthOnAssetFetch,!1),rate:i(Y.rate,1),language:i(Y.language,"en-US")};if(J==="polly")return{...G,defaultVoice:i(G.defaultVoice,"Joanna"),engine:i(G.engine,"neural"),format:i(G.format,"mp3"),speechMarksMode:i(G.speechMarksMode,"word+sentence")};if(J==="google")return{...G,defaultVoice:i(G.defaultVoice,"en-US-Wavenet-A")};return G},y8=(Q)=>{let Y=P9(Q),J=P9(Y.settings),{provider:G,...X}={...Y,...J};return _2({...X,...typeof G==="string"?{provider:G}:{}})},L9=(Q)=>Q.backend||"browser",$2=(Q,Y)=>{if(Y==="polly"||Y==="google")return Y;if(Y==="server")return Q.serverProvider||Q.provider;return Q.serverProvider||Q.provider},F2=(Q,Y)=>Q.transportMode||(Y==="custom"?"custom":"pie"),f8=(Q)=>{let Y=L9(Q),J=$2(Q,Y),G=F2(Q,J),X=j7(Q.mathSpeech);return{voice:Q.defaultVoice,rate:Q.rate,pitch:Q.pitch,providerOptions:{...P9(Q.providerOptions),...Q.language?{locale:Q.language}:{},...Y==="polly"&&Q.engine?{engine:Q.engine}:{},...Y==="polly"&&typeof Q.sampleRate==="number"?{sampleRate:Q.sampleRate}:{},...Y==="polly"&&Q.format?{format:Q.format}:{},...Y==="polly"?{speechMarkTypes:Q.speechMarksMode==="word+sentence"?["word","sentence"]:["word"]}:{},...G==="custom"&&typeof Q.cache==="boolean"?{cache:Q.cache}:{},...G==="custom"&&Q.speedRate?{speedRate:Q.speedRate}:{},...G==="custom"&&Q.lang_id?{lang_id:Q.lang_id}:{},...X?{mathSpeech:X}:{}},apiEndpoint:Q.apiEndpoint,provider:J,language:Q.language,transportMode:G,endpointMode:Q.endpointMode,endpointValidationMode:Q.endpointValidationMode,includeAuthOnAssetFetch:Q.includeAuthOnAssetFetch,assetOrigins:Q.assetOrigins,credentials:Q.credentials,headers:Q.headers,validateEndpoint:Q.validateEndpoint,...typeof Q.mathTokenHighlighting==="boolean"?{mathTokenHighlighting:Q.mathTokenHighlighting}:{}}};class H1{providers=new Map;configs=new Map;initialized=new Map;initializationPromises=new Map;async emitTelemetry(Q,Y,J){try{await Q.onTelemetry?.(Y,J)}catch(G){console.warn("[ToolProviderRegistry] Telemetry callback failed:",G)}}register(Q,Y){if(this.providers.has(Q)){console.warn(`[ToolProviderRegistry] Provider "${Q}" already registered, skipping`);return}if(this.providers.set(Q,Y.provider),this.configs.set(Q,Y),this.initialized.set(Q,!1),console.log(`[ToolProviderRegistry] Registered provider "${Q}" (${Y.provider.providerName})`),Y.lazy===!1)this.initialize(Q).catch((J)=>{console.error(`[ToolProviderRegistry] Failed to initialize provider "${Q}":`,J)})}async initialize(Q){if(this.initialized.get(Q))return;let Y=this.initializationPromises.get(Q);if(Y)return Y;let J=this._doInitialize(Q);this.initializationPromises.set(Q,J);try{await J}finally{this.initializationPromises.delete(Q)}}async _doInitialize(Q){let Y=this.providers.get(Q),J=this.configs.get(Q);if(!Y||!J)throw Error(`[ToolProviderRegistry] Provider "${Q}" not registered`);let G={...J.config},X=(Z)=>{if(!Z||typeof Z!=="object")return"unknown";let B=Z;return(typeof B.backend==="string"?B.backend:typeof B.provider==="string"?B.provider:typeof B.serverProvider==="string"?B.serverProvider:typeof B.providerId==="string"?B.providerId:"")||"unknown"},j=Date.now();if(await this.emitTelemetry(J,"pie-tool-init-start",{toolId:Q,providerId:Q,backend:X(G),operation:"provider-initialize"}),Y.requiresAuth&&J.authFetcher){let Z=Date.now();await this.emitTelemetry(J,"pie-tool-backend-call-start",{toolId:Q,providerId:Q,backend:X(G),operation:"auth-fetch"}),console.log(`[ToolProviderRegistry] Fetching auth for "${Q}"...`);try{let B=await J.authFetcher();G={...G,...B},await this.emitTelemetry(J,"pie-tool-backend-call-success",{toolId:Q,providerId:Q,backend:X(G),operation:"auth-fetch",duration:Date.now()-Z})}catch(B){throw await this.emitTelemetry(J,"pie-tool-backend-call-error",{toolId:Q,providerId:Q,backend:X(G),operation:"auth-fetch",duration:Date.now()-Z,errorType:"ProviderAuthFetchError",message:B instanceof Error?B.message:String(B)}),console.error(`[ToolProviderRegistry] Auth fetch failed for "${Q}":`,B),Error(`Failed to fetch auth credentials for provider "${Q}"`)}}try{await Y.initialize(G),this.initialized.set(Q,!0),await this.emitTelemetry(J,"pie-tool-init-success",{toolId:Q,providerId:Q,backend:X(G),operation:"provider-initialize",duration:Date.now()-j}),console.log(`[ToolProviderRegistry] Provider "${Q}" initialized`)}catch(Z){throw await this.emitTelemetry(J,"pie-tool-init-error",{toolId:Q,providerId:Q,backend:X(G),operation:"provider-initialize",duration:Date.now()-j,errorType:"ProviderInitializationError",message:Z instanceof Error?Z.message:String(Z)}),console.error(`[ToolProviderRegistry] Initialization failed for "${Q}":`,Z),Z}}async getProvider(Q,Y=!0){let J=this.providers.get(Q);if(!J)throw console.error("[ToolProviderRegistry] Provider not found:",{requestedId:Q,availableProviders:Array.from(this.providers.keys())}),Error(`[ToolProviderRegistry] Provider "${Q}" not registered`);if(Y&&!this.initialized.get(Q))console.log("[ToolProviderRegistry] Auto-initializing provider:",Q),await this.initialize(Q);return J}getProvidersByCategory(Q){return Array.from(this.providers.entries()).filter(([Y,J])=>J.category===Q).map(([Y])=>Y)}getProviderIds(){return Array.from(this.providers.keys())}has(Q){return this.providers.has(Q)}isInitialized(Q){return this.initialized.get(Q)===!0}isInitializing(Q){return this.initializationPromises.has(Q)}async unregister(Q){let Y=this.providers.get(Q);if(Y){let J=this.initializationPromises.get(Q);if(J)try{await J}catch{}Y.destroy(),this.providers.delete(Q),this.configs.delete(Q),this.initialized.delete(Q),this.initializationPromises.delete(Q),console.log(`[ToolProviderRegistry] Unregistered provider "${Q}"`)}}async destroy(){let Q=Array.from(this.providers.keys());await Promise.all(Q.map((Y)=>this.unregister(Y))),console.log("[ToolProviderRegistry] Registry destroyed")}}class w9{targets=new Set;changeListeners=new Set;registerTarget(Q){return this.targets.add(Q),this.notifyChange(),()=>{if(!this.targets.delete(Q))return;this.notifyChange()}}canRequest(Q,Y){return this.findTarget(Q,Y)!==null}request(Q){let Y=this.findTarget(Q.toolId,Q.level);if(!Y)return!1;try{Y.open(Q.toolId,Q.params)}catch(J){return console.error(`[ToolRequestRegistry] Target failed to open "${Q.toolId}":`,J),!1}return!0}onTargetsChange(Q){return this.changeListeners.add(Q),()=>{this.changeListeners.delete(Q)}}findTarget(Q,Y){let J=this.findTargetAtLevel(Q,Y??"section");if(J||Y!==void 0)return J;for(let G of this.targets){if(G.level==="section")continue;if(this.hostsTool(G,Q))return G}return null}findTargetAtLevel(Q,Y){for(let J of this.targets){if(J.level!==Y)continue;if(this.hostsTool(J,Q))return J}return null}hostsTool(Q,Y){try{return Q.hostsTool(Y)===!0}catch(J){return console.warn(`[ToolRequestRegistry] Target at level "${Q.level}" failed the host check for "${Y}":`,J),!1}}notifyChange(){for(let Q of this.changeListeners)try{Q()}catch(Y){console.warn("[ToolRequestRegistry] Target change listener threw:",Y)}}dispose(){this.targets.clear(),this.changeListeners.clear()}}var H2=(Q)=>`No assessment is bound, so no policy source could grant "${Q}"`;function R9(Q,Y,J,G){return{featureId:Q,granted:!1,action:"block",rule:Y,precedence:0,sourceType:"host",reason:Y==="host-blocked"?"Listed in tools.policy.blocked":`Not listed in tools.policy.allowed (${J.join(", ")})`,required:!1,assessmentBound:G.assessmentBound}}function x8(Q,Y,J){let G=Y.decisions[0],X=Array.from(Y.perToolFlags.values())[0],j=G?.action==="enable",Z=G?.reason??`Feature "${Q}" not configured`;return{featureId:Q,granted:j,action:G?.action??"skip",rule:G?.rule??"pnp-support",precedence:G?.precedence??6,sourceType:G?.sourceType??"system",reason:J.assessmentBound||j?Z:H2(Q),required:Boolean(X?.required),parameters:X?.settings,assessmentBound:J.assessmentBound}}class E9{provenance;stepCounter=0;constructor(Q){this.provenance={contextId:Q,resolvedAt:new Date,sources:{},features:new Map,decisionLog:[],summary:{totalFeatures:0,enabled:0,blocked:0,notConfigured:0,bySource:{},byRule:{}}}}addSource(Q,Y){let J={id:Y.id,name:Y.name??Y.id};switch(Q){case"organization":this.provenance.sources.organization={...J,pnpDefaults:Y.config};break;case"assessment":this.provenance.sources.assessment={...J,settings:Y.config};break;case"section":this.provenance.sources.section={...J,settings:Y.config};break;case"item":this.provenance.sources.item={...J,settings:Y.config};break;case"student":this.provenance.sources.student={id:Y.id,pnpProfile:Y.config};break;case"host":this.provenance.sources.host={id:Y.id,config:Y.config};break}return this}addDecision(Q){let Y={step:++this.stepCounter,precedence:Q.precedence,rule:Q.rule,featureId:Q.featureId,action:Q.action,source:{type:Q.sourceType,id:Q.sourceId,name:Q.sourceName},reason:Q.reason,value:Q.value,timestamp:new Date};this.provenance.decisionLog.push(Y);let J=this.provenance.features.get(Q.featureId);if(!J)J={featureId:Q.featureId,finalState:"not-configured",allDecisions:[],explanation:""},this.provenance.features.set(Q.featureId,J);if(J.allDecisions.push(Y),Q.action==="advisory"){if(J.finalState==="not-configured")J.finalState="advisory-only"}else if(Q.action!=="skip"){if(!J.winningDecision||Y.precedence<J.winningDecision.precedence)J.winningDecision=Y,J.finalState=Y.action==="enable"?"enabled":"blocked"}return this.provenance.summary.bySource[Q.sourceType]=(this.provenance.summary.bySource[Q.sourceType]||0)+1,this.provenance.summary.byRule[Q.rule]=(this.provenance.summary.byRule[Q.rule]||0)+1,this}reconcileFinalStates(Q){for(let Y of Q){let J=this.provenance.features.get(Y);if(!J){J={featureId:Y,finalState:"enabled",allDecisions:[],explanation:""},this.provenance.features.set(Y,J);continue}J.finalState="enabled"}for(let Y of this.provenance.features.values()){if(Q.has(Y.featureId))continue;let J=Y.allDecisions.some((X)=>X.action!=="skip"&&X.action!=="advisory"),G=Y.allDecisions.some((X)=>X.action==="advisory");if(J)Y.finalState="blocked";else if(G)Y.finalState="advisory-only";else Y.finalState="not-configured"}return this}build(){for(let Q of this.provenance.features.values())Q.explanation=D2(Q);for(let Q of this.provenance.features.values())if(this.provenance.summary.totalFeatures++,Q.finalState==="enabled")this.provenance.summary.enabled++;else if(Q.finalState==="blocked")this.provenance.summary.blocked++;else this.provenance.summary.notConfigured++;return this.provenance}}function D2(Q){if(!Q.winningDecision){if(Q.finalState==="advisory-only"){let j=Q.allDecisions.find((Z)=>Z.action==="advisory");return j?`Feature "${Q.featureId}" was kept in its host-decided state; ${j.reason}`:`Feature "${Q.featureId}" carries an advisory note.`}return`Feature "${Q.featureId}" was not configured at any level.`}let Y=Q.winningDecision,J=Y.source.name||Y.source.type,G=`Feature "${Q.featureId}" is ${Q.finalState}.
|
|
216
216
|
|
|
217
|
-
`;
|
|
218
|
-
`,
|
|
219
|
-
`,
|
|
220
|
-
`;let X=
|
|
217
|
+
`;G+=`**Primary Reason** (${Y.rule}):
|
|
218
|
+
`,G+=`${Y.reason}
|
|
219
|
+
`,G+=`Source: ${J} (${Y.source.type})
|
|
220
|
+
`;let X=Q.allDecisions.filter((j)=>j.step!==Y.step&&j.action!=="skip"&&j.action!=="advisory"&&j.precedence>Y.precedence);if(X.length>0){G+=`
|
|
221
221
|
**Overridden Rules**:
|
|
222
|
-
`;for(let j of X)
|
|
223
|
-
`}return J}function b8(G){let{request:Q,tools:Y,pnpPolicy:J,customSources:X,contextId:j}=G,Z=new M1(j);Z.addSource("host",{id:Q.scope.scopeId,name:`${Q.level}:${Q.scope.scopeId}`,config:{placement:Y.placement,policy:Y.policy}});let q=L7(Y.placement[Q.level]),B=L7(Y.policy.allowed),K=new Set(L7(Y.policy.blocked)),W=[];for(let D of q)W.push(D),Z.addDecision({precedence:0,rule:"placement-membership",featureId:D,action:"skip",sourceType:"host",reason:`Listed in tools.placement.${Q.level}`});if(W=W.filter((D)=>{if(Y.providers?.[D]?.enabled===!1)return Z.addDecision({precedence:0,rule:"provider-disabled",featureId:D,action:"block",sourceType:"host",reason:`tools.providers.${D}.enabled === false`,value:!1}),!1;return!0}),B.length>0){let D=new Set(B);W=W.filter((P)=>{if(!D.has(P))return Z.addDecision({precedence:0,rule:"host-allowlist",featureId:P,action:"block",sourceType:"host",reason:"Not present in tools.policy.allowed",value:B}),!1;return!0})}W=W.filter((D)=>{if(K.has(D))return Z.addDecision({precedence:0,rule:"host-blocked",featureId:D,action:"block",sourceType:"host",reason:"Listed in tools.policy.blocked",value:Y.policy.blocked}),!1;return!0});let $=[],H=new Map;for(let D of W)H.set(D,["placement"]);let N=new Set(W),F=null;if(J.enforcement==="on"&&J.source&&(J.assessment||J.currentItemRef)){if(F=J.source.apply({assessment:J.assessment,currentItemRef:J.currentItemRef}),F.sources.assessment)Z.addSource("assessment",F.sources.assessment);if(F.sources.student)Z.addSource("student",F.sources.student);if(F.sources.item)Z.addSource("item",F.sources.item);for(let D of F.decisions)Z.addDecision({precedence:D.precedence,rule:D.rule,featureId:D.featureId,action:D.action,sourceType:D.sourceType,reason:D.reason,value:D.value});for(let D of F.unmappedSupportIds)$.push({code:"tool-policy.unknownSupportId",level:Q.level,toolId:D,message:`No registered tool claims PNP support id "${D}"; it was carried through as a feature id and matched nothing. Expected an AfA 3.0 / QTI 3.0 access feature id.`,source:"pnp.pnp-support"});W=W.filter((D)=>{return!F.blockedToolIds.has(D)});for(let D of Array.from(H.keys()))if(F.blockedToolIds.has(D))H.delete(D);for(let D of F.mandatedToolIds){if(!!N.has(D))continue;let v=F.perToolFlags.get(D)?.rule??"required-tool",I=MQ(D,{placement:q,allowed:B,blocked:K,providers:Y.providers}),p={rule:v,hostRule:I.hostRule,hostValue:I.hostValue};$.push({code:"tool-policy.requiredToolBlocked",level:Q.level,toolId:D,message:`Profile policy mandates "${D}" (${v}) but host policy removed it from level "${Q.level}" via ${I.hostRule}.`,details:p}),Z.addDecision({precedence:0,rule:"required-tool-blocked",featureId:D,action:"advisory",sourceType:"host",reason:`Host removed required tool "${D}" via ${I.hostRule}`,value:p})}for(let D of W){let P=F.perToolFlags.get(D);if(P){let S=H.get(D)??[];S.push(`pnp.${P.rule}`),H.set(D,S)}}}for(let D=0;D<X.length;D++){let P=X[D],S=W.slice(),v=P.refine({request:Q,candidates:S}),I=new Set(v.refinedCandidates);for(let E of v.refinedCandidates)if(!S.includes(E))$.push({code:"tool-policy.placementMissing",level:Q.level,toolId:E,message:`Custom source "${P.id}" tried to add tool "${E}" that was not in candidates; ignored.`,source:`custom.${P.id}`}),I.delete(E);W=S.filter((E)=>I.has(E));let p=new Set;if(v.decisions){for(let E of v.decisions)if(Z.addDecision({precedence:E.precedence??100+D,rule:E.rule,featureId:E.featureId,action:E.action,sourceType:E.sourceType,reason:E.reason,value:E.value}),E.action==="block")p.add(E.featureId)}for(let E of S){if(I.has(E))continue;if(p.has(E))continue;Z.addDecision({precedence:100+D,rule:"custom-source",featureId:E,action:"block",sourceType:"custom",reason:`Custom policy source "${P.id}" removed tool "${E}" from candidates without emitting a decision; auto-logged for trail completeness.`,value:{customSourceId:P.id}})}for(let E of W){let g=H.get(E)??["placement"];g.push(`custom.${P.id}`),H.set(E,g)}for(let E of S)if(!I.has(E))H.delete(E)}let O=new Set(W),L=W.map((D)=>{let P=F?.perToolFlags.get(D);return{toolId:D,required:P?.required??!1,alwaysAvailable:P?.alwaysAvailable??!1,settings:P?.settings,sources:H.get(D)??["placement"]}});return Z.reconcileFinalStates(O),{visibleTools:L,diagnostics:$,provenance:Z.build()}}function MQ(G,Q){if(!Q.placement.includes(G))return{hostRule:"placement-missing",hostValue:Q.placement};if(Q.providers?.[G]?.enabled===!1)return{hostRule:"provider-disabled",hostValue:!1};if(Q.allowed.length>0&&!Q.allowed.includes(G))return{hostRule:"host-allowlist",hostValue:Q.allowed};if(Q.blocked.has(G))return{hostRule:"host-blocked",hostValue:Array.from(Q.blocked)};return{hostRule:"placement-missing",hostValue:Q.placement}}function p0(G){if(!G)return!1;let Q=G.personalNeedsProfile;if(Q){if(Array.isArray(Q.supports)&&Q.supports.length>0)return!0;if(Array.isArray(Q.prohibitedSupports)&&Q.prohibitedSupports.length>0)return!0;if(Array.isArray(Q.activateAtInit)&&Q.activateAtInit.length>0)return!0}let Y=G.settings;if(Y){let J=Y.districtPolicy;if(J){if(Array.isArray(J.blockedTools)&&J.blockedTools.length>0)return!0;if(Array.isArray(J.requiredTools)&&J.requiredTools.length>0)return!0;if(J.policies&&typeof J.policies==="object"&&Object.keys(J.policies).length>0)return!0}let X=Y.testAdministration;if(X&&typeof X==="object")for(let j of Object.keys(X)){let Z=X[j];if(Z===void 0||Z===null)continue;if(Array.isArray(Z)&&Z.length===0)continue;if(typeof Z==="object"&&!Array.isArray(Z)&&Object.keys(Z).length===0)continue;return!0}}return!1}function g0(G){let Q=G?.settings;if(!Q)return!1;if(Array.isArray(Q.requiredTools)&&Q.requiredTools.length>0)return!0;if(Array.isArray(Q.restrictedTools)&&Q.restrictedTools.length>0)return!0;if(Q.toolParameters&&typeof Q.toolParameters==="object"&&Object.keys(Q.toolParameters).length>0)return!0;return!1}function l7(G){if(p0(G.assessment))return"on";if(g0(G.currentItemRef))return"on";return"off"}class z1{id="pnp";toolRegistry;constructor(G){this.toolRegistry=G}apply(G){let{ctx:Q,result:Y}=this.prepare(G),{pnp:J,districtPolicy:X,itemSettings:j}=Q,Z=new Set;J?.supports?.forEach((q)=>Z.add(q)),J?.prohibitedSupports?.forEach((q)=>Z.add(q)),X?.blockedTools?.forEach((q)=>Z.add(q)),X?.requiredTools?.forEach((q)=>Z.add(q)),j?.requiredTools?.forEach((q)=>Z.add(q)),j?.restrictedTools?.forEach((q)=>Z.add(q));for(let q of Z)this.resolveSupport(q,Q,Y);return Y}resolveFeature(G,Q){let{ctx:Y,result:J}=this.prepare(Q);return this.resolveSupport(G,Y,J),J}prepare(G){let{assessment:Q,currentItemRef:Y}=G,J=Q?.personalNeedsProfile,X=Q?.settings,j=Y?.settings,Z={blockedToolIds:new Set,mandatedToolIds:new Set,perToolFlags:new Map,decisions:[],unmappedSupportIds:new Set,sources:{}};if(X?.districtPolicy||X?.testAdministration)Z.sources.assessment={id:Q?.id||"unknown",name:Q?.name||Q?.id||"Assessment",config:X};if(J)Z.sources.student={id:"student",name:"Student PNP Profile",config:J};if(Y&&j)Z.sources.item={id:Y.identifier,name:Y.identifier,config:j};return{ctx:{pnp:J,districtPolicy:X?.districtPolicy,testAdmin:X?.testAdministration,itemSettings:j,toolConfigs:X?.toolConfigs},result:Z}}resolveSupport(G,Q,Y){if(Q.districtPolicy?.blockedTools?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.blockedToolIds.add(X),Y.decisions.push({precedence:1,rule:"district-block",featureId:X,action:"block",sourceType:"assessment",reason:`District policy blocks "${G}" for all assessments`,value:Q.districtPolicy.blockedTools});return}if(Q.testAdmin?.toolOverrides?.[G]===!1){let X=this.mapSupportToToolId(G,Y);Y.blockedToolIds.add(X),Y.decisions.push({precedence:2,rule:"test-admin-override",featureId:X,action:"block",sourceType:"assessment",reason:`Test administrator disabled "${G}" for this session`,value:Q.testAdmin.toolOverrides});return}if(Q.itemSettings?.restrictedTools?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.blockedToolIds.add(X),Y.decisions.push({precedence:3,rule:"item-restriction",featureId:X,action:"block",sourceType:"item",reason:`Item restricts "${G}" (e.g., mental math question blocks calculator)`,value:Q.itemSettings.restrictedTools});return}if(Q.itemSettings?.requiredTools?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.mandatedToolIds.add(X),Y.perToolFlags.set(X,{required:!0,alwaysAvailable:!1,settings:this.resolveToolSettings(G,Q),rule:"item-requirement",sourceType:"item"}),Y.decisions.push({precedence:4,rule:"item-requirement",featureId:X,action:"enable",sourceType:"item",reason:`Item requires "${G}" for this question`,value:Q.itemSettings.requiredTools});return}if(Q.districtPolicy?.requiredTools?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.mandatedToolIds.add(X),Y.perToolFlags.set(X,{required:!0,alwaysAvailable:!1,settings:this.resolveToolSettings(G,Q),rule:"district-requirement",sourceType:"assessment"}),Y.decisions.push({precedence:5,rule:"district-requirement",featureId:X,action:"enable",sourceType:"assessment",reason:`District policy requires "${G}" for all assessments`,value:Q.districtPolicy.requiredTools});return}if(Q.pnp?.prohibitedSupports?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.blockedToolIds.add(X),Y.decisions.push({precedence:6,rule:"pnp-prohibited",featureId:X,action:"block",sourceType:"student",reason:`Student PNP profile prohibits "${G}"`,value:Q.pnp.prohibitedSupports});return}if(Q.pnp?.supports?.includes(G)){let X=this.mapSupportToToolId(G,Y);Y.perToolFlags.set(X,{required:!1,alwaysAvailable:!0,settings:this.resolveToolSettings(G,Q),rule:"pnp-support",sourceType:"student"}),Y.decisions.push({precedence:6,rule:"pnp-support",featureId:X,action:"enable",sourceType:"student",reason:`Student PNP profile requests "${G}"`,value:Q.pnp.supports});return}let J=this.mapSupportToToolId(G,Y);Y.decisions.push({precedence:6,rule:"pnp-support",featureId:J,action:"skip",sourceType:"system",reason:`Feature "${G}" not configured at any level`,value:{supportId:G}})}mapSupportToToolId(G,Q){let Y=this.toolRegistry.getToolsByPNPSupport(G);if(Y.size===0){if(this.toolRegistry.getAllTools().length>0)Q.unmappedSupportIds.add(G);return G}return Array.from(Y)[0]}resolveToolSettings(G,Q){return Q.itemSettings?.toolParameters?.[G]??Q.toolConfigs?.[G]}}var c0=b7({policy:{allowed:[],blocked:[]},placement:{section:[],item:[],passage:[]},providers:{}});class O1{toolRegistry;contextId;pnpPolicySource;customSources;listeners=new Set;tools;assessment;currentItemRef;pnpEnforcement;disposed=!1;constructor(G){this.toolRegistry=G.toolRegistry,this.contextId=G.contextId??"tool-policy",this.pnpPolicySource=new z1(this.toolRegistry),this.customSources=G.customSources?[...G.customSources]:[];let Q=G.inputs??{};this.tools=Q.tools??c0,this.assessment=Q.assessment??null,this.currentItemRef=Q.currentItemRef??null,this.pnpEnforcement=Q.pnpEnforcement??l7({assessment:this.assessment,currentItemRef:this.currentItemRef})}decide(G){this.assertNotDisposed();let Q=G.scope.scopeId?`${this.contextId}:${G.level}:${G.scope.scopeId}`:`${this.contextId}:${G.level}`;return b8({request:G,tools:this.tools,pnpPolicy:{source:this.pnpPolicySource,assessment:this.assessment??void 0,currentItemRef:this.currentItemRef??void 0,enforcement:this.pnpEnforcement},customSources:this.customSources,contextId:Q})}decideFeature(G){this.assertNotDisposed();let Q=this.hostFeatureGate(G);if(Q)return Q;return u0(G,this.pnpPolicySource.resolveFeature(G,{assessment:this.assessment??void 0,currentItemRef:this.currentItemRef??void 0}),{assessmentBound:this.assessment!==null})}hostFeatureGate(G){let Q={assessmentBound:this.assessment!==null},Y=L7(this.tools.policy.blocked);if(Y.includes(G))return E8(G,"host-blocked",Y,Q);let J=L7(this.tools.policy.allowed);if(J.length>0&&!J.includes(G))return E8(G,"host-allowlist",J,Q);return null}getVisibleToolIds(G,Q){return this.decide({level:G,scope:{level:G,scopeId:Q}}).visibleTools.map((Y)=>Y.toolId)}updateInputs(G){this.assertNotDisposed();let Q=!1,Y=!1;if("tools"in G){let J=G.tools??c0;if(!Object.is(this.tools,J))this.tools=J,Q=!0}if("assessment"in G){let J=G.assessment??null;if(!Object.is(this.assessment,J))this.assessment=J,Q=!0}if("currentItemRef"in G){let J=G.currentItemRef??null;if(!Object.is(this.currentItemRef,J))this.currentItemRef=J,Q=!0}if("pnpEnforcement"in G&&G.pnpEnforcement){if(this.pnpEnforcement!==G.pnpEnforcement)this.pnpEnforcement=G.pnpEnforcement,Y=!0}if(Q||Y)this.emit({reason:Y&&!Q?"pnp-enforcement":"inputs",inputs:this.snapshotInputs()})}registerPolicySource(G){return this.assertNotDisposed(),this.customSources.push(G),this.emit({reason:"policy-source-added",inputs:this.snapshotInputs()}),()=>{let Q=this.customSources.indexOf(G);if(Q!==-1){if(this.customSources.splice(Q,1),!this.disposed)this.emit({reason:"policy-source-removed",inputs:this.snapshotInputs()})}}}onPolicyChange(G){return this.listeners.add(G),()=>{this.listeners.delete(G)}}getInputs(){return this.snapshotInputs()}dispose(){if(this.disposed)return;this.disposed=!0,this.emit({reason:"disposed",inputs:this.snapshotInputs()}),this.listeners.clear(),this.customSources.length=0}snapshotInputs(){return Object.freeze({tools:this.tools,assessment:this.assessment,currentItemRef:this.currentItemRef,pnpEnforcement:this.pnpEnforcement})}emit(G){for(let Q of Array.from(this.listeners))try{Q(G)}catch{}}assertNotDisposed(){if(this.disposed)throw Error("ToolPolicyEngine has been disposed.")}}var zQ=Symbol("@pie-players/tool-policy-engine");class d extends Error{constructor(){super("ToolkitCoordinator has been disposed.");this.name="ToolkitCoordinatorDisposedError"}}class T8 extends Error{constructor(){super("Section controller acquisition was retired during initialization.");this.name="SectionControllerRetiredError"}}var P1=(G)=>!!G&&typeof G==="object"&&!Array.isArray(G),OQ=(G,Q,Y)=>{let J={...Q,...Y};if(G==="textToSpeech"&&P1(Q.settings)&&P1(Y.settings)){if(J.settings={...Q.settings,...Y.settings},P1(Q.settings.mathSpeech)&&P1(Y.settings.mathSpeech))J.settings.mathSpeech={...Q.settings.mathSpeech,...Y.settings.mathSpeech}}return J},PQ=["item-selected","item-session-data-changed","item-session-meta-changed","item-complete-changed","content-loaded","item-player-error"],LQ=["section-navigation-change","section-session-applied","section-loading-complete","section-items-complete-changed","section-error","timed-media-cue-changed","timed-media-policy-degraded","timed-media-invalid"];class L1{assessmentId;config;ttsService;toolCoordinator;highlightCoordinator;elementToolStateStore;catalogResolver;toolProviderRegistry;hooks;lazyInit;ttsInitialized=!1;ttsInitPromise;ttsReconfigurePromise;stateLoaded=!1;stateLoadPromise;coordinatorReadyPromise;coordinatorReadyNotified=!1;providerInitPromises=new Map;toolRegistry;toolContextResolvers=new Map;toolContextResolverChangeListeners=new Set;toolRequests=new R8;sectionControllers=new Map;sectionControllerKeys=new Map;sectionControllerInitEntries=new Map;sectionControllerDisposePromises=new Map;sectionPersistenceStrategies=new Map;sectionControllerLifecycleListeners=new Set;activeSubscriptions=new Map;activeCohortMapKey=null;latestRequestedActiveCohortMapKey=null;telemetryListeners=new Set;frameworkErrorBus;ownsFrameworkErrorBus;frameworkErrorHookUnsubscribe=null;disposePromise=null;policyEngine;pnpEnforcementOverride=null;boundAssessment=null;boundCurrentItemRef=null;reportedUnboundFeaturePolicy=!1;static resolveConfig(G){let Q=i1(G.toolConfigStrictness),Y=G.toolRegistry??new S8,J=G.deferToolConfigValidation===!0?b7(G.tools):Z7(G.tools,{strictness:Q,source:"ToolkitCoordinator.init",toolRegistry:Y}).config;return{...G,toolConfigStrictness:Q,toolRegistry:Y,tools:{...J,providers:{...{textToSpeech:{enabled:!0,backend:"browser"},annotationToolbar:{enabled:!0}},...J.providers}},accessibility:{language:"en-US",...G.accessibility??{},catalogs:G.accessibility?.catalogs??[]}}}constructor(G){if(!G.assessmentId)throw Error("ToolkitCoordinator requires assessmentId in config");let Q=L1.resolveConfig(G);if(this.assessmentId=Q.assessmentId,this.config=Q,this.toolRegistry=Q.toolRegistry??new S8,this.installToolContextResolvers(Q.toolContextResolvers),this.hooks=Q.hooks??{},this.lazyInit=G.lazyInit===!0,this.pnpEnforcementOverride=this.resolveConfiguredPnpEnforcement(),this.frameworkErrorBus=G.frameworkErrorBus??new p7,this.ownsFrameworkErrorBus=!G.frameworkErrorBus,this.subscribeFrameworkErrorHookAdapters(),this.toolCoordinator=new X8,this.highlightCoordinator=new g7,this.elementToolStateStore=new Y8,this.catalogResolver=new Q8(Q.accessibility?.catalogs||[],Q.accessibility?.language||"en-US"),this.toolProviderRegistry=new F1,this._registerToolProviders(),this.ttsService=new c7,this.setupStatePersistenceHooks(),this.policyEngine=new O1({toolRegistry:this.toolRegistry,contextId:`toolkit-coordinator:${this.assessmentId}`,inputs:{tools:this.config.tools,assessment:null,currentItemRef:null,pnpEnforcement:this.resolveEffectivePnpEnforcement()}}),!this.lazyInit)this.waitUntilReady().catch((Y)=>{if(Y instanceof d)return;console.error("[ToolkitCoordinator] Failed eager initialization:",Y),this.handleError(Y,{phase:"coordinator-ready"})})}assertNotDisposed(){if(this.disposePromise!==null)throw new d}subscribeFrameworkErrorHookAdapters(){this.frameworkErrorHookUnsubscribe=this.frameworkErrorBus.subscribeFrameworkErrors((G)=>{let Q=this.hooks.onFrameworkError;if(!Q)return;try{Q(G)}catch(Y){console.warn("[ToolkitCoordinator] onFrameworkError hook failed:",Y)}})}async emitTelemetry(G,Q){try{await this.hooks.onTelemetry?.(G,Q)}catch(J){console.warn("[ToolkitCoordinator] telemetry hook failed:",J)}let Y=Q?{...Q}:void 0;for(let J of this.telemetryListeners)try{J({eventName:G,payload:Y?{...Y}:void 0})}catch(X){console.warn("[ToolkitCoordinator] telemetry listener failed:",X)}}emitSectionControllerLifecycle(G){for(let Q of this.sectionControllerLifecycleListeners)try{Q(G)}catch(Y){console.warn("[ToolkitCoordinator] section controller lifecycle listener failed:",Y)}}handleError(G,Q){let Y=X6({error:G,context:Q});this.frameworkErrorBus.reportFrameworkError(Y)}subscribeFrameworkErrors(G){return this.frameworkErrorBus.subscribeFrameworkErrors(G)}reportFrameworkError(G){this.frameworkErrorBus.reportFrameworkError(G)}getSectionControllerMapKey(G){return`${G.assessmentId}::${G.sectionId}::${G.attemptId||""}`}createDefaultSectionPersistence(){let G=(()=>{try{if(typeof window>"u")return null;return window.localStorage}catch{return null}})(),Q=(Y)=>{let{assessmentId:J,sectionId:X,attemptId:j}=Y.key;return`pie:section-controller:v1:${J}:${X}:${j||"default"}`};return{async loadSession(Y){if(!G)return null;let J=G.getItem(Q(Y));if(!J)return null;try{return JSON.parse(J)}catch{return null}},async saveSession(Y,J){if(!G)return;G.setItem(Q(Y),JSON.stringify(J))},async clearSession(Y){if(!G)return;G.removeItem(Q(Y))}}}async resolveSectionPersistence(G){let Q=this.getSectionControllerMapKey(G.key),Y=this.sectionPersistenceStrategies.get(Q);if(Y)return Y;let J={createDefaultPersistence:()=>this.createDefaultSectionPersistence()},X=await this.hooks.createSectionSessionPersistence?.(G,J)??await J.createDefaultPersistence();return this.sectionPersistenceStrategies.set(Q,X),X}setupStatePersistenceHooks(){this.elementToolStateStore.setOnStateChange((G)=>{if(!this.hooks.saveToolState)return;Promise.resolve(this.hooks.saveToolState(G)).catch((Q)=>{this.handleError(Q,{phase:"state-save"})})})}async ensureStateLoaded(){if(this.stateLoaded)return;if(this.stateLoadPromise)return this.stateLoadPromise;return this.stateLoadPromise=(async()=>{let G=this.hooks.loadToolState;if(!G)return;try{let Q=await G();if(this.assertNotDisposed(),Q&&typeof Q==="object")this.elementToolStateStore.loadState(Q);this.stateLoaded=!0,await this.emitTelemetry("pie-toolkit-tool-state-loaded",{hasState:Boolean(Q)})}catch(Q){if(Q instanceof d)throw Q;this.handleError(Q,{phase:"state-load"})}})().finally(()=>{this.stateLoadPromise=void 0}),this.stateLoadPromise}_registerToolProviders(){let G=this.getProviderDescriptorTools();for(let Q of G)this.registerProviderFromTool(Q)}getProviderDescriptorTools(){return this.toolRegistry.getAllTools().filter((G)=>!!G.provider)}async registerProviderFromTool(G){let Q=G.provider;if(!Q)return;let Y=this.getToolConfig(G.toolId)||void 0;if(Y?.enabled===!1)return;let J=Q.getProviderId?.(Y)??Y?.provider?.id??G.toolId;if(this.toolProviderRegistry.has(J))return;let X=Q.createProvider(Y),j=Q.getInitConfig?.(Y)??Y?.provider?.init??{},Z=this.addToolTelemetryReporter({toolId:G.toolId,providerId:J,initConfig:j}),q=this.createToolTelemetryForwarder({toolId:G.toolId,providerId:J}),B=Q.getAuthFetcher?.(Y)??Y?.provider?.runtime?.authFetcher;await this.registerProvider(J,{provider:X,config:Z,lazy:Q.lazy??!0,authFetcher:B,onTelemetry:q})}createToolTelemetryForwarder(G){return async(Q,Y)=>{await this.emitTelemetry(Q,{...Y||{},toolId:G.toolId,providerId:G.providerId})}}addToolTelemetryReporter(G){let Q=G.initConfig&&typeof G.initConfig==="object"?{...G.initConfig}:{},Y=typeof Q.onTelemetry==="function"?Q.onTelemetry:null,J=this.createToolTelemetryForwarder({toolId:G.toolId,providerId:G.providerId});return Q.onTelemetry=async(X,j)=>{if(Y)await Y(X,j);await J(X,j)},Q}async registerProvider(G,Q){try{this.toolProviderRegistry.register(G,Q);let Y={providerId:G,providerName:Q.provider.providerName};await this.hooks.onProviderRegistered?.(G,Y),await this.emitTelemetry("pie-toolkit-provider-registered",{providerId:G,providerName:Q.provider.providerName})}catch(Y){console.warn(`[ToolkitCoordinator] Failed to register provider "${G}":`,Y),this.handleError(Y,{phase:"provider-register",providerId:G})}}async ensureProviderReady(G){this.assertNotDisposed();let Q=this.providerInitPromises.get(G);if(Q)return Q;let Y=(async()=>{let J=await this.toolProviderRegistry.getProvider(G,!1);this.assertNotDisposed();let X={providerId:G,providerName:J.providerName};try{return await this.hooks.onProviderInitStart?.(G,X),this.assertNotDisposed(),await this.toolProviderRegistry.initialize(G),this.assertNotDisposed(),await this.hooks.onProviderReady?.(G,X),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-provider-ready",{providerId:G}),this.assertNotDisposed(),J}catch(j){if(j instanceof d)throw j;let Z=j instanceof Error?j:Error(String(j));throw this.handleError(Z,{phase:"provider-init",providerId:G}),Z}})().finally(()=>{this.providerInitPromises.delete(G)});return this.providerInitPromises.set(G,Y),Y}setHooks(G){if(Object.assign(this.hooks,G),this.setupStatePersistenceHooks(),this.disposePromise===null&&G.onCoordinatorReady&&this.isReady())Promise.resolve(G.onCoordinatorReady(this)).catch((Q)=>{this.handleError(Q,{phase:"coordinator-ready"})})}subscribeTelemetry(G){return this.telemetryListeners.add(G),()=>{this.telemetryListeners.delete(G)}}getSectionController(G){let Q={assessmentId:this.assessmentId,sectionId:G.sectionId,attemptId:G.attemptId};return this.sectionControllers.get(this.getSectionControllerMapKey(Q))}subscribeSectionEvents(G){if(this.activeCohortMapKey===null)throw Error("[ToolkitCoordinator] subscribeSectionEvents requires an active section cohort; call getOrCreateSectionController first.");let Q=this.activeSubscriptions.get(G.listener);if(Q)Q.unsubscribeCurrent?.(),Q.unsubscribeCurrent=null;let Y={listener:G.listener,eventTypes:G.eventTypes,itemIds:G.itemIds,unsubscribeCurrent:null};this.activeSubscriptions.set(G.listener,Y);let J=this.sectionControllers.get(this.activeCohortMapKey);if(J)this.bindSubscriptionToController(Y,J);let X=!1;return()=>{if(X)return;if(X=!0,Y.unsubscribeCurrent?.(),Y.unsubscribeCurrent=null,this.activeSubscriptions.get(G.listener)===Y)this.activeSubscriptions.delete(G.listener)}}bindSubscriptionToController(G,Q){G.unsubscribeCurrent?.(),G.unsubscribeCurrent=null;let Y=Q.subscribe;if(typeof Y!=="function")return;let J=this.buildSectionEventPredicate(G);G.unsubscribeCurrent=Y.call(Q,(Z)=>{if(!J(Z))return;this.deliverSectionEventSafely(G.listener,Z)});let X=this.buildContentLoadedReplayEvents(Q);for(let Z of X)if(J(Z))this.deliverSectionEventSafely(G.listener,Z);let j=this.buildLoadingCompleteReplayEvent(Q);if(j&&J(j))this.deliverSectionEventSafely(G.listener,j)}deliverSectionEventSafely(G,Q){try{G(Q)}catch(Y){console.warn("[ToolkitCoordinator] section-event listener failed:",Y)}}setActiveCohort(G){if(this.activeCohortMapKey===G)return;this.activeCohortMapKey=G;let Q=this.sectionControllers.get(G);if(!Q)return;for(let Y of Array.from(this.activeSubscriptions.values()))this.bindSubscriptionToController(Y,Q)}setActiveCohortIfLatestRequest(G){if(this.latestRequestedActiveCohortMapKey!==G)return;this.setActiveCohort(G)}suspendActiveCohortIfSuperseded(G){if(this.activeCohortMapKey===null)return;if(this.activeCohortMapKey===G)return;this.activeCohortMapKey=null;for(let Q of Array.from(this.activeSubscriptions.values()))Q.unsubscribeCurrent?.(),Q.unsubscribeCurrent=null}clearActiveCohortIfMatches(G){if(this.activeCohortMapKey!==G)return;this.activeCohortMapKey=null;for(let Q of Array.from(this.activeSubscriptions.values()))Q.unsubscribeCurrent?.(),Q.unsubscribeCurrent=null}buildSectionEventPredicate(G){let Q=G.eventTypes?new Set(G.eventTypes):null,Y=G.itemIds?new Set(G.itemIds):null;return(J)=>{if(Q||Y){let X=J?.type||null;if(Q&&(!X||!Q.has(X)))return!1;if(Y){if(!Array.from(this.collectEventItemIds(J)).some((Z)=>Y.has(Z)))return!1}}return!0}}collectEventItemIds(G){let Q=new Set;if("itemId"in G&&typeof G.itemId==="string")Q.add(G.itemId);if("canonicalItemId"in G&&typeof G.canonicalItemId==="string")Q.add(G.canonicalItemId);if("currentItemId"in G&&typeof G.currentItemId==="string")Q.add(G.currentItemId);if("previousItemId"in G&&typeof G.previousItemId==="string")Q.add(G.previousItemId);return Q}buildContentLoadedReplayEvents(G){let Q=G.getRuntimeState?.(),Y=Q?.loadedRenderables;if(!Array.isArray(Y)||Y.length===0)return[];let J=typeof Q?.currentItemIndex==="number"&&Number.isFinite(Q.currentItemIndex)?Q.currentItemIndex:0,X=Date.now(),j=[];for(let Z of Y){if(!Z)continue;let q=Z.itemId,B=typeof Z.canonicalItemId==="string"&&Z.canonicalItemId?Z.canonicalItemId:q;if(typeof q!=="string"||!q)continue;j.push({type:"content-loaded",contentKind:Z.contentKind??"unknown",itemId:q,canonicalItemId:B,currentItemIndex:J,timestamp:X})}return j}buildLoadingCompleteReplayEvent(G){let Q=G.getRuntimeState?.();if(Q?.loadingComplete!==!0)return null;let Y=typeof Q.totalRegistered==="number"&&Number.isFinite(Q.totalRegistered)?Math.max(0,Q.totalRegistered):0,J=typeof Q.totalLoaded==="number"&&Number.isFinite(Q.totalLoaded)?Math.max(0,Q.totalLoaded):Y;return{type:"section-loading-complete",totalRegistered:Y,totalLoaded:J,currentItemIndex:Q.currentItemIndex,timestamp:Date.now()}}subscribeItemEvents(G){return this.subscribeSectionEvents({eventTypes:G.eventTypes||PQ,itemIds:G.itemIds,listener:G.listener})}subscribeSectionLifecycleEvents(G){return this.subscribeSectionEvents({eventTypes:G.eventTypes||LQ,listener:G.listener})}onSectionControllerLifecycle(G){return this.sectionControllerLifecycleListeners.add(G),()=>{this.sectionControllerLifecycleListeners.delete(G)}}async getOrCreateSectionController(G){if(this.disposePromise!==null)throw new d;let Q={assessmentId:this.assessmentId,sectionId:G.sectionId,attemptId:G.attemptId},Y=this.getSectionControllerMapKey(Q);this.latestRequestedActiveCohortMapKey=Y,this.suspendActiveCohortIfSuperseded(Y);let J=await this.resolveExistingSectionController({mapKey:Y,key:Q,input:G.input,updateExisting:G.updateExisting});if(J){if(this.disposePromise!==null)throw new d;return J}let X=this.sectionControllerDisposePromises.get(Y);if(X)await Promise.allSettled([X]);if(this.disposePromise!==null)throw new d;let j=this.sectionControllerInitEntries.get(Y);if(j)return j.promise;let Z={retired:!1,candidateClaimed:!1},q=this.initializeNewSectionController({args:G,key:Q,mapKey:Y,token:Z}).catch((B)=>{throw this.handleSectionControllerInitError(B,G),B}).finally(()=>{if(this.sectionControllerInitEntries.get(Y)?.token===Z)this.sectionControllerInitEntries.delete(Y)});return this.sectionControllerInitEntries.set(Y,{key:Q,token:Z,promise:q}),q}async resolveExistingSectionController(G){let Q=this.sectionControllers.get(G.mapKey);if(!Q)return;if(this.sectionControllerKeys.set(G.mapKey,G.key),G.updateExisting!==!1)await Q.updateInput?.(G.input);if(this.sectionControllers.get(G.mapKey)!==Q)return;return this.setActiveCohortIfLatestRequest(G.mapKey),Q}createSectionControllerContext(G){return{key:G.key,coordinator:this,input:G.input}}async initializeNewSectionController(G){let Q=this.createSectionControllerContext({key:G.key,input:G.args.input}),Y=await this.resolveSectionPersistence(Q);if(this.disposePromise!==null||G.token.retired){if(this.sectionPersistenceStrategies.get(G.mapKey)===Y)this.sectionPersistenceStrategies.delete(G.mapKey);throw this.createSectionControllerRetirementError()}let J={createDefaultController:G.args.createDefaultController},X=await this.hooks.createSectionController?.(Q,J)??await J.createDefaultController(),j={mapKey:G.mapKey,key:G.key,controller:X,persistence:Y,token:G.token};try{return await this.retireUnpublishedSectionControllerIfNeeded(j),await X.configureSessionPersistence?.({strategy:Y,context:Q}),await this.retireUnpublishedSectionControllerIfNeeded(j),await X.initialize?.(G.args.input),await this.retireUnpublishedSectionControllerIfNeeded(j),await X.hydrate?.(),await this.finalizeSectionControllerReady({...j,context:Q}),X}catch(Z){throw await this.cleanupUnpublishedSectionController(j),Z}}createSectionControllerRetirementError(){return this.disposePromise!==null?new d:new T8}async retireUnpublishedSectionControllerIfNeeded(G){if(this.disposePromise===null&&!G.token.retired)return;throw await this.cleanupUnpublishedSectionController(G),this.createSectionControllerRetirementError()}async cleanupUnpublishedSectionController(G){if(G.token.candidateClaimed)return;G.token.candidateClaimed=!0;try{await G.controller.dispose?.()}catch(Q){this.handleError(Q,{phase:"section-controller-dispose",details:{sectionId:G.key.sectionId,attemptId:G.key.attemptId}})}finally{if(this.sectionPersistenceStrategies.get(G.mapKey)===G.persistence)this.sectionPersistenceStrategies.delete(G.mapKey)}}retirePublishedSectionControllerIfNeeded(G){if(this.disposePromise!==null&&!G.token.retired)this.disposeSectionController({sectionId:G.key.sectionId,attemptId:G.key.attemptId});if(G.token.retired)throw this.createSectionControllerRetirementError()}async finalizeSectionControllerReady(G){await this.retireUnpublishedSectionControllerIfNeeded(G),this.sectionControllers.set(G.mapKey,G.controller),this.sectionControllerKeys.set(G.mapKey,G.key),G.token.candidateClaimed=!0,this.setActiveCohortIfLatestRequest(G.mapKey),this.emitSectionControllerLifecycle({type:"ready",key:G.key,controller:G.controller}),await this.hooks.onSectionControllerReady?.(G.context,G.controller),this.retirePublishedSectionControllerIfNeeded(G),await this.emitTelemetry("pie-toolkit-section-controller-ready",{assessmentId:G.key.assessmentId,sectionId:G.key.sectionId,attemptId:G.key.attemptId}),this.retirePublishedSectionControllerIfNeeded(G)}handleSectionControllerInitError(G,Q){if(G instanceof d||G instanceof T8)return;this.handleError(G,{phase:"section-controller-init",details:{sectionId:Q.sectionId,attemptId:Q.attemptId}})}disposeSectionController(G){let Q={assessmentId:this.assessmentId,sectionId:G.sectionId,attemptId:G.attemptId},Y=this.getSectionControllerMapKey(Q),J=this.sectionControllerInitEntries.get(Y);if(J)J.token.retired=!0;let X=this.sectionControllers.get(Y);if(!X){let K=this.sectionControllerDisposePromises.get(Y);if(K)return K;if(!J)return Promise.resolve();let W=Promise.allSettled([J.promise]).then(()=>{return});return this.trackSectionControllerDisposal(Y,W)}let j=this.sectionPersistenceStrategies.get(Y);if(this.clearActiveCohortIfMatches(Y),this.sectionControllers.get(Y)===X)this.sectionControllers.delete(Y),this.sectionControllerKeys.delete(Y),this.sectionPersistenceStrategies.delete(Y),this.emitSectionControllerLifecycle({type:"disposed",key:Q});let Z=this.createSectionControllerContext({key:Q,input:void 0}),q=this.disposeSectionControllerEntry({args:G,key:Q,context:Z,controller:X,persistenceStrategy:j}),B=J?Promise.allSettled([J.promise]).then(()=>q):q;return this.trackSectionControllerDisposal(Y,B)}trackSectionControllerDisposal(G,Q){this.sectionControllerDisposePromises.set(G,Q);let Y=()=>{if(this.sectionControllerDisposePromises.get(G)===Q)this.sectionControllerDisposePromises.delete(G)};return Q.then(Y,Y),Q}async disposeSectionControllerEntry(G){try{await this.runSectionControllerDisposePipeline({key:G.key,context:G.context,controller:G.controller,persistBeforeDispose:G.args.persistBeforeDispose})}catch(Q){this.handleError(Q,{phase:"section-controller-dispose",details:{sectionId:G.args.sectionId,attemptId:G.args.attemptId}})}finally{await this.finalizeSectionControllerDispose({context:G.context,persistenceStrategy:G.persistenceStrategy,clearPersistence:G.args.clearPersistence})}}async runSectionControllerDisposePipeline(G){let Q=[];if(G.persistBeforeDispose!==!1)try{await G.controller.persist?.()}catch(Y){Q.push(Y)}try{await G.controller.dispose?.()}catch(Y){Q.push(Y)}if(Q.length===1)throw Q[0];if(Q.length>1)throw AggregateError(Q,"Section controller persistence and disposal both failed.");await this.hooks.onSectionControllerDispose?.(G.context,G.controller),await this.emitTelemetry("pie-toolkit-section-controller-disposed",{assessmentId:G.key.assessmentId,sectionId:G.key.sectionId,attemptId:G.key.attemptId})}async finalizeSectionControllerDispose(G){if(G.clearPersistence)await G.persistenceStrategy?.clearSession?.(G.context)}dispose(){if(this.disposePromise)return this.disposePromise;return this.disposePromise=Promise.resolve().then(()=>this.disposeOwnedResources()),this.disposePromise}async disposeOwnedResources(){let G=[],Q=async(J)=>{try{await J()}catch(X){G.push(X)}};await this.waitForAdmittedInitialization();let Y=new Map;for(let[J,X]of this.sectionControllerInitEntries)Y.set(J,X.key);for(let[J,X]of this.sectionControllerKeys)Y.set(J,X);for(let J of Y.values())this.disposeSectionController({sectionId:J.sectionId,attemptId:J.attemptId});await Promise.allSettled(Array.from(this.sectionControllerDisposePromises.values())),this.sectionControllers.clear(),this.sectionControllerKeys.clear(),this.sectionControllerInitEntries.clear(),this.sectionPersistenceStrategies.clear();for(let J of this.activeSubscriptions.values())await Q(()=>J.unsubscribeCurrent?.()),J.unsubscribeCurrent=null;this.activeSubscriptions.clear(),this.activeCohortMapKey=null,this.latestRequestedActiveCohortMapKey=null,await Q(()=>this.ttsService.stop()),await Q(()=>this.toolProviderRegistry.destroy()),await Q(()=>this.highlightCoordinator.destroy());for(let J of this.toolCoordinator.getRegisteredTools())await Q(()=>this.toolCoordinator.releaseTool(J));if(await Q(()=>this.catalogResolver.destroy()),await Q(()=>this.toolRequests.dispose()),await Q(()=>this.policyEngine.dispose()),this.toolContextResolvers.clear(),this.toolContextResolverChangeListeners.clear(),this.sectionControllerLifecycleListeners.clear(),this.telemetryListeners.clear(),this.frameworkErrorHookUnsubscribe?.(),this.frameworkErrorHookUnsubscribe=null,this.ownsFrameworkErrorBus)this.frameworkErrorBus.dispose();if(G.length===1)throw G[0];if(G.length>1)throw AggregateError(G,"ToolkitCoordinator cleanup failed for multiple owned resources.")}async waitForAdmittedInitialization(){let G=new Set;if(this.coordinatorReadyPromise)G.add(this.coordinatorReadyPromise);if(this.ttsInitPromise)G.add(this.ttsInitPromise);if(this.ttsReconfigurePromise)G.add(this.ttsReconfigurePromise);for(let Q of this.providerInitPromises.values())G.add(Q);await Promise.allSettled(G)}async ensureTTSReady(G){if(this.assertNotDisposed(),await this.waitForPendingTTSReconfigure(),this.assertNotDisposed(),this.ttsInitialized)return;if(this.ttsInitPromise)return this.ttsInitPromise;return this.ttsInitPromise=this._initializeTTS(G).then(()=>this.assertNotDisposed()).finally(()=>{this.ttsInitPromise=void 0}),this.ttsInitPromise}async waitForPendingTTSReconfigure(){let G=this.ttsReconfigurePromise;while(G)await G,G=this.ttsReconfigurePromise}async _initializeTTS(G){if(this.ttsInitialized)return;let Q=this.resolveTTSToolConfig(G),Y=v0(Q),J=w8(Y),X=h0(Y);if(await this.hooks.onBeforeTTSInit?.({phase:"tts-init",details:{backend:J}}),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-tts-init-start",{backend:J}),await this.emitTelemetry("pie-tool-init-start",{toolId:"textToSpeech",operation:"tts-init",backend:J}),this.toolProviderRegistry.has("tts"))try{let q=await(await this.ensureProviderReady("tts")).createInstance();await this.initializeTTSService(q,X),await this.emitTelemetry("pie-toolkit-tts-init-success",{provider:"registry"}),await this.emitTelemetry("pie-tool-init-success",{toolId:"textToSpeech",operation:"tts-init",backend:J,provider:"registry"}),console.log("[ToolkitCoordinator] TTS initialized via ToolProviderRegistry");return}catch(Z){if(Z instanceof d)throw Z;let q=Z instanceof Error?Z:Error(String(Z));await this.emitTelemetry("pie-tool-init-error",{toolId:"textToSpeech",providerId:"tts",operation:"tts-init",backend:J,errorType:"TTSRegistryInitError",message:q.message,recovered:!0}),await this.emitTelemetry("pie-tool-init-fallback",{toolId:"textToSpeech",providerId:"tts",operation:"tts-init",backend:J,fromProvider:"registry",toProvider:"browser",reason:q.message}),console.warn("[ToolkitCoordinator] Failed to initialize TTS via registry, falling back to browser provider:",q)}let j=new T7;try{await this.initializeTTSService(j,X),await this.emitTelemetry("pie-toolkit-tts-init-success",{provider:"browser-fallback"}),await this.emitTelemetry("pie-tool-init-success",{toolId:"textToSpeech",operation:"tts-init",backend:J,provider:"browser-fallback"})}catch(Z){if(Z instanceof d)throw Z;let q=Z instanceof Error?Z:Error(String(Z));throw this.handleError(q,{phase:"tts-init"}),await this.emitTelemetry("pie-toolkit-tts-init-error",{message:q.message}),await this.emitTelemetry("pie-tool-init-error",{toolId:"textToSpeech",operation:"tts-init",backend:J,errorType:"TTSInitError",message:q.message}),q}}resolveTTSToolConfig(G){return G||this.getTTSConfigFromProviders()||{}}async initializeTTSService(G,Q){let Y={...Q.providerOptions||{},__pieTelemetry:async(X,j)=>{await this.emitTelemetry(X,{toolId:"textToSpeech",...j||{}})}},J={...Q,providerOptions:Y};await this.ttsService.initialize(G,J),await this.ensureBrowserVoicesReady(G),this.assertNotDisposed(),this.ttsService.setCatalogResolver(this.catalogResolver),this.ttsInitialized=!0,await this.hooks.onTTSReady?.(),this.assertNotDisposed()}async ensureBrowserVoicesReady(G,Q=1200){if(G.providerId!=="browser")return;if(typeof window>"u")return;if(!("speechSynthesis"in window))return;let Y=window.speechSynthesis;if(Y.getVoices().length>0)return;await new Promise((j)=>{let Z=!1,q=typeof Y.addEventListener==="function"&&typeof Y.removeEventListener==="function",B=!q&&"onvoiceschanged"in Y,K=B?Y.onvoiceschanged:null,W=!1,$=()=>{if(Z)return;if(Z=!0,window.clearTimeout(N),q)Y.removeEventListener("voiceschanged",H);else if(W&&Y.onvoiceschanged===H)Y.onvoiceschanged=K;j()},H=(F)=>{if(!q&&typeof K==="function"&&F)K.call(Y,F);$()},N=window.setTimeout($,Q);if(q)Y.addEventListener("voiceschanged",H,{once:!0});else if(B)Y.onvoiceschanged=H,W=!0});let X=Y.getVoices();await this.emitTelemetry("pie-toolkit-tts-browser-voices-ready",{voiceCount:X.length,timedOut:X.length===0})}getServiceBundle(){return{ttsService:this.ttsService,toolCoordinator:this.toolCoordinator,highlightCoordinator:this.highlightCoordinator,elementToolStateStore:this.elementToolStateStore,catalogResolver:this.catalogResolver,toolProviderRegistry:this.toolProviderRegistry}}async getToolProvider(G){return this.ensureProviderReady(G)}async waitUntilReady(){if(this.assertNotDisposed(),this.isReady())return;if(this.coordinatorReadyPromise)return this.coordinatorReadyPromise;return this.coordinatorReadyPromise=(async()=>{await this.ensureStateLoaded(),this.assertNotDisposed();let G=this.getTTSConfigFromProviders();if(G?.enabled!==!1)await this.ensureTTSReady(G);if(this.assertNotDisposed(),!this.coordinatorReadyNotified)this.coordinatorReadyNotified=!0,await this.hooks.onCoordinatorReady?.(this),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-coordinator-ready",{assessmentId:this.assessmentId})})().finally(()=>{this.coordinatorReadyPromise=void 0}),this.coordinatorReadyPromise}isReady(){return this.getInitStatus().coordinator}getInitStatus(){let G={};for(let Y of this.toolProviderRegistry.getProviderIds())G[Y]=this.toolProviderRegistry.isInitialized(Y);let Q=this.getTTSConfigFromProviders();return{tts:this.ttsInitialized,stateLoaded:this.stateLoaded||!this.hooks.loadToolState,coordinator:(this.stateLoaded||!this.hooks.loadToolState)&&(this.ttsInitialized||Q?.enabled===!1),providers:G}}getTTSConfigFromProviders(){return(this.config.tools?.providers||{}).textToSpeech}assertCanonicalToolId(G){if(typeof G!=="string"||G.trim().length===0)throw Error("Tool id must be a non-empty string.");if(G==="tts")throw Error('Tool id "tts" is no longer supported. Use "textToSpeech".');if(this.toolRegistry.getAllToolIds().length===0)return;if(!this.toolRegistry.get(G))throw Error(`Unknown tool id "${G}".`)}installToolContextResolvers(G){if(!G)return;for(let[Q,Y]of Object.entries(G)){if(Y==null)continue;if(this.assertCanonicalToolId(Q),typeof Y!=="function")throw Error(`Invalid tool context resolver for "${Q}": expected a function.`);this.toolContextResolvers.set(Q,Y)}}setToolContextResolvers(G){this.toolContextResolvers.clear(),this.installToolContextResolvers(G??void 0),this.notifyToolContextResolverChange()}notifyToolContextResolverChange(){for(let G of this.toolContextResolverChangeListeners)try{G()}catch(Q){console.warn("[ToolkitCoordinator] Tool context resolver listener threw:",Q)}}isToolEnabled(G){return this.assertCanonicalToolId(G),this.config.tools?.providers?.[G]?.enabled!==!1}getToolConfig(G){return this.assertCanonicalToolId(G),this.config.tools?.providers?.[G]||null}updateToolConfig(G,Q){this.assertCanonicalToolId(G);let Y=this.getToolConfig(G)||{};if(!this.config.tools)this.config.tools=Z7(void 0,{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolConfig",toolRegistry:this.toolRegistry}).config;if(!this.config.tools.providers)this.config.tools.providers={};let J={...this.config.tools.providers||{},[G]:OQ(G,Y,Q)},X=Z7({...this.config.tools,providers:J},{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolConfig",toolRegistry:this.toolRegistry});this.config.tools=X.config,this.policyEngine.updateInputs({tools:this.config.tools}),this.emitTelemetry("pie-toolkit-tool-config-updated",{toolId:G}),this._applyToolConfigChange(G,Q)}updateToolPlacement(G,Q){this.updateToolsPlacement({[G]:[...Q]})}updateToolsPlacement(G){if(!this.config.tools)this.config.tools=Z7(void 0,{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolsPlacement",toolRegistry:this.toolRegistry}).config;let Q=this.config.tools?.placement??{section:[],item:[],passage:[]},Y={section:[...G.section??Q.section??[]],item:[...G.item??Q.item??[]],passage:[...G.passage??Q.passage??[]]},J=Z7({...this.config.tools,placement:Y},{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolsPlacement",toolRegistry:this.toolRegistry});J.config.placement=Y,this.config.tools=J.config,this.policyEngine.updateInputs({tools:this.config.tools})}decideToolPolicy(G){return this.policyEngine.decide(G)}decideFeaturePolicy(G){let Q=this.policyEngine.decideFeature(G);if(!Q.assessmentBound&&!this.reportedUnboundFeaturePolicy)this.reportedUnboundFeaturePolicy=!0,console.warn(`[ToolkitCoordinator] Feature policy was asked about "${G}" with no assessment bound, so every capability will be declined for want of a profile to read. Call updateAssessment(...) with the assessment (its personalNeedsProfile, settings.districtPolicy and settings.testAdministration are what policy reads) before relying on any accommodation. Reported once per coordinator.`);return Q}onPolicyChange(G){return this.policyEngine.onPolicyChange(G)}onCatalogsChange(G){return this.catalogResolver.onCatalogsChange(G)}updateAssessment(G){this.boundAssessment=G,this.policyEngine.updateInputs({assessment:G,pnpEnforcement:this.resolveEffectivePnpEnforcement()})}updateCurrentItemRef(G){this.boundCurrentItemRef=G,this.policyEngine.updateInputs({currentItemRef:G,pnpEnforcement:this.resolveEffectivePnpEnforcement()})}setPnpEnforcement(G){this.pnpEnforcementOverride=G,this.policyEngine.updateInputs({pnpEnforcement:this.resolveEffectivePnpEnforcement()})}getPolicyInputs(){return this.policyEngine.getInputs()}registerPolicySource(G){return this.policyEngine.registerPolicySource(G)}registerToolContextResolver(G,Q){if(this.assertCanonicalToolId(G),typeof Q!=="function")throw Error(`Invalid tool context resolver for "${G}": expected a function.`);return this.toolContextResolvers.set(G,Q),this.notifyToolContextResolverChange(),()=>{if(this.toolContextResolvers.get(G)!==Q)return;this.toolContextResolvers.delete(G),this.notifyToolContextResolverChange()}}hasToolContextResolver(G){return this.assertCanonicalToolId(G),this.toolContextResolvers.has(G)}resolveToolContext(G){this.assertCanonicalToolId(G.toolId);let Q=this.toolContextResolvers.get(G.toolId);if(!Q)return null;let Y;try{Y=Q(G)}catch(X){return console.error(`[ToolkitCoordinator] Tool context resolver for "${G.toolId}" threw:`,X),{toolId:G.toolId,visible:!1,params:{},reason:"Tool context resolver threw."}}if(!Y)return{toolId:G.toolId,visible:!0,params:{}};let J=Y.params&&typeof Y.params==="object"&&!Array.isArray(Y.params)?Y.params:{};return{toolId:G.toolId,visible:Y.visible!==!1,params:J,reason:typeof Y.reason==="string"?Y.reason:void 0}}onToolContextResolverChange(G){return this.toolContextResolverChangeListeners.add(G),()=>{this.toolContextResolverChangeListeners.delete(G)}}registerToolRequestTarget(G){return this.toolRequests.registerTarget(G)}requestTool(G){return this.assertCanonicalToolId(G.toolId),this.toolRequests.request(G)}canRequestTool(G,Q){try{this.assertCanonicalToolId(G)}catch{return!1}return this.toolRequests.canRequest(G,Q)}onToolRequestTargetsChange(G){return this.toolRequests.onTargetsChange(G)}resolveEffectivePnpEnforcement(){if(this.pnpEnforcementOverride!==null)return this.pnpEnforcementOverride;return l7({assessment:this.boundAssessment,currentItemRef:this.boundCurrentItemRef})}resolveConfiguredPnpEnforcement(){return this.config.tools?.pnpEnforcement??null}_applyToolConfigChange(G,Q){if(this.disposePromise!==null)return;switch(G){case"textToSpeech":{let Y=this._reconfigureTTSProvider();this.ttsReconfigurePromise=Y,Y.finally(()=>{if(this.ttsReconfigurePromise===Y)this.ttsReconfigurePromise=void 0}),Y.then(async()=>{if(this.disposePromise!==null)return;let J=this.getTTSConfigFromProviders();if(!this.lazyInit&&J?.enabled!==!1)await this.ensureTTSReady(J)});break}case"answerEliminator":break}}async _reconfigureTTSProvider(){this.ttsInitialized=!1,this.ttsInitPromise=void 0;try{this.ttsService.stop()}catch{}if(this.toolProviderRegistry.has("tts"))await this.toolProviderRegistry.unregister("tts");if(this.disposePromise!==null)return;let G=this.getProviderDescriptorTools().find((Q)=>Q.toolId==="textToSpeech");if(!G)return;await this.registerProviderFromTool(G)}}var wQ=()=>{};function l0(G){let{ttsService:Q,listenerId:Y,silence:J}=G;if(typeof Q?.onStateChange!=="function")return wQ;let X=(j)=>{if(j!==R.PLAYING&&j!==R.LOADING)return;J()};return Q.onStateChange(Y,X),()=>{try{Q.offStateChange?.(Y,X)}catch{}}}function d0(G){try{if(G?.isPlaying?.())G.pause?.()}catch{}}import{timedMediaProjectionSignature as G9}from"@pie-players/pie-players-shared/timed-media";var i0="pie-register",s0="pie-unregister",n0="pie-item-session-changed";var r0="pie-content-loaded",o0="pie-item-player-error",a0="pie-formative-action",t0="pie-media-time-source";var RQ={bubbles:!0,composed:!0,cancelable:!1};function EQ(G,Q,Y={}){return new CustomEvent(G,{detail:Q,...RQ,...Y})}function C8(G,Q,Y,J={}){return G.dispatchEvent(EQ(Q,Y,J))}function f7(){return{phase:"idle",cohort:null,controllerResolved:!1,readinessSignals:{sectionReady:!1,interactionReady:!1,allLoadingComplete:!1,runtimeError:!1},effectiveRuntime:null,effectiveToolsConfig:null,loadingCompleteEmitted:!1,lastFrameworkError:null,itemCount:0,loadedCount:0}}function y8(G,Q){if(G===Q)return!0;if(!G||!Q)return!1;return G.sectionId===Q.sectionId&&G.attemptId===Q.attemptId}function bQ(G){if(G.runtimeError)return"error";if(G.allLoadingComplete)return"ready";if(G.interactionReady)return"interaction-ready";if(G.sectionReady)return"loading";return"bootstrapping"}function e0(G){let Q=G.signals.sectionReady&&G.signals.allLoadingComplete,Y=G.mode==="strict"?Q:G.signals.interactionReady;return{phase:bQ({...G.signals,allLoadingComplete:Q,interactionReady:Y}),interactionReady:Y,allLoadingComplete:Q,reason:G.reason}}function G3(G){switch(G){case"idle":return null;case"booting-section":return"composed";case"engine-ready":return"engine-ready";case"interactive":return"interactive";case"disposed":return"disposed"}}function w1(G,Q,Y,J="entered"){let X=G3(Q);if(!X)return;G.push({kind:"stage-change",stage:X,status:J,cohort:Y})}function Q3(G){let Q={...f7(),phase:"booting-section",cohort:G.cohort,effectiveRuntime:G.effectiveRuntime,effectiveToolsConfig:G.effectiveToolsConfig,itemCount:G.itemCount},Y=[];return w1(Y,"booting-section",G.cohort),{state:Q,outputs:Y}}function SQ(G,Q){if(G.phase==="idle"||G.phase==="disposed")return{state:G,outputs:[]};let Y=e0({mode:Q.mode,signals:Q.signals}),J=[],X=G.phase,j=G.loadingCompleteEmitted;if(X==="engine-ready"&&Y.interactionReady)X="interactive",w1(J,X,G.cohort);if(Y.allLoadingComplete&&G.cohort&&!j)j=!0,J.push({kind:"loading-complete",cohort:G.cohort,itemCount:Q.itemCount,loadedCount:Q.loadedCount});return{state:{...G,phase:X,readinessSignals:Q.signals,loadedCount:Q.loadedCount,itemCount:Q.itemCount,loadingCompleteEmitted:j},outputs:J}}function d7(G,Q){switch(Q.kind){case"initialize":{if(G.phase==="disposed")return{state:G,outputs:[]};if(G.phase!=="idle"){if(y8(G.cohort,Q.cohort))return d7(G,{kind:"update-runtime",effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig});return d7(G,{kind:"cohort-change",cohort:Q.cohort,effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig,itemCount:Q.itemCount})}return Q3({state:G,cohort:Q.cohort,effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig,itemCount:Q.itemCount})}case"update-runtime":{if(G.phase==="idle"||G.phase==="disposed")return{state:G,outputs:[]};return{state:{...G,effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig},outputs:[]}}case"cohort-change":{if(G.phase==="disposed")return{state:G,outputs:[]};if(y8(G.cohort,Q.cohort))return d7(G,{kind:"update-runtime",effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig});let Y=[];if(G.phase!=="idle")Y.push({kind:"stage-change",stage:"disposed",status:"entered",cohort:G.cohort});let J=Q3({state:G,cohort:Q.cohort,effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig,itemCount:Q.itemCount});return{state:J.state,outputs:[...Y,...J.outputs]}}case"section-controller-resolved":{if(G.phase!=="booting-section")return{state:{...G,controllerResolved:!0},outputs:[]};let Y=[];return w1(Y,"engine-ready",G.cohort),{state:{...G,phase:"engine-ready",controllerResolved:!0},outputs:Y}}case"update-readiness-signals":return SQ(G,{signals:Q.signals,mode:Q.mode,loadedCount:Q.loadedCount,itemCount:Q.itemCount});case"framework-error":return{state:{...G,lastFrameworkError:Q.error,readinessSignals:{...G.readinessSignals,runtimeError:Q.error.recoverable===!0?G.readinessSignals.runtimeError:!0}},outputs:[{kind:"framework-error",error:Q.error}]};case"dispose":{if(G.phase==="disposed")return{state:G,outputs:[]};let Y=[];if(G.phase!=="idle")w1(Y,"disposed",G.cohort);return{state:{...G,phase:"disposed"},outputs:Y}}default:{let Y=Q;return{state:G,outputs:[]}}}}class x8{state=f7();listeners=new Set;getState(){return this.state}dispatch(G){let Q=d7(this.state,G);if(this.state=Q.state,Q.outputs.length>0)this.fanOut(Q.outputs);return Q.outputs}subscribe(G){this.listeners.add(G);let Q=!0;return()=>{if(!Q)return;Q=!1,this.listeners.delete(G)}}disposeListeners(){this.listeners.clear()}fanOut(G){let Q=Array.from(this.listeners),Y=Object.freeze(G.slice());for(let J of Q)try{J(Y)}catch(X){console.warn("[SectionEngineCore] listener failed:",X)}}}function Y3(G){let{coordinator:Q,dispatchCoreInput:Y}=G,J=0,X=null,j=null,Z=!1,q=Q.subscribeFrameworkErrors(($)=>{try{Y({kind:"framework-error",error:$})}catch(H){console.warn("[CoordinatorBridge] framework-error dispatch failed:",H)}});function B(){if(!j)return;try{j()}catch($){console.warn("[CoordinatorBridge] controller unsubscribe failed:",$)}j=null}async function K($){if(Z)return;J+=1;let H=J;X=$.cohort;let N=await Q.getOrCreateSectionController({sectionId:$.cohort.sectionId,attemptId:$.cohort.attemptId||void 0,input:{section:$.section,sectionId:$.cohort.sectionId,assessmentId:$.assessmentId,view:$.view},updateExisting:!0,createDefaultController:$.createDefaultController});if(H!==J||Z)return;B(),$.onControllerResolved?.(N);let F=N.getCompositionModel;if($.onCompositionChanged?.(F?.()),typeof N.subscribe==="function")j=N.subscribe((O)=>{if(H!==J||Z)return;$.onCompositionChanged?.(F?.())});Y({kind:"section-controller-resolved"})}async function W(){if(Z)return;Z=!0,J+=1,B();try{q()}catch(H){console.warn("[CoordinatorBridge] framework-error unsubscribe failed:",H)}let $=X;if(X=null,$)try{await Q.disposeSectionController({sectionId:$.sectionId,attemptId:$.attemptId||void 0})}catch(H){console.warn("[CoordinatorBridge] section-controller dispose failed:",H)}}return{resolveSectionController:K,dispose:W}}function J3(G){let{runtimeId:Q,sourceCe:Y}=G,J=G.host,X=G.now??(()=>new Date().toISOString());function j(W){let $={stage:W.stage,status:W.status,runtimeId:Q,sectionId:W.cohort?.sectionId,attemptId:W.cohort?.attemptId?W.cohort.attemptId:void 0,timestamp:X(),sourceCe:Y};J.dispatchEvent(new CustomEvent("pie-stage-change",{detail:$}))}function Z(W){let $={runtimeId:Q,sectionId:W.cohort.sectionId,attemptId:W.cohort.attemptId?W.cohort.attemptId:void 0,itemCount:W.itemCount,loadedCount:W.loadedCount,timestamp:X(),sourceCe:Y};J.dispatchEvent(new CustomEvent("pie-loading-complete",{detail:$}))}function q(W){J.dispatchEvent(new CustomEvent("framework-error",{detail:W.error}))}function B(W){switch(W.kind){case"stage-change":j(W);return;case"loading-complete":Z(W);return;case"framework-error":q(W);return;default:{let $=W;return}}}function K(W){J=W}return{dispatch:B,setHost:K}}function X3(G){let{bus:Q}=G;function Y(J){switch(J.kind){case"framework-error":Q.reportFrameworkError(J.error);return;case"stage-change":case"loading-complete":return;default:{let X=J;return}}}return{dispatch:Y}}function Z3(G={}){let Q=G.hook;function Y(X){if(!Q)return;try{Q(X)}catch(j){console.warn("[InstrumentationBridge] hook failed:",j)}}function J(X){Q=X}return{dispatch:Y,setHook:J}}function j3(){let G=new Set;function Q(j){if(j.length===0)return;let Z=Array.from(G),q=Object.freeze(j.slice());for(let B of Z)try{B(q)}catch(K){console.warn("[SubscriberFanout] listener failed:",K)}}function Y(j){G.add(j);let Z=!0;return()=>{if(!Z)return;Z=!1,G.delete(j)}}function J(){G.clear()}function X(){return G.size}return{emit:Q,subscribe:Y,dispose:J,getListenerCount:X}}class f8{core;domEventBridge;frameworkErrorBridge;instrumentationBridge;subscriberFanout;coordinatorBridge;unsubscribeCore;disposed=!1;constructor(G){this.core=G.core??new x8,this.domEventBridge=J3({host:G.host,runtimeId:G.runtimeId,sourceCe:G.sourceCe,now:G.now}),this.frameworkErrorBridge=X3({bus:G.frameworkErrorBus}),this.instrumentationBridge=Z3({hook:G.instrumentationHook}),this.subscriberFanout=j3(),this.coordinatorBridge=G.coordinator?Y3({coordinator:G.coordinator,dispatchCoreInput:(Q)=>this.dispatchInput(Q)}):null,this.unsubscribeCore=this.core.subscribe((Q)=>{this.routeOutputs(Q)})}getState(){return this.core.getState()}dispatchInput(G){if(this.disposed)return[];return this.core.dispatch(G)}subscribe(G){return this.subscriberFanout.subscribe(G)}setHost(G){this.domEventBridge.setHost(G)}setInstrumentationHook(G){this.instrumentationBridge.setHook(G)}resolveSectionController(G){if(!this.coordinatorBridge)throw Error("[SectionEngineAdapter] resolveSectionController called without a coordinator.");return this.coordinatorBridge.resolveSectionController(G)}async dispose(){if(this.disposed)return;if(this.disposed=!0,this.core.dispatch({kind:"dispose"}),this.unsubscribeCore(),this.subscriberFanout.dispose(),this.coordinatorBridge)await this.coordinatorBridge.dispose()}routeOutputs(G){for(let Q of G)this.routeOne(Q);this.subscriberFanout.emit(G)}routeOne(G){switch(G.kind){case"stage-change":case"loading-complete":this.domEventBridge.dispatch(G);break;case"framework-error":this.domEventBridge.dispatch(G),this.frameworkErrorBridge.dispatch(G);break;default:{let Q=G;return}}this.instrumentationBridge.dispatch(G)}}var TQ={mode:"gather",role:"student"};function R1(G,Q){return G!==void 0?G:Q}function CQ(G){let Q=G.runtime??{};if(Q.onFrameworkError!==void 0)return Q.onFrameworkError;return G.onFrameworkError}function yQ(G){let Q=G.runtime?.tools||{},Y=Q.placement||{};return{...Q,placement:{...Y}}}function xQ(G){let Q=G.runtime||{},Y=Q.player?{...Q.player}:null;return{...Q,assessmentId:R1(Q.assessmentId,G.assessmentId),playerType:Q.playerType??"iife",player:Y,lazyInit:Q.lazyInit??!0,accessibility:Q.accessibility??null,coordinator:Q.coordinator??null,createSectionController:Q.createSectionController,isolation:Q.isolation??"inherit",env:Q.env??TQ,toolConfigStrictness:R1(Q.toolConfigStrictness,G.toolConfigStrictness)??"error",onFrameworkError:CQ({runtime:G.runtime,onFrameworkError:G.onFrameworkError}),onStageChange:R1(Q.onStageChange,G.onStageChange),onLoadingComplete:R1(Q.onLoadingComplete,G.onLoadingComplete),tools:G.effectiveToolsConfig}}function q3(G,Q){let Y=G.assessmentId??"section-demo-direct",J=yQ({runtime:G.runtime}),X=xQ({assessmentId:Y,runtime:G.runtime,effectiveToolsConfig:J,toolConfigStrictness:G.toolConfigStrictness,onFrameworkError:G.onFrameworkError,onStageChange:G.onStageChange,onLoadingComplete:G.onLoadingComplete}),j=Q.resolvePlayerRuntime({effectiveRuntime:X,playerType:String(X.playerType??"iife"),env:X.env??null});return{effectiveToolsConfig:J,effectiveRuntime:X,playerRuntime:j}}import{createPieLogger as kQ,isGlobalDebugEnabled as IQ}from"@pie-players/pie-players-shared";function fQ(G,Q){if(G===Q)return 0;let Y=G.compareDocumentPosition(Q);if(Y&Node.DOCUMENT_POSITION_PRECEDING)return 1;if(Y&Node.DOCUMENT_POSITION_FOLLOWING)return-1;return 0}class k8{shellsByElement=new Map;register(G){let Q=this.shellsByElement.get(G.element),Y={...G,sortKey:Date.now()};if(Q&&Q.kind===Y.kind&&Q.itemId===Y.itemId&&Q.canonicalItemId===Y.canonicalItemId)return!1;return this.shellsByElement.set(G.element,Y),!0}unregister(G){return this.shellsByElement.delete(G)}getOrderedShells(G){let Q=Array.from(this.shellsByElement.values()).filter((Y)=>!G||Y.kind===G);return Q.sort((Y,J)=>fQ(Y.element,J.element)),Q}getCanonicalIdMap(){let G={};for(let Q of this.getOrderedShells("item")){if(!Q.itemId)continue;G[Q.itemId]=Q.canonicalItemId||Q.itemId}return G}clear(){this.shellsByElement.clear()}}function E1(G="runtime"){return`${G}-${Math.random().toString(16).slice(2)}-${Date.now()}`}var vQ=kQ("section-runtime-engine",()=>IQ());class I8{registry=new k8;runtimeId=E1("section-engine");adapter=null;controller=null;coordinator=null;sectionId="";attemptId;unsubscribeController=null;activeInitToken=0;loadedRenderableKeys=new Set;attachHost(G){if(this.adapter){if(this.adapter.setHost(G.host),G.instrumentationHook!==void 0)this.adapter.setInstrumentationHook(G.instrumentationHook);return}this.adapter=new f8({host:G.host,runtimeId:this.runtimeId,sourceCe:G.sourceCe,frameworkErrorBus:G.frameworkErrorBus,coordinator:G.coordinator,instrumentationHook:G.instrumentationHook,now:G.now})}dispatchInput(G){return this.adapter?.dispatchInput(G)??[]}subscribe(G){return this.adapter?.subscribe(G)??hQ}getState(){return this.adapter?.getState()??f7()}getEffectiveRuntime(G,Q){return q3(G,Q).effectiveRuntime}setInstrumentationHook(G){this.adapter?.setInstrumentationHook(G)}getRuntimeId(){return this.runtimeId}async initialize(G){this.activeInitToken+=1;let Q=this.activeInitToken;this.coordinator=G.coordinator,this.sectionId=G.sectionId,this.attemptId=G.attemptId;let Y=await G.coordinator.getOrCreateSectionController({sectionId:G.sectionId,attemptId:G.attemptId,input:{section:G.section,sectionId:G.sectionId,assessmentId:G.assessmentId,view:G.view},updateExisting:!0,createDefaultController:G.createDefaultController});if(Q!==this.activeInitToken)return;this.unsubscribeController?.(),this.controller=Y,this.replayRegisteredShellsIntoController(Y),G.onCompositionChanged?.(Y.getCompositionModel?.()),this.unsubscribeController=Y.subscribe?.((J)=>{try{G.onControllerEvent?.(J)}catch(X){vQ.warn("onControllerEvent handler threw",X)}G.onCompositionChanged?.(Y.getCompositionModel?.())})||null}replayRegisteredShellsIntoController(G){if(!G.handleContentRegistered)return;let Q=this.registry.getOrderedShells();if(Q.length===0)return;for(let J of Q){let X=J.canonicalItemId||J.itemId;G.handleContentRegistered({itemId:J.itemId,canonicalItemId:X,contentKind:J.contentKind||J.kind})}let Y=Date.now();for(let J of Q){let X=J.canonicalItemId||J.itemId,j=this.getLoadedKey(X,J.contentKind);if(this.loadedRenderableKeys.has(j))G.handleContentLoaded?.({itemId:J.itemId,canonicalItemId:X,contentKind:J.contentKind||J.kind,timestamp:Y})}}getLoadedKey(G,Q){return`${Q??""}:${G}`}register(G){return this.registry.register(G)}unregister(G){return this.registry.unregister(G)}getCompositionModel(){return this.controller?.getCompositionModel?.()??null}getCanonicalItemId(G){return this.registry.getCanonicalIdMap()[G]||this.controller?.getCanonicalItemId?.(G)||G}handleContentRegistered(G){this.controller?.handleContentRegistered?.({itemId:G.itemId,canonicalItemId:G.canonicalItemId||G.itemId,contentKind:G.contentKind||G.kind})}handleContentUnregistered(G){let Q=G.canonicalItemId||G.itemId;this.loadedRenderableKeys.delete(this.getLoadedKey(Q,G.contentKind)),this.controller?.handleContentUnregistered?.({itemId:G.itemId,canonicalItemId:Q,contentKind:G.contentKind||G.kind})}handleContentLoaded(G){let Q=G.canonicalItemId||G.itemId;this.loadedRenderableKeys.add(this.getLoadedKey(Q,G.contentKind)),this.controller?.handleContentLoaded?.(G)}handleItemPlayerError(G){this.controller?.handleItemPlayerError?.(G)}reportSectionError(G){this.controller?.reportSectionError?.(G)}updateItemSession(G,Q){let Y=this.getCanonicalItemId(G);return this.controller?.updateItemSession?.(Y,Q)??null}navigateToItem(G){return this.controller?.navigateToItem?.(G)??null}handleFormativeAction(G){if(!G?.itemId)return;let Q=this.getCanonicalItemId(G.itemId);if(G.action==="retry"){this.controller?.retryFormativeItem?.({itemId:Q});return}this.controller?.recordFormativeTry?.({itemId:Q,outcomes:G.outcomes})}handleMediaTimeSource(G){if(G?.action==="detach"){this.controller?.detachMediaTimeSource?.({origin:G.origin??"host"});return}if(!G?.source)return;this.controller?.attachMediaTimeSource?.(G.source,{origin:G.origin??"host",renderableId:G.renderableId})}requestMediaPauseForCompetingAudio(){return this.controller?.pauseMediaForCompetingAudio?.()??!0}async persist(){await this.controller?.persist?.()}async hydrate(){await this.controller?.hydrate?.()}getRegistry(){return this.registry}async dispose(){if(this.activeInitToken+=1,this.unsubscribeController?.(),this.unsubscribeController=null,this.coordinator&&this.sectionId)await this.coordinator.disposeSectionController({sectionId:this.sectionId,attemptId:this.attemptId});if(this.registry.clear(),this.loadedRenderableKeys.clear(),this.controller=null,this.coordinator=null,this.adapter){let G=this.adapter;this.adapter=null,await G.dispose()}}}var hQ=()=>{};import{ContextConsumer as mQ,createContext as uQ}from"@pie-players/pie-context";var U3=uQ(Symbol.for("pie.sectionRuntimeEngineHostContext"));function B3(G,Q){let Y=!1,J=new mQ(G,{context:U3,subscribe:!0,onValue:(B)=>{Y=!0,Q(B)}});J.connect();let X=(B)=>{if(B.context!==U3)return;J.requestValue()};G.addEventListener("context-provider",X);let j=0,Z=200,q=globalThis.setInterval(()=>{if(Y||j>=Z){globalThis.clearInterval(q);return}j+=1,J.requestValue()},50);return()=>{globalThis.clearInterval(q),G.removeEventListener("context-provider",X),J.disconnect()}}var pQ=(G)=>{console.error("[pie-assessment-toolkit] onStageChange handler threw",G)};function W3(G,Q){if(G.isSuppressed())return!1;G.dispatchDomEvent(Q);let Y=G.getOnStageChange();if(Y)try{Y(Q)}catch(J){(G.logHandlerError??pQ)(J)}return!0}function i7(G,Q){if(typeof G==="function")return G;if(G===null)return null;return typeof Q==="function"?Q:null}function K3(G={}){let Q=G.frameDeadlineMs??100,Y=!1,J=null,X=null,j=null,Z=null,q=null;function B(){if(Y=!1,X!==null)Z?.(X),X=null;if(j!==null)q?.(j),j=null;Z=null,q=null}function K(H){if(!Y)return;if(H==="frame")X=null;if(H==="timer")j=null;let N=J;J=null,B(),N?.()}function W(H){if(J=H,Y)return;Y=!0;let N=globalThis,F=i7(G.requestFrame,N.requestAnimationFrame);Z=i7(G.cancelFrame,N.cancelAnimationFrame);let O=i7(G.setTimer,N.setTimeout);if(q=i7(G.clearTimer,N.clearTimeout),F){let D=F(()=>K("frame"));if(!Y)return;if(X=D,O){let P=O(()=>K("timer"),Q);if(Y)j=P}return}let L=i7(G.queueMicrotaskFn,N.queueMicrotask);if(L){L(()=>K("microtask"));return}if(O){let D=O(()=>K("timer"),0);if(Y)j=D;return}K("microtask")}function $(){if(!Y)return;J=null,B()}return{schedule:W,cancel:$,isPending:()=>Y}}function _3(){return{lastSessionEventSignatureByItemId:new Map,lastMetadataSignatureByItemId:new Map}}function V3(G){G.lastSessionEventSignatureByItemId.clear(),G.lastMetadataSignatureByItemId.clear()}function $3(G){let{state:Q,itemId:Y,payload:J}=G;if(cQ(J)){let Z=lQ(J);if(Q.lastMetadataSignatureByItemId.get(Y)===Z)return!1;Q.lastMetadataSignatureByItemId.set(Y,Z)}let X=gQ(J);if(Q.lastSessionEventSignatureByItemId.get(Y)===X)return!1;return Q.lastSessionEventSignatureByItemId.set(Y,X),!0}function gQ(G){let Q={...G};delete Q.timestamp,delete Q.sourceRuntimeId;try{return JSON.stringify(Q)}catch{return String(Q.itemId||"")}}function cQ(G){return G.intent==="metadata-only"}function lQ(G){try{return JSON.stringify({itemId:G.itemId,canonicalItemId:G.canonicalItemId,intent:G.intent,complete:G.complete??null,component:G.component??null})}catch{return String(G.itemId||"")}}var dQ=(G,Q)=>{if(customElements.get(G))return;try{customElements.define(G,Q)}catch(Y){if(!(Y instanceof DOMException&&Y.name==="NotSupportedError"||Y&&typeof Y==="object"&&Y.name==="NotSupportedError")||!customElements.get(G))throw Y}},Q9=u8('<div class="pie-assessment-toolkit-error svelte-vpe4u2" role="alert" aria-live="assertive"><div class="pie-assessment-toolkit-error-title svelte-vpe4u2"> </div> <div class="pie-assessment-toolkit-error-message svelte-vpe4u2"> </div> <pre class="pie-assessment-toolkit-error-details svelte-vpe4u2"> </pre></div>'),Y9=u8('<div class="pie-assessment-toolkit-anchor svelte-vpe4u2" aria-hidden="true"></div> <!>',1),J9={hash:"svelte-vpe4u2",code:`.pie-assessment-toolkit-anchor.svelte-vpe4u2 {display:none;}.pie-assessment-toolkit-error.svelte-vpe4u2 {margin:0.75rem;padding:0.75rem 1rem;border-radius:0.5rem;border:1px solid
|
|
224
|
-
color-mix(in srgb, var(--pie-incorrect-icon, #dc2626) 40%, transparent);background:color-mix(in srgb, var(--pie-incorrect-icon, #dc2626) 12%, transparent);color:var(--pie-incorrect, #7f1d1d);font-size:0.9rem;}.pie-assessment-toolkit-error-title.svelte-vpe4u2 {font-weight:600;margin-bottom:0.25rem;}.pie-assessment-toolkit-error-message.svelte-vpe4u2 {margin-bottom:0.5rem;}.pie-assessment-toolkit-error-details.svelte-vpe4u2 {margin:0;white-space:pre-wrap;word-break:break-word;}`};function C3(G,Q){N3(Q,!0),w3(G,J9);let Y=E1("toolkit"),J=new I8,X=h(null),j=new p7,Z={mode:"gather",role:"student"},q={iife:"pie-item-player",esm:"pie-item-player",preloaded:"pie-item-player",custom:""},B=x(Q,"assessmentId",7,""),K=x(Q,"section",7,null),W=x(Q,"sectionId",7,""),$=x(Q,"attemptId",7,""),H=x(Q,"env",23,()=>({})),N=x(Q,"ndsIcons",7,!1),F=x(Q,"locale",7,""),O=x(Q,"lazyInit",7,!0),L=x(Q,"toolConfigStrictness",7,"error"),D=x(Q,"tools",23,()=>({})),P=x(Q,"toolContextResolvers",7,null),S=x(Q,"enabledTools",7,""),v=x(Q,"toolRegistry",7,null),I=x(Q,"accessibility",23,()=>({})),p=x(Q,"player",7,null),E=x(Q,"playerType",7,""),g=x(Q,"coordinator",7,null),q7=x(Q,"createSectionController",7,null),U7=x(Q,"onFrameworkError",7,null),B7=x(Q,"errorRenderer",7,null),w7=x(Q,"onStageChange",7,null),s7=x(Q,"assessment",7,null),n7=x(Q,"currentItemRef",7,null),r7=x(Q,"pnpEnforcement",7,null),W7=x(Q,"isolation",7,"inherit"),k7=h(null),i=h(null),J7=h(null),p8=null,I7=null,v7=null,o7=null,h7=null,a7=null,t7=h(0),y1=h(null),m7=h(null),o=h(null),x1=h("Unable to initialize assessment toolkit."),f1=h(v8([])),g8="",k1="",c8=h(""),l8=null,d8=K3(),K7=[],e7=new Map,I1=new WeakMap,i8=_3(),s=nQ({sourceCe:"pie-assessment-toolkit",sourceCeShape:"toolkit",runtimeId:Y,sectionId:m(()=>W()||void 0),attemptId:m(()=>$()||void 0),emit:(U)=>{W3({isSuppressed:()=>V(X)!==null,dispatchDomEvent:(_)=>_7("pie-stage-change",_),getOnStageChange:()=>w7()},U)}}),s8=h(v8(m(()=>`${W()}|${$()}`))),G1=h(!1),t=h(!1),v1=h(!1),h1=h(!1);function y3(){if(!V(k7))return null;let U=V(k7).getRootNode();if(U&&"host"in U)return U.host;return V(k7).parentElement}let f=r(()=>y3());function _7(U,_){if(!V(f)){K7=[...K7,{name:U,detail:_}];return}C8(V(f),U,_)}b(()=>{if(!V(f))return;if(K7.length===0)return;let U=K7;K7=[],queueMicrotask(()=>{let _=V(f);if(!_){K7=[...U,...K7];return}for(let M of U)C8(_,M.name,M.detail)})});function x3(U){if(!B7())return{title:"Unable to initialize assessment toolkit.",details:U.details.length>0?U.details:[U.message]};try{let _=B7()(U)||{};return{title:typeof _.title==="string"&&_.title.trim().length>0?_.title:"Unable to initialize assessment toolkit.",details:Array.isArray(_.details)&&_.details.length>0?_.details.map((M)=>String(M)):U.details.length>0?U.details:[U.message]}}catch(_){let M=_ instanceof Error&&_.message.trim().length>0?_.message:String(_||"Unknown renderer error");return{title:"Unable to initialize assessment toolkit.",details:[...U.details,`Error renderer failed: ${M}`]}}}function R7(U){let _=j1({kind:U.kind,source:U.source,error:U.error,recoverable:U.recoverable});return j.reportFrameworkError(_),_}function f3(U){if(U?.type==="timed-media-policy-degraded"){let M=U.degradations||[];j.reportFrameworkError(Z1({kind:"timed-media",severity:"warning",source:"pie-assessment-toolkit",message:"A timed-media playback policy degraded to advisory: the media time source does not report the capability it needs.",details:M.map((z)=>z?.message).filter((z)=>typeof z==="string"),recoverable:!0}));return}if(U?.type!=="timed-media-invalid")return;let _=U.errors||[];j.reportFrameworkError(Z1({kind:"timed-media",severity:"error",source:"pie-assessment-toolkit",message:'This section declares sectionType: "timed-media" but its timedMedia data is not deliverable; the section renders without cue behavior.',details:_.map((M)=>M?.message).filter((M)=>typeof M==="string"),recoverable:!1}))}function k3(U){if(U?.type!=="timed-media-audio-started")return;if(!V(C))return;d0(V(C).getServiceBundle().ttsService)}function I3(U){return U==="coordinator-init"||U==="runtime-init"||U==="tool-config"}function n8(U){if(!U7())return;try{U7()(U),g8=`${U.kind}|${U.source}|${U.message}`}catch(_){console.error(`[pie-framework:${U.kind}:${U.source}] framework error hook failed`,_)}}b(()=>{let U=j.subscribeFrameworkErrors((_)=>{if(console.error(Z6(_),_.cause),I3(_.kind)){let M=x3(_);w(o,_,!0),w(x1,M.title,!0),w(f1,M.details,!0)}_7("framework-error",_),n8(_)});return()=>{U()}}),b(()=>{if(!V(o))return;let U=`${V(o).kind}|${V(o).source}|${V(o).message}`;if(g8===U)return;n8(V(o))});function v3(U){let _=5381;for(let M=0;M<U.length;M+=1)_=(_<<5)+_^U.charCodeAt(M);return(_>>>0).toString(36)}function n(U){return U&&typeof U==="object"?U:{}}function h3(U){let _=n(U.section),M=typeof _.identifier==="string"?_.identifier:"",z=typeof U.sectionId==="string"?U.sectionId:"";return M||z}function m3(U){return typeof U.currentItemIndex==="number"?U.currentItemIndex:-1}function u3(U){return(Array.isArray(U.renderables)?U.renderables:[]).map((M,z)=>{let A=n(M),k=n(A.entity),G7=typeof k.id==="string"&&k.id||`renderable-${z}`,X1=n(k.config),d1=typeof k.version==="string"&&k.version||(typeof k.version==="number"?String(k.version):"")||(typeof X1.version==="string"?X1.version:"");return{id:G7,version:d1}})}function p3(U){let _=n(U.itemSessionsByItemId);return Object.keys(_).sort((M,z)=>M.localeCompare(z)).map((M)=>{let z=n(_[M]),A=typeof z.id==="string"?z.id:"",k=Array.isArray(z.data)?z.data:[],G7="";try{G7=v3(JSON.stringify(k))}catch{G7=String(k.length)}return{itemId:M,sessionId:A,payloadSignature:G7}})}function g3(U){let _=n(n(U.formative).states);return Object.entries(_).map(([M,z])=>{let A=n(z),k=n(A.lastOutcome).correctness??"";return`${M}:${A.tryCount??0}:${A.revealed===!0?1:0}:${String(k)}:${String(A.revealOverride??"")}`}).sort().join("|")}function c3(U){let _=U.timedMedia;return G9(_)}function l3(U){let _=n(U),M=u3(_).map((A)=>`${A.id}:${A.version}`).join("|"),z=p3(_).map((A)=>`${A.itemId}:${A.sessionId}:${A.payloadSignature}`).join("|");return{sectionId:h3(_),currentItemIndex:m3(_),renderableSignature:M,itemSessionSignature:z,formativeSignature:g3(_),timedMediaSignature:c3(_)}}function d3(U){let _=l3(U);return`${_.sectionId}|${_.currentItemIndex}|${_.renderableSignature}|${_.itemSessionSignature}|${_.formativeSignature}|${_.timedMediaSignature}`}function r8(U){return U==="iife"||U==="esm"||U==="preloaded"||U==="custom"}function i3(U,_){let M=U?.type,z=r8(M)?M:r8(_)?_:U?.tagName?"custom":"iife",A=U?.tagName?.trim();if(z==="custom"&&!A)return{type:"iife",tagName:q.iife,version:void 0,source:void 0,isDefault:!0};return{type:z,tagName:A||q[z],version:U?.version,source:U?.source,loaderConfig:U?.loaderConfig,loaderOptions:U?.loaderOptions,isDefault:!U&&!_}}function o8(U){let _=U||{},M=typeof _.mode==="string"&&_.mode.trim()?_.mode.trim():Z.mode,z=typeof _.role==="string"&&_.role.trim()?_.role.trim():Z.role;return{mode:M,role:z}}function s3(U){let _=o8(U);if(_.mode==="author")return"author";if(_.role==="instructor")return"scorer";return"candidate"}async function n3(){if(q7())return q7()();throw Error("pie-assessment-toolkit requires createSectionController when no coordinator hook provides one")}function a8(){let U=D()||{},_=T3(S());if(_.length===0)return U;let M=U.placement||{},z=Array.isArray(M.section)?M.section:null;if(z&&z.length>0)return U;return{...U,placement:{...M,section:_}}}function r3(){return Z7(a8(),{strictness:L(),source:"pie-assessment-toolkit.bootstrap",toolRegistry:v()}).config}function o3(){let U="",_="";try{U=JSON.stringify(a8())}catch{U="[unserializable-tools]"}try{_=JSON.stringify(Object.entries(P()??{}).map(([M,z])=>[M,typeof z]))}catch{_="[unserializable-resolvers]"}return[B()||"",String(L()||"error"),U,_].join("|")}function t8(U){return U==="on"||U==="off"?U:null}function a3(U,_){let M=t8(U);if(M)return M;if(_&&typeof _==="object"){let A=_.pnpEnforcement;return t8(typeof A==="string"?A:null)}return null}function t3(U){let _=B()||K()?.identifier||`assessment-${Math.random().toString(16).slice(2)}`;return new L1({assessmentId:_,lazyInit:O(),toolConfigStrictness:L(),deferToolConfigValidation:!0,tools:U,toolRegistry:v(),toolContextResolvers:P(),accessibility:I(),frameworkErrorBus:j})}function m1(){let U=V(i);if(!U)return Promise.resolve();return w(i,null),U.dispose()}function u1(U){w(m7,U,!0),R7({kind:"runtime-dispose",source:"pie-assessment-toolkit",error:U,recoverable:!0,details:{owner:"toolkit-coordinator"}})}let C=r(()=>{if(W7()!=="force"&&V(J7)?.coordinator)return V(J7).coordinator;return g()||V(i)});b(()=>{V(f),g(),W7(),V(J7),P(),m(()=>{if(!V(f))return;if(g()){if(V(i))m1().catch(u1);I7=null;return}if(W7()!=="force"&&V(J7)?.coordinator){if(V(i))m1().catch(u1);I7=null;return}if(V(i)&&I7!==P()){try{V(i).setToolContextResolvers(P()),I7=P()}catch(U){w(m7,U,!0),R7({kind:"coordinator-init",phase:"coordinator-ready",error:U})}return}if(!V(i)){let U=o3();if(k1===U)return;try{let _=r3();w(i,t3(_),!0),I7=P(),k1="",w(o,null),w(x1,"Unable to initialize assessment toolkit."),w(f1,[],!0)}catch(_){w(m7,_,!0),w(i,null),k1=U,R7({kind:"coordinator-init",source:"pie-assessment-toolkit",error:_})}}})});let Q1=tQ(),p1=h(0);b(()=>Q1.subscribe(()=>{w(p1,V(p1)+1)})),b(()=>{let U=typeof F()==="string"?F().trim():"";m(()=>{Promise.resolve(Q1.setLocale(U||eQ)).catch((_)=>{R7({kind:"i18n-locale-load",source:"pie-assessment-toolkit",error:_ instanceof Error?_:Error(String(_))})})})});let X7=r(()=>B()||V(C)?.assessmentId||""),e=r(()=>W()||K()?.identifier||`section-${V(X7)||"default"}`),g1=r(()=>o8(H())),e3=r(()=>s3(V(g1))),E7=r(()=>i3(p(),E())),u7=r(()=>rQ({player:V(E7),component:"pie-assessment-toolkit"})),Y1=r(()=>{if(!V(C))return null;let U=V(C).getServiceBundle();return{toolkitCoordinator:V(C),toolCoordinator:V(C).toolCoordinator,ttsService:U.ttsService,highlightCoordinator:U.highlightCoordinator,catalogResolver:U.catalogResolver,elementToolStateStore:U.elementToolStateStore,assessmentId:V(X7),sectionId:V(e),itemPlayer:V(E7),ndsIcons:N()===!0,locale:(V(p1),Q1.getLocale()),i18n:Q1,reportSessionChanged:(_,M)=>{let z=J.updateItemSession(_,M);Q6({itemId:_,result:z,fallbackSession:M})}}}),J1=r(()=>{if(!V(C))return null;return{runtimeId:Y,coordinator:V(C)}});function G5(U){let _=d3(U);if(_===V(c8))return;w(c8,_,!0),w(t7,V(t7)+1),w(y1,U,!0),_7("composition-changed",{composition:V(y1),version:V(t7)})}function c1(U){l8=U??J.getCompositionModel(),d8.schedule(()=>{G5(l8)})}function l1(U){if(!U)return;let _=I1.get(U);if(!_)return;for(let M of _)M();I1.delete(U)}function e8(){for(let U of e7.values())l1(U.element)}function G6(U){if(l1(U.element),!V(C))return;let _=V(C).getServiceBundle().catalogResolver;I1.set(U.element,[_.registerOwner({owner:{kind:U.kind,itemId:U.itemId,canonicalItemId:U.canonicalItemId,assessmentId:V(X7),sectionId:V(e)},entity:U.item})])}function Q5(){e8();for(let U of e7.values())G6(U)}function Q6(U){let M={...U.result?.eventDetail||U.fallbackSession,itemId:U.itemId,canonicalItemId:U.canonicalItemId||U.itemId,sourceRuntimeId:Y};if(!$3({state:i8,itemId:U.itemId,payload:M}))return;_7("session-changed",M)}function Y5(U){if(!(U instanceof HTMLElement))return!1;return iQ(U,m8)?.runtimeId===Y}function V7(U){return U.detail??null}function J5(U,_){for(let M of _)U.addEventListener(M.name,M.handler);return()=>{for(let M of _)U.removeEventListener(M.name,M.handler)}}b(()=>{if(!V(f))return;if(W7()==="force"){w(J7,null);return}return S3(V(f),(U)=>{if(U.runtimeId===Y)return;w(J7,U,!0)})}),b(()=>{let U=V(f);return m(()=>{if(!U){w(X,null);return}let _=B3(U,(M)=>{if(M.engine===V(X))return;w(X,M.engine,!0)});return()=>{_(),w(X,null)}})}),b(()=>{let U=V(C);if(!U)return;return m(()=>l0({ttsService:U.getServiceBundle().ttsService,listenerId:`timed-media-audio-handoff:${Y}`,silence:()=>J.requestMediaPauseForCompetingAudio()}))}),b(()=>{let U=W7()!=="force"&&V(J7)?V(J7).runtimeId:null,_=U?"inherited":"owned";if(_!==p8)p8=_,_7(_==="inherited"?"runtime-inherited":"runtime-owned",{runtimeId:Y,parentRuntimeId:U})}),b(()=>{let U=V(e),_=$()||"";V3(i8)}),b(()=>{if(!V(f)||!V(J1))return;return h7=new H3(V(f),{context:m8,initialValue:V(J1)}),h7.connect(),a7=new D3(V(f)),a7.attach(),()=>{a7?.detach(),a7=null,h7?.disconnect(),h7=null}}),b(()=>{if(!V(J1))return;h7?.setValue(V(J1))}),b(()=>{if(!V(f))return;V(f).setAttribute("data-item-player-type",V(E7).type),V(f).setAttribute("data-item-player-tag",V(E7).tagName),V(f).setAttribute("data-env-mode",String(V(g1)?.mode||"")),V(f).setAttribute("data-env-role",String(V(g1)?.role||""))}),b(()=>{if(!V(f)||!V(Y1))return;return v7=new H3(V(f),{context:b3,initialValue:V(Y1)}),v7.connect(),o7=new D3(V(f)),o7.attach(),()=>{o7?.detach(),o7=null,v7?.disconnect(),v7=null}}),b(()=>{if(V(Y1))v7?.setValue(V(Y1))}),b(()=>{return V(C),V(X7),V(e),Q5(),()=>{e8()}}),b(()=>{if(!V(f))return;return sQ({host:V(f),instrumentationProvider:V(u7),component:"pie-assessment-toolkit",eventMap:oQ,staticAttributes:{instrumentationLayer:"toolkit",assessmentId:V(X7),sectionId:V(e),attemptId:$()||void 0}})}),b(()=>{s7(),n7(),r7(),D();let U=V(C);if(!U)return;if(U!==V(i))return;m(()=>{U.setPnpEnforcement(a3(r7(),D())),U.updateAssessment(s7()),U.updateCurrentItemRef(n7())})}),b(()=>{if(!V(C))return;return V(C).subscribeTelemetry(({eventName:U,payload:_})=>{if(!aQ(V(u7)))return;if(!V(u7).isReady())return;let M=U,z=new Date().toISOString(),A={..._||{},instrumentationLayer:"toolkit",assessmentId:V(X7),sectionId:V(e),attemptId:$()||void 0,component:"pie-assessment-toolkit",sourceEventName:U,timestamp:z};V(u7).trackEvent(M,A);let k=_&&typeof _.errorType==="string"?_.errorType:void 0;if(!U.endsWith("-error")&&!k)return;let G7=_&&typeof _.message==="string"?_.message:`Toolkit telemetry error: ${U}`;V(u7).trackError(Error(G7),{component:"pie-assessment-toolkit",errorType:k||"ToolkitTelemetryError",...A})})}),b(()=>{if(!K()||!V(C))return;let U=!1;return J.initialize({coordinator:V(C),section:K(),sectionId:V(e),assessmentId:V(X7),attemptId:$()||void 0,view:V(e3),createDefaultController:n3,onCompositionChanged:(_)=>{if(U)return;c1(_)},onControllerEvent:(_)=>{if(U)return;k3(_),f3(_)}}).then(()=>{if(U)return;_7("toolkit-ready",{runtimeId:Y,assessmentId:V(X7),sectionId:V(e),itemPlayer:V(E7),coordinator:V(C)}),_7("section-ready",{sectionId:V(e)}),m(()=>{w(h1,!0)})}).catch((_)=>{if(U)return;m(()=>{if(!V(t))w(t,!0),s.enter("engine-ready","skipped");s.enter("interactive","failed")}),w(m7,_,!0),J.reportSectionError({source:"section-runtime",error:_,timestamp:Date.now()}),R7({kind:"runtime-init",source:"pie-assessment-toolkit",error:_})}),()=>{U=!0}}),b(()=>{if(!V(f))return;let U=V(f),_=(z)=>Y5(z.target);return J5(U,[{name:i0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.element||!A?.itemId)return;let k=J.register(A);if(e7.set(A.element,A),G6(A),J.handleContentRegistered(A),k)c1()}},{name:s0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.itemId)return;let k=A?.element?J.unregister(A.element):!1;if(l1(A.element),A.element)e7.delete(A.element);if(J.handleContentUnregistered(A),k)c1()}},{name:n0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.itemId)return;let k=J.updateItemSession(A.itemId,A.session);Q6({itemId:A.itemId,canonicalItemId:J.getCanonicalItemId(A.itemId),result:k,fallbackSession:A.session})}},{name:r0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.itemId)return;J.handleContentLoaded({itemId:A.itemId,canonicalItemId:A.canonicalItemId,contentKind:A.contentKind,detail:A.detail,timestamp:Date.now()})}},{name:o0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.itemId)return;J.handleItemPlayerError({itemId:A.itemId,canonicalItemId:A.canonicalItemId,contentKind:A.contentKind,error:A.error,timestamp:Date.now()})}},{name:a0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.itemId)return;if(A.action!=="check"&&A.action!=="retry")return;J.handleFormativeAction({itemId:A.canonicalItemId||A.itemId,action:A.action,outcomes:A.outcomes})}},{name:t0,handler:(z)=>{if(!_(z))return;let A=V7(z);if(!A?.renderableId)return;if(A.action!=="attach"&&A.action!=="detach")return;J.handleMediaTimeSource({renderableId:A.renderableId,action:A.action,source:A.source,origin:A.origin})}}])});async function X5(){if(!V(C))throw Error("Coordinator not initialized");await V(C).waitUntilReady()}function Z5(){if(!V(C))throw Error("Coordinator not initialized");return V(C).getServiceBundle()}function j5(U){if(!V(C))throw Error("Coordinator not initialized");V(C).setHooks(U)}function q5(U){return J.navigateToItem(U)}function U5(){return J.getCompositionModel()}function B5(){return V(E7)}async function W5(){await J.persist()}async function K5(){await J.hydrate()}b(()=>{return()=>{m(()=>{if(s.getCurrent()!==null)s.enter("disposed")})}}),b(()=>{let U=`${W()}|${$()}`;m(()=>{if(U===V(s8))return;if(s.getCurrent()!==null)s.enter("disposed");s.reset({sectionId:W()||void 0,attemptId:$()||void 0}),w(s8,U),w(G1,!1),w(t,!1),w(v1,!1),w(h1,!1)})}),b(()=>{let U=V(t)&&V(h1);m(()=>{if(!U)return;if(V(v1))return;w(v1,!0),s.enter("interactive")})}),b(()=>{let U=V(t7)>0||V(y1)!==null;m(()=>{if(!V(G1)&&U)w(G1,!0),s.enter("composed")})}),b(()=>{if(!V(C))return;if(!V(G1))return;if(V(t))return;let U=V(C),_=!1;return U.waitUntilReady().then(()=>{if(_)return;m(()=>{if(V(t))return;w(t,!0),s.enter("engine-ready")})}).catch(()=>{if(_)return;m(()=>{if(V(t))return;w(t,!0),s.enter("engine-ready","failed")})}),()=>{_=!0}}),b(()=>{return()=>{d8.cancel(),J.dispose().catch((U)=>{w(m7,U,!0),R7({kind:"runtime-dispose",source:"pie-assessment-toolkit",error:U,recoverable:!0})}).then(()=>m1()).catch(u1).finally(()=>{j.dispose()})}});var _5={waitUntilReady:X5,getServiceBundle:Z5,setHooks:j5,navigateToItem:q5,getCompositionModel:U5,getItemPlayerConfig:B5,persist:W5,hydrate:K5,get assessmentId(){return B()},set assessmentId(U){B(U),y()},get section(){return K()},set section(U){K(U),y()},get sectionId(){return W()},set sectionId(U){W(U),y()},get attemptId(){return $()},set attemptId(U){$(U),y()},get env(){return H()},set env(U){H(U),y()},get ndsIcons(){return N()},set ndsIcons(U){N(U),y()},get locale(){return F()},set locale(U){F(U),y()},get lazyInit(){return O()},set lazyInit(U){O(U),y()},get toolConfigStrictness(){return L()},set toolConfigStrictness(U){L(U),y()},get tools(){return D()},set tools(U){D(U),y()},get toolContextResolvers(){return P()},set toolContextResolvers(U){P(U),y()},get enabledTools(){return S()},set enabledTools(U){S(U),y()},get toolRegistry(){return v()},set toolRegistry(U){v(U),y()},get accessibility(){return I()},set accessibility(U){I(U),y()},get player(){return p()},set player(U){p(U),y()},get playerType(){return E()},set playerType(U){E(U),y()},get coordinator(){return g()},set coordinator(U){g(U),y()},get createSectionController(){return q7()},set createSectionController(U){q7(U),y()},get onFrameworkError(){return U7()},set onFrameworkError(U){U7(U),y()},get errorRenderer(){return B7()},set errorRenderer(U){B7(U),y()},get onStageChange(){return w7()},set onStageChange(U){w7(U),y()},get assessment(){return s7()},set assessment(U){s7(U),y()},get currentItemRef(){return n7()},set currentItemRef(U){n7(U),y()},get pnpEnforcement(){return r7()},set pnpEnforcement(U){r7(U),y()},get isolation(){return W7()},set isolation(U){W7(U),y()}},Y6=Y9(),J6=h8(Y6);R3(J6,(U)=>w(k7,U),()=>V(k7));var V5=S1(J6,2);{var $5=(U)=>{var _=Q9(),M=M3(_),z=b1(M,!0),A=S1(M,2),k=b1(A,!0),G7=S1(A,2),X1=b1(G7,!0);A3(_),z3((d1)=>{C1(z,V(x1)),C1(k,V(o).message),C1(X1,d1)},[()=>V(f1).join(`
|
|
225
|
-
`)]),
|
|
222
|
+
`;for(let j of X)G+=`- ${j.rule}: ${j.reason}
|
|
223
|
+
`}return G}function k8(Q){let{request:Y,tools:J,pnpPolicy:G,customSources:X,contextId:j}=Q,Z=new E9(j);Z.addSource("host",{id:Y.scope.scopeId,name:`${Y.level}:${Y.scope.scopeId}`,config:{placement:J.placement,policy:J.policy}});let B=L7(J.placement[Y.level]),W=L7(J.policy.allowed),K=new Set(L7(J.policy.blocked)),U=[];for(let F of B)U.push(F),Z.addDecision({precedence:0,rule:"placement-membership",featureId:F,action:"skip",sourceType:"host",reason:`Listed in tools.placement.${Y.level}`});if(U=U.filter((F)=>{if(J.providers?.[F]?.enabled===!1)return Z.addDecision({precedence:0,rule:"provider-disabled",featureId:F,action:"block",sourceType:"host",reason:`tools.providers.${F}.enabled === false`,value:!1}),!1;return!0}),W.length>0){let F=new Set(W);U=U.filter((L)=>{if(!F.has(L))return Z.addDecision({precedence:0,rule:"host-allowlist",featureId:L,action:"block",sourceType:"host",reason:"Not present in tools.policy.allowed",value:W}),!1;return!0})}U=U.filter((F)=>{if(K.has(F))return Z.addDecision({precedence:0,rule:"host-blocked",featureId:F,action:"block",sourceType:"host",reason:"Listed in tools.policy.blocked",value:J.policy.blocked}),!1;return!0});let _=[],$=new Map;for(let F of U)$.set(F,["placement"]);let N=new Set(U),D=null;if(G.enforcement==="on"&&G.source&&(G.assessment||G.currentItemRef)){if(D=G.source.apply({assessment:G.assessment,currentItemRef:G.currentItemRef}),D.sources.assessment)Z.addSource("assessment",D.sources.assessment);if(D.sources.student)Z.addSource("student",D.sources.student);if(D.sources.item)Z.addSource("item",D.sources.item);for(let F of D.decisions)Z.addDecision({precedence:F.precedence,rule:F.rule,featureId:F.featureId,action:F.action,sourceType:F.sourceType,reason:F.reason,value:F.value});for(let F of D.unmappedSupportIds)_.push({code:"tool-policy.unknownSupportId",level:Y.level,toolId:F,message:`No registered tool claims PNP support id "${F}"; it was carried through as a feature id and matched nothing. Expected an AfA 3.0 / QTI 3.0 access feature id.`,source:"pnp.pnp-support"});U=U.filter((F)=>{return!D.blockedToolIds.has(F)});for(let F of Array.from($.keys()))if(D.blockedToolIds.has(F))$.delete(F);for(let F of D.mandatedToolIds){if(!!N.has(F))continue;let v=D.perToolFlags.get(F)?.rule??"required-tool",k=N2(F,{placement:B,allowed:W,blocked:K,providers:J.providers}),p={rule:v,hostRule:k.hostRule,hostValue:k.hostValue};_.push({code:"tool-policy.requiredToolBlocked",level:Y.level,toolId:F,message:`Profile policy mandates "${F}" (${v}) but host policy removed it from level "${Y.level}" via ${k.hostRule}.`,details:p}),Z.addDecision({precedence:0,rule:"required-tool-blocked",featureId:F,action:"advisory",sourceType:"host",reason:`Host removed required tool "${F}" via ${k.hostRule}`,value:p})}for(let F of U){let L=D.perToolFlags.get(F);if(L){let C=$.get(F)??[];C.push(`pnp.${L.rule}`),$.set(F,C)}}}for(let F=0;F<X.length;F++){let L=X[F],C=U.slice(),v=L.refine({request:Y,candidates:C}),k=new Set(v.refinedCandidates);for(let R of v.refinedCandidates)if(!C.includes(R))_.push({code:"tool-policy.placementMissing",level:Y.level,toolId:R,message:`Custom source "${L.id}" tried to add tool "${R}" that was not in candidates; ignored.`,source:`custom.${L.id}`}),k.delete(R);U=C.filter((R)=>k.has(R));let p=new Set;if(v.decisions){for(let R of v.decisions)if(Z.addDecision({precedence:R.precedence??100+F,rule:R.rule,featureId:R.featureId,action:R.action,sourceType:R.sourceType,reason:R.reason,value:R.value}),R.action==="block")p.add(R.featureId)}for(let R of C){if(k.has(R))continue;if(p.has(R))continue;Z.addDecision({precedence:100+F,rule:"custom-source",featureId:R,action:"block",sourceType:"custom",reason:`Custom policy source "${L.id}" removed tool "${R}" from candidates without emitting a decision; auto-logged for trail completeness.`,value:{customSourceId:L.id}})}for(let R of U){let g=$.get(R)??["placement"];g.push(`custom.${L.id}`),$.set(R,g)}for(let R of C)if(!k.has(R))$.delete(R)}let O=new Set(U),P=U.map((F)=>{let L=D?.perToolFlags.get(F);return{toolId:F,required:L?.required??!1,alwaysAvailable:L?.alwaysAvailable??!1,settings:L?.settings,sources:$.get(F)??["placement"]}});return Z.reconcileFinalStates(O),{visibleTools:P,diagnostics:_,provenance:Z.build()}}function N2(Q,Y){if(!Y.placement.includes(Q))return{hostRule:"placement-missing",hostValue:Y.placement};if(Y.providers?.[Q]?.enabled===!1)return{hostRule:"provider-disabled",hostValue:!1};if(Y.allowed.length>0&&!Y.allowed.includes(Q))return{hostRule:"host-allowlist",hostValue:Y.allowed};if(Y.blocked.has(Q))return{hostRule:"host-blocked",hostValue:Array.from(Y.blocked)};return{hostRule:"placement-missing",hostValue:Y.placement}}function I8(Q){if(!Q)return!1;let Y=Q.personalNeedsProfile;if(Y){if(Array.isArray(Y.supports)&&Y.supports.length>0)return!0;if(Array.isArray(Y.prohibitedSupports)&&Y.prohibitedSupports.length>0)return!0;if(Array.isArray(Y.activateAtInit)&&Y.activateAtInit.length>0)return!0}let J=Q.settings;if(J){let G=J.districtPolicy;if(G){if(Array.isArray(G.blockedTools)&&G.blockedTools.length>0)return!0;if(Array.isArray(G.requiredTools)&&G.requiredTools.length>0)return!0;if(G.policies&&typeof G.policies==="object"&&Object.keys(G.policies).length>0)return!0}let X=J.testAdministration;if(X&&typeof X==="object")for(let j of Object.keys(X)){let Z=X[j];if(Z===void 0||Z===null)continue;if(Array.isArray(Z)&&Z.length===0)continue;if(typeof Z==="object"&&!Array.isArray(Z)&&Object.keys(Z).length===0)continue;return!0}}return!1}function v8(Q){let Y=Q?.settings;if(!Y)return!1;if(Array.isArray(Y.requiredTools)&&Y.requiredTools.length>0)return!0;if(Array.isArray(Y.restrictedTools)&&Y.restrictedTools.length>0)return!0;if(Y.toolParameters&&typeof Y.toolParameters==="object"&&Object.keys(Y.toolParameters).length>0)return!0;return!1}function d7(Q){if(I8(Q.assessment))return"on";if(v8(Q.currentItemRef))return"on";return"off"}class D1{id="pnp";toolRegistry;constructor(Q){this.toolRegistry=Q}apply(Q){let{ctx:Y,result:J}=this.prepare(Q),{pnp:G,districtPolicy:X,itemSettings:j}=Y,Z=new Set;G?.supports?.forEach((B)=>Z.add(B)),G?.prohibitedSupports?.forEach((B)=>Z.add(B)),X?.blockedTools?.forEach((B)=>Z.add(B)),X?.requiredTools?.forEach((B)=>Z.add(B)),j?.requiredTools?.forEach((B)=>Z.add(B)),j?.restrictedTools?.forEach((B)=>Z.add(B));for(let B of Z)this.resolveSupport(B,Y,J);return J}resolveFeature(Q,Y){let{ctx:J,result:G}=this.prepare(Y);return this.resolveSupport(Q,J,G),G}prepare(Q){let{assessment:Y,currentItemRef:J}=Q,G=Y?.personalNeedsProfile,X=Y?.settings,j=J?.settings,Z={blockedToolIds:new Set,mandatedToolIds:new Set,perToolFlags:new Map,decisions:[],unmappedSupportIds:new Set,sources:{}};if(X?.districtPolicy||X?.testAdministration)Z.sources.assessment={id:Y?.id||"unknown",name:Y?.name||Y?.id||"Assessment",config:X};if(G)Z.sources.student={id:"student",name:"Student PNP Profile",config:G};if(J&&j)Z.sources.item={id:J.identifier,name:J.identifier,config:j};return{ctx:{pnp:G,districtPolicy:X?.districtPolicy,testAdmin:X?.testAdministration,itemSettings:j,toolConfigs:X?.toolConfigs},result:Z}}resolveSupport(Q,Y,J){if(Y.districtPolicy?.blockedTools?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.blockedToolIds.add(X),J.decisions.push({precedence:1,rule:"district-block",featureId:X,action:"block",sourceType:"assessment",reason:`District policy blocks "${Q}" for all assessments`,value:Y.districtPolicy.blockedTools});return}if(Y.testAdmin?.toolOverrides?.[Q]===!1){let X=this.mapSupportToToolId(Q,J);J.blockedToolIds.add(X),J.decisions.push({precedence:2,rule:"test-admin-override",featureId:X,action:"block",sourceType:"assessment",reason:`Test administrator disabled "${Q}" for this session`,value:Y.testAdmin.toolOverrides});return}if(Y.itemSettings?.restrictedTools?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.blockedToolIds.add(X),J.decisions.push({precedence:3,rule:"item-restriction",featureId:X,action:"block",sourceType:"item",reason:`Item restricts "${Q}" (e.g., mental math question blocks calculator)`,value:Y.itemSettings.restrictedTools});return}if(Y.itemSettings?.requiredTools?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.mandatedToolIds.add(X),J.perToolFlags.set(X,{required:!0,alwaysAvailable:!1,settings:this.resolveToolSettings(Q,Y),rule:"item-requirement",sourceType:"item"}),J.decisions.push({precedence:4,rule:"item-requirement",featureId:X,action:"enable",sourceType:"item",reason:`Item requires "${Q}" for this question`,value:Y.itemSettings.requiredTools});return}if(Y.districtPolicy?.requiredTools?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.mandatedToolIds.add(X),J.perToolFlags.set(X,{required:!0,alwaysAvailable:!1,settings:this.resolveToolSettings(Q,Y),rule:"district-requirement",sourceType:"assessment"}),J.decisions.push({precedence:5,rule:"district-requirement",featureId:X,action:"enable",sourceType:"assessment",reason:`District policy requires "${Q}" for all assessments`,value:Y.districtPolicy.requiredTools});return}if(Y.pnp?.prohibitedSupports?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.blockedToolIds.add(X),J.decisions.push({precedence:6,rule:"pnp-prohibited",featureId:X,action:"block",sourceType:"student",reason:`Student PNP profile prohibits "${Q}"`,value:Y.pnp.prohibitedSupports});return}if(Y.pnp?.supports?.includes(Q)){let X=this.mapSupportToToolId(Q,J);J.perToolFlags.set(X,{required:!1,alwaysAvailable:!0,settings:this.resolveToolSettings(Q,Y),rule:"pnp-support",sourceType:"student"}),J.decisions.push({precedence:6,rule:"pnp-support",featureId:X,action:"enable",sourceType:"student",reason:`Student PNP profile requests "${Q}"`,value:Y.pnp.supports});return}let G=this.mapSupportToToolId(Q,J);J.decisions.push({precedence:6,rule:"pnp-support",featureId:G,action:"skip",sourceType:"system",reason:`Feature "${Q}" not configured at any level`,value:{supportId:Q}})}mapSupportToToolId(Q,Y){let J=this.toolRegistry.getToolsByPNPSupport(Q);if(J.size===0){if(this.toolRegistry.getAllTools().length>0)Y.unmappedSupportIds.add(Q);return Q}return Array.from(J)[0]}resolveToolSettings(Q,Y){return Y.itemSettings?.toolParameters?.[Q]??Y.toolConfigs?.[Q]}}var h8=b7({policy:{allowed:[],blocked:[]},placement:{section:[],item:[],passage:[]},providers:{}});class N1{toolRegistry;contextId;pnpPolicySource;customSources;listeners=new Set;tools;assessment;currentItemRef;pnpEnforcement;disposed=!1;constructor(Q){this.toolRegistry=Q.toolRegistry,this.contextId=Q.contextId??"tool-policy",this.pnpPolicySource=new D1(this.toolRegistry),this.customSources=Q.customSources?[...Q.customSources]:[];let Y=Q.inputs??{};this.tools=Y.tools??h8,this.assessment=Y.assessment??null,this.currentItemRef=Y.currentItemRef??null,this.pnpEnforcement=Y.pnpEnforcement??d7({assessment:this.assessment,currentItemRef:this.currentItemRef})}decide(Q){this.assertNotDisposed();let Y=Q.scope.scopeId?`${this.contextId}:${Q.level}:${Q.scope.scopeId}`:`${this.contextId}:${Q.level}`;return k8({request:Q,tools:this.tools,pnpPolicy:{source:this.pnpPolicySource,assessment:this.assessment??void 0,currentItemRef:this.currentItemRef??void 0,enforcement:this.pnpEnforcement},customSources:this.customSources,contextId:Y})}decideFeature(Q){this.assertNotDisposed();let Y=this.hostFeatureGate(Q);if(Y)return Y;return x8(Q,this.pnpPolicySource.resolveFeature(Q,{assessment:this.assessment??void 0,currentItemRef:this.currentItemRef??void 0}),{assessmentBound:this.assessment!==null})}hostFeatureGate(Q){let Y={assessmentBound:this.assessment!==null},J=L7(this.tools.policy.blocked);if(J.includes(Q))return R9(Q,"host-blocked",J,Y);let G=L7(this.tools.policy.allowed);if(G.length>0&&!G.includes(Q))return R9(Q,"host-allowlist",G,Y);return null}getVisibleToolIds(Q,Y){return this.decide({level:Q,scope:{level:Q,scopeId:Y}}).visibleTools.map((J)=>J.toolId)}updateInputs(Q){this.assertNotDisposed();let Y=!1,J=!1;if("tools"in Q){let G=Q.tools??h8;if(!Object.is(this.tools,G))this.tools=G,Y=!0}if("assessment"in Q){let G=Q.assessment??null;if(!Object.is(this.assessment,G))this.assessment=G,Y=!0}if("currentItemRef"in Q){let G=Q.currentItemRef??null;if(!Object.is(this.currentItemRef,G))this.currentItemRef=G,Y=!0}if("pnpEnforcement"in Q&&Q.pnpEnforcement){if(this.pnpEnforcement!==Q.pnpEnforcement)this.pnpEnforcement=Q.pnpEnforcement,J=!0}if(Y||J)this.emit({reason:J&&!Y?"pnp-enforcement":"inputs",inputs:this.snapshotInputs()})}replaceToolRegistry(Q,Y){this.assertNotDisposed(),this.toolRegistry=Q,this.pnpPolicySource=new D1(Q),this.tools=Y,this.emit({reason:"inputs",inputs:this.snapshotInputs()})}registerPolicySource(Q){return this.assertNotDisposed(),this.customSources.push(Q),this.emit({reason:"policy-source-added",inputs:this.snapshotInputs()}),()=>{let Y=this.customSources.indexOf(Q);if(Y!==-1){if(this.customSources.splice(Y,1),!this.disposed)this.emit({reason:"policy-source-removed",inputs:this.snapshotInputs()})}}}onPolicyChange(Q){return this.listeners.add(Q),()=>{this.listeners.delete(Q)}}getInputs(){return this.snapshotInputs()}dispose(){if(this.disposed)return;this.disposed=!0,this.emit({reason:"disposed",inputs:this.snapshotInputs()}),this.listeners.clear(),this.customSources.length=0}snapshotInputs(){return Object.freeze({tools:this.tools,assessment:this.assessment,currentItemRef:this.currentItemRef,pnpEnforcement:this.pnpEnforcement})}emit(Q){for(let Y of Array.from(this.listeners))try{Y(Q)}catch{}}assertNotDisposed(){if(this.disposed)throw Error("ToolPolicyEngine has been disposed.")}}class s extends Error{constructor(){super("ToolkitCoordinator has been disposed.");this.name="ToolkitCoordinatorDisposedError"}}class C9 extends Error{constructor(){super("Section controller acquisition was retired during initialization.");this.name="SectionControllerRetiredError"}}var M1=(Q)=>!!Q&&typeof Q==="object"&&!Array.isArray(Q),M2=(Q,Y,J)=>{let G={...Y,...J};if(Q==="textToSpeech"&&M1(Y.settings)&&M1(J.settings)){if(G.settings={...Y.settings,...J.settings},M1(Y.settings.mathSpeech)&&M1(J.settings.mathSpeech))G.settings.mathSpeech={...Y.settings.mathSpeech,...J.settings.mathSpeech}}return G},z2=["item-selected","item-session-data-changed","item-session-meta-changed","item-complete-changed","content-loaded","item-player-error"],O2=["section-navigation-change","section-session-applied","section-loading-complete","section-items-complete-changed","section-error","timed-media-cue-changed","timed-media-policy-degraded","timed-media-invalid"];class T9{assessmentId;config;ttsService;toolCoordinator;highlightCoordinator;elementToolStateStore;catalogResolver;toolProviderRegistry;hooks;lazyInit;ttsInitialized=!1;ttsInitPromise;ttsReconfigurePromise;stateLoaded=!1;stateLoadPromise;coordinatorReadyPromise;coordinatorReadyNotified=!1;providerInitPromises=new Map;toolRegistry;toolRegistrySupplied;toolRegistrySettled;toolContextResolvers=new Map;toolContextResolverChangeListeners=new Set;toolRequests=new w9;sectionControllers=new Map;sectionControllerKeys=new Map;sectionControllerInitEntries=new Map;sectionControllerDisposePromises=new Map;sectionPersistenceStrategies=new Map;sectionControllerLifecycleListeners=new Set;activeSubscriptions=new Map;activeCohortMapKey=null;latestRequestedActiveCohortMapKey=null;telemetryListeners=new Set;frameworkErrorBus;ownsFrameworkErrorBus;frameworkErrorHookUnsubscribe=null;disposePromise=null;policyEngine;pnpEnforcementOverride=null;boundAssessment=null;boundCurrentItemRef=null;reportedUnboundFeaturePolicy=!1;reportedMissingTTSProvider=!1;heldMissingTTSProviderBackend=null;reportedRegistryUnavailable=!1;resolveConfig(Q){let Y=c1(Q.toolConfigStrictness),J=Q.toolRegistry??new S9,G=Q.deferToolConfigValidation===!0?b7(Q.tools):this.validateToolsConfig(Q.tools,{strictness:Y,source:"ToolkitCoordinator.init",toolRegistry:J});return{...Q,toolConfigStrictness:Y,toolRegistry:J,tools:{...G,providers:{...{textToSpeech:{enabled:!0,backend:"browser"},annotationToolbar:{enabled:!0}},...G.providers}},accessibility:{language:"en-US",...Q.accessibility??{},catalogs:Q.accessibility?.catalogs??[]}}}validateToolsConfig(Q,Y){let{config:J,diagnostics:G}=d1(Q,Y.toolRegistry),X=this.reportedRegistryUnavailable||!this.toolRegistrySettled?G.filter((j)=>j.code!=="tools.registryUnavailable"):G;if(l1(X,Y),Y.strictness!=="off"&&X.some((j)=>j.code==="tools.registryUnavailable"))this.reportedRegistryUnavailable=!0;return J}constructor(Q){if(!Q.assessmentId)throw Error("ToolkitCoordinator requires assessmentId in config");this.toolRegistrySupplied=Q.toolRegistry!=null,this.toolRegistrySettled=this.toolRegistrySupplied;let Y=this.resolveConfig(Q);if(this.assessmentId=Y.assessmentId,this.config=Y,this.toolRegistry=Y.toolRegistry??new S9,this.installToolContextResolvers(Y.toolContextResolvers),this.hooks=Y.hooks??{},this.lazyInit=Q.lazyInit===!0,this.pnpEnforcementOverride=this.resolveConfiguredPnpEnforcement(),this.frameworkErrorBus=Q.frameworkErrorBus??new u7,this.ownsFrameworkErrorBus=!Q.frameworkErrorBus,this.subscribeFrameworkErrorHookAdapters(),this.toolCoordinator=new G9,this.highlightCoordinator=new p7,this.elementToolStateStore=new Y9,this.catalogResolver=new Q9(Y.accessibility?.catalogs||[],Y.accessibility?.language||"en-US"),this.toolProviderRegistry=new H1,this._registerToolProviders(),this.ttsService=new c7,this.ttsService.setHighlightCoordinator(this.highlightCoordinator),this.setupStatePersistenceHooks(),this.policyEngine=new N1({toolRegistry:this.toolRegistry,contextId:`toolkit-coordinator:${this.assessmentId}`,inputs:{tools:this.config.tools,assessment:null,currentItemRef:null,pnpEnforcement:this.resolveEffectivePnpEnforcement()}}),!this.lazyInit)this.waitUntilReady().catch((J)=>{if(J instanceof s)return;console.error("[ToolkitCoordinator] Failed eager initialization:",J),this.handleError(J,{phase:"coordinator-ready"})})}assertNotDisposed(){if(this.disposePromise!==null)throw new s}subscribeFrameworkErrorHookAdapters(){this.frameworkErrorHookUnsubscribe=this.frameworkErrorBus.subscribeFrameworkErrors((Q)=>{let Y=this.hooks.onFrameworkError;if(!Y)return;try{Y(Q)}catch(J){console.warn("[ToolkitCoordinator] onFrameworkError hook failed:",J)}})}async emitTelemetry(Q,Y){try{await this.hooks.onTelemetry?.(Q,Y)}catch(G){console.warn("[ToolkitCoordinator] telemetry hook failed:",G)}let J=Y?{...Y}:void 0;for(let G of this.telemetryListeners)try{G({eventName:Q,payload:J?{...J}:void 0})}catch(X){console.warn("[ToolkitCoordinator] telemetry listener failed:",X)}}emitSectionControllerLifecycle(Q){for(let Y of this.sectionControllerLifecycleListeners)try{Y(Q)}catch(J){console.warn("[ToolkitCoordinator] section controller lifecycle listener failed:",J)}}handleError(Q,Y){let J=W0({error:Q,context:Y});this.frameworkErrorBus.reportFrameworkError(J)}subscribeFrameworkErrors(Q){return this.frameworkErrorBus.subscribeFrameworkErrors(Q)}reportFrameworkError(Q){this.frameworkErrorBus.reportFrameworkError(Q)}getSectionControllerMapKey(Q){return`${Q.assessmentId}::${Q.sectionId}::${Q.attemptId||""}`}createDefaultSectionPersistence(){let Q=(()=>{try{if(typeof window>"u")return null;return window.localStorage}catch{return null}})(),Y=(J)=>{let{assessmentId:G,sectionId:X,attemptId:j}=J.key;return`pie:section-controller:v1:${G}:${X}:${j||"default"}`};return{async loadSession(J){if(!Q)return null;let G=Q.getItem(Y(J));if(!G)return null;try{return JSON.parse(G)}catch{return null}},async saveSession(J,G){if(!Q)return;Q.setItem(Y(J),JSON.stringify(G))},async clearSession(J){if(!Q)return;Q.removeItem(Y(J))}}}async resolveSectionPersistence(Q){let Y=this.getSectionControllerMapKey(Q.key),J=this.sectionPersistenceStrategies.get(Y);if(J)return J;let G={createDefaultPersistence:()=>this.createDefaultSectionPersistence()},X=await this.hooks.createSectionSessionPersistence?.(Q,G)??await G.createDefaultPersistence();return this.sectionPersistenceStrategies.set(Y,X),X}setupStatePersistenceHooks(){this.elementToolStateStore.setOnStateChange((Q)=>{if(!this.hooks.saveToolState)return;Promise.resolve(this.hooks.saveToolState(Q)).catch((Y)=>{this.handleError(Y,{phase:"state-save"})})})}async ensureStateLoaded(){if(this.stateLoaded)return;if(this.stateLoadPromise)return this.stateLoadPromise;return this.stateLoadPromise=(async()=>{let Q=this.hooks.loadToolState;if(!Q)return;try{let Y=await Q();if(this.assertNotDisposed(),Y&&typeof Y==="object")this.elementToolStateStore.loadState(Y);this.stateLoaded=!0,await this.emitTelemetry("pie-toolkit-tool-state-loaded",{hasState:Boolean(Y)})}catch(Y){if(Y instanceof s)throw Y;this.handleError(Y,{phase:"state-load"})}})().finally(()=>{this.stateLoadPromise=void 0}),this.stateLoadPromise}reportMissingTTSProvider(Q){if(!this.toolRegistrySettled){this.heldMissingTTSProviderBackend=Q;return}if(this.reportedMissingTTSProvider)return;this.reportedMissingTTSProvider=!0,console.warn(`[ToolkitCoordinator] Text-to-speech is configured for the "${Q}" backend but falls back to browser speech: no "tts" tool provider is registered. A coordinator registers tool providers only from its \`toolRegistry\`, or from its toolkit's when constructed without one, so supply one that carries the text-to-speech registration — for the packaged capability set, \`createPackagedToolRegistry()\` from "@pie-players/pie-default-tool-loaders". Reported once per coordinator.`)}adoptToolRegistry(Q){if(this.disposePromise!==null||this.toolRegistrySettled)return!1;this.toolRegistrySettled=!0;let Y=this.heldMissingTTSProviderBackend;this.heldMissingTTSProviderBackend=null;let J=this.config.toolConfigStrictness??"error",G="ToolkitCoordinator.adoptToolRegistry";if(!Q){if(this.validateToolsConfig(this.config.tools,{strictness:J,source:G,toolRegistry:this.toolRegistry}),Y)this.reportMissingTTSProvider(Y);return!1}this.toolRegistry=Q,this.config.toolRegistry=Q;try{this.config.tools=this.validateToolsConfig(this.config.tools,{strictness:J==="off"?"off":"warn",source:G,toolRegistry:Q})}catch(j){console.warn("[ToolkitCoordinator] Tool config does not validate against the adopted tool registry:",j)}this.policyEngine.replaceToolRegistry(Q,this.config.tools);let X=this.ttsInitialized||this.ttsInitPromise!==void 0||this.ttsReconfigurePromise!==void 0;for(let j of this.getProviderDescriptorTools()){if(X&&j.toolId==="textToSpeech")continue;this.registerProviderFromTool(j)}if(X)this.scheduleTTSReconfigure();return!0}_registerToolProviders(){let Q=this.getProviderDescriptorTools();for(let Y of Q)this.registerProviderFromTool(Y)}getProviderDescriptorTools(){return this.toolRegistry.getAllTools().filter((Q)=>!!Q.provider)}async registerProviderFromTool(Q){let Y=Q.provider;if(!Y)return;let J=null,G;try{let X=this.getToolConfig(Q.toolId)||void 0;if(X?.enabled===!1)return;if(J=b9(Q,X),!J||this.toolProviderRegistry.has(J))return;let j=Y.createProvider(X),Z=Y.getInitConfig?.(X)??X?.provider?.init??{},B=this.addToolTelemetryReporter({toolId:Q.toolId,providerId:J,initConfig:Z}),W=this.createToolTelemetryForwarder({toolId:Q.toolId,providerId:J}),K=Y.getAuthFetcher?.(X)??X?.provider?.runtime?.authFetcher;G={provider:j,config:B,lazy:Y.lazy??!0,authFetcher:K,onTelemetry:W}}catch(X){this.reportProviderRegisterFailure(X,J,Q.toolId);return}await this.registerProvider(J,G)}createToolTelemetryForwarder(Q){return async(Y,J)=>{await this.emitTelemetry(Y,{...J||{},toolId:Q.toolId,providerId:Q.providerId})}}addToolTelemetryReporter(Q){let Y=Q.initConfig&&typeof Q.initConfig==="object"?{...Q.initConfig}:{},J=typeof Y.onTelemetry==="function"?Y.onTelemetry:null,G=this.createToolTelemetryForwarder({toolId:Q.toolId,providerId:Q.providerId});return Y.onTelemetry=async(X,j)=>{if(J)await J(X,j);await G(X,j)},Y}async registerProvider(Q,Y){try{this.toolProviderRegistry.register(Q,Y);let J={providerId:Q,providerName:Y.provider.providerName};await this.hooks.onProviderRegistered?.(Q,J),await this.emitTelemetry("pie-toolkit-provider-registered",{providerId:Q,providerName:Y.provider.providerName})}catch(J){this.reportProviderRegisterFailure(J,Q)}}reportProviderRegisterFailure(Q,Y,J){console.warn(Y?`[ToolkitCoordinator] Failed to register provider "${Y}":`:`[ToolkitCoordinator] Failed to register the provider of tool "${J}":`,Q),this.handleError(Q,{phase:"provider-register",providerId:Y??void 0})}async ensureProviderReady(Q){this.assertNotDisposed();let Y=this.providerInitPromises.get(Q);if(Y)return Y;let J=(async()=>{let G=await this.toolProviderRegistry.getProvider(Q,!1);this.assertNotDisposed();let X={providerId:Q,providerName:G.providerName};try{return await this.hooks.onProviderInitStart?.(Q,X),this.assertNotDisposed(),await this.toolProviderRegistry.initialize(Q),this.assertNotDisposed(),await this.hooks.onProviderReady?.(Q,X),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-provider-ready",{providerId:Q}),this.assertNotDisposed(),G}catch(j){if(j instanceof s)throw j;let Z=j instanceof Error?j:Error(String(j));throw this.handleError(Z,{phase:"provider-init",providerId:Q}),Z}})().finally(()=>{this.providerInitPromises.delete(Q)});return this.providerInitPromises.set(Q,J),J}setHooks(Q){if(Object.assign(this.hooks,Q),this.setupStatePersistenceHooks(),this.disposePromise===null&&Q.onCoordinatorReady&&this.isReady())Promise.resolve(Q.onCoordinatorReady(this)).catch((Y)=>{this.handleError(Y,{phase:"coordinator-ready"})})}subscribeTelemetry(Q){return this.telemetryListeners.add(Q),()=>{this.telemetryListeners.delete(Q)}}getSectionController(Q){let Y={assessmentId:this.assessmentId,sectionId:Q.sectionId,attemptId:Q.attemptId};return this.sectionControllers.get(this.getSectionControllerMapKey(Y))}subscribeSectionEvents(Q){if(this.activeCohortMapKey===null)throw Error("[ToolkitCoordinator] subscribeSectionEvents requires an active section cohort; call getOrCreateSectionController first.");let Y=this.activeSubscriptions.get(Q.listener);if(Y)Y.unsubscribeCurrent?.(),Y.unsubscribeCurrent=null;let J={listener:Q.listener,eventTypes:Q.eventTypes,itemIds:Q.itemIds,unsubscribeCurrent:null};this.activeSubscriptions.set(Q.listener,J);let G=this.sectionControllers.get(this.activeCohortMapKey);if(G)this.bindSubscriptionToController(J,G);let X=!1;return()=>{if(X)return;if(X=!0,J.unsubscribeCurrent?.(),J.unsubscribeCurrent=null,this.activeSubscriptions.get(Q.listener)===J)this.activeSubscriptions.delete(Q.listener)}}bindSubscriptionToController(Q,Y){Q.unsubscribeCurrent?.(),Q.unsubscribeCurrent=null;let J=Y.subscribe;if(typeof J!=="function")return;let G=this.buildSectionEventPredicate(Q);Q.unsubscribeCurrent=J.call(Y,(Z)=>{if(!G(Z))return;this.deliverSectionEventSafely(Q.listener,Z)});let X=this.buildContentLoadedReplayEvents(Y);for(let Z of X)if(G(Z))this.deliverSectionEventSafely(Q.listener,Z);let j=this.buildLoadingCompleteReplayEvent(Y);if(j&&G(j))this.deliverSectionEventSafely(Q.listener,j)}deliverSectionEventSafely(Q,Y){try{Q(Y)}catch(J){console.warn("[ToolkitCoordinator] section-event listener failed:",J)}}setActiveCohort(Q){if(this.activeCohortMapKey===Q)return;this.activeCohortMapKey=Q;let Y=this.sectionControllers.get(Q);if(!Y)return;for(let J of Array.from(this.activeSubscriptions.values()))this.bindSubscriptionToController(J,Y)}setActiveCohortIfLatestRequest(Q){if(this.latestRequestedActiveCohortMapKey!==Q)return;this.setActiveCohort(Q)}suspendActiveCohortIfSuperseded(Q){if(this.activeCohortMapKey===null)return;if(this.activeCohortMapKey===Q)return;this.activeCohortMapKey=null;for(let Y of Array.from(this.activeSubscriptions.values()))Y.unsubscribeCurrent?.(),Y.unsubscribeCurrent=null}clearActiveCohortIfMatches(Q){if(this.activeCohortMapKey!==Q)return;this.activeCohortMapKey=null;for(let Y of Array.from(this.activeSubscriptions.values()))Y.unsubscribeCurrent?.(),Y.unsubscribeCurrent=null}buildSectionEventPredicate(Q){let Y=Q.eventTypes?new Set(Q.eventTypes):null,J=Q.itemIds?new Set(Q.itemIds):null;return(G)=>{if(Y||J){let X=G?.type||null;if(Y&&(!X||!Y.has(X)))return!1;if(J){if(!Array.from(this.collectEventItemIds(G)).some((Z)=>J.has(Z)))return!1}}return!0}}collectEventItemIds(Q){let Y=new Set;if("itemId"in Q&&typeof Q.itemId==="string")Y.add(Q.itemId);if("canonicalItemId"in Q&&typeof Q.canonicalItemId==="string")Y.add(Q.canonicalItemId);if("currentItemId"in Q&&typeof Q.currentItemId==="string")Y.add(Q.currentItemId);if("previousItemId"in Q&&typeof Q.previousItemId==="string")Y.add(Q.previousItemId);return Y}buildContentLoadedReplayEvents(Q){let Y=Q.getRuntimeState?.(),J=Y?.loadedRenderables;if(!Array.isArray(J)||J.length===0)return[];let G=typeof Y?.currentItemIndex==="number"&&Number.isFinite(Y.currentItemIndex)?Y.currentItemIndex:0,X=Date.now(),j=[];for(let Z of J){if(!Z)continue;let B=Z.itemId,W=typeof Z.canonicalItemId==="string"&&Z.canonicalItemId?Z.canonicalItemId:B;if(typeof B!=="string"||!B)continue;j.push({type:"content-loaded",contentKind:Z.contentKind??"unknown",itemId:B,canonicalItemId:W,currentItemIndex:G,timestamp:X})}return j}buildLoadingCompleteReplayEvent(Q){let Y=Q.getRuntimeState?.();if(Y?.loadingComplete!==!0)return null;let J=typeof Y.totalRegistered==="number"&&Number.isFinite(Y.totalRegistered)?Math.max(0,Y.totalRegistered):0,G=typeof Y.totalLoaded==="number"&&Number.isFinite(Y.totalLoaded)?Math.max(0,Y.totalLoaded):J;return{type:"section-loading-complete",totalRegistered:J,totalLoaded:G,currentItemIndex:Y.currentItemIndex,timestamp:Date.now()}}subscribeItemEvents(Q){return this.subscribeSectionEvents({eventTypes:Q.eventTypes||z2,itemIds:Q.itemIds,listener:Q.listener})}subscribeSectionLifecycleEvents(Q){return this.subscribeSectionEvents({eventTypes:Q.eventTypes||O2,listener:Q.listener})}onSectionControllerLifecycle(Q){return this.sectionControllerLifecycleListeners.add(Q),()=>{this.sectionControllerLifecycleListeners.delete(Q)}}async getOrCreateSectionController(Q){if(this.disposePromise!==null)throw new s;let Y={assessmentId:this.assessmentId,sectionId:Q.sectionId,attemptId:Q.attemptId},J=this.getSectionControllerMapKey(Y);this.latestRequestedActiveCohortMapKey=J,this.suspendActiveCohortIfSuperseded(J);let G=await this.resolveExistingSectionController({mapKey:J,key:Y,input:Q.input,updateExisting:Q.updateExisting});if(G){if(this.disposePromise!==null)throw new s;return G}let X=this.sectionControllerDisposePromises.get(J);if(X)await Promise.allSettled([X]);if(this.disposePromise!==null)throw new s;let j=this.sectionControllerInitEntries.get(J);if(j)return j.promise;let Z={retired:!1,candidateClaimed:!1},B=this.initializeNewSectionController({args:Q,key:Y,mapKey:J,token:Z}).catch((W)=>{throw this.handleSectionControllerInitError(W,Q),W}).finally(()=>{if(this.sectionControllerInitEntries.get(J)?.token===Z)this.sectionControllerInitEntries.delete(J)});return this.sectionControllerInitEntries.set(J,{key:Y,token:Z,promise:B}),B}async resolveExistingSectionController(Q){let Y=this.sectionControllers.get(Q.mapKey);if(!Y)return;if(this.sectionControllerKeys.set(Q.mapKey,Q.key),Q.updateExisting!==!1)await Y.updateInput?.(Q.input);if(this.sectionControllers.get(Q.mapKey)!==Y)return;return this.setActiveCohortIfLatestRequest(Q.mapKey),Y}createSectionControllerContext(Q){return{key:Q.key,coordinator:this,input:Q.input}}async initializeNewSectionController(Q){let Y=this.createSectionControllerContext({key:Q.key,input:Q.args.input}),J=await this.resolveSectionPersistence(Y);if(this.disposePromise!==null||Q.token.retired){if(this.sectionPersistenceStrategies.get(Q.mapKey)===J)this.sectionPersistenceStrategies.delete(Q.mapKey);throw this.createSectionControllerRetirementError()}let G={createDefaultController:Q.args.createDefaultController},X=await this.hooks.createSectionController?.(Y,G)??await G.createDefaultController(),j={mapKey:Q.mapKey,key:Q.key,controller:X,persistence:J,token:Q.token};try{return await this.retireUnpublishedSectionControllerIfNeeded(j),await X.configureSessionPersistence?.({strategy:J,context:Y}),await this.retireUnpublishedSectionControllerIfNeeded(j),await X.initialize?.(Q.args.input),await this.retireUnpublishedSectionControllerIfNeeded(j),await X.hydrate?.(),await this.finalizeSectionControllerReady({...j,context:Y}),X}catch(Z){throw await this.cleanupUnpublishedSectionController(j),Z}}createSectionControllerRetirementError(){return this.disposePromise!==null?new s:new C9}async retireUnpublishedSectionControllerIfNeeded(Q){if(this.disposePromise===null&&!Q.token.retired)return;throw await this.cleanupUnpublishedSectionController(Q),this.createSectionControllerRetirementError()}async cleanupUnpublishedSectionController(Q){if(Q.token.candidateClaimed)return;Q.token.candidateClaimed=!0;try{await Q.controller.dispose?.()}catch(Y){this.handleError(Y,{phase:"section-controller-dispose",details:{sectionId:Q.key.sectionId,attemptId:Q.key.attemptId}})}finally{if(this.sectionPersistenceStrategies.get(Q.mapKey)===Q.persistence)this.sectionPersistenceStrategies.delete(Q.mapKey)}}retirePublishedSectionControllerIfNeeded(Q){if(this.disposePromise!==null&&!Q.token.retired)this.disposeSectionController({sectionId:Q.key.sectionId,attemptId:Q.key.attemptId});if(Q.token.retired)throw this.createSectionControllerRetirementError()}async finalizeSectionControllerReady(Q){await this.retireUnpublishedSectionControllerIfNeeded(Q),this.sectionControllers.set(Q.mapKey,Q.controller),this.sectionControllerKeys.set(Q.mapKey,Q.key),Q.token.candidateClaimed=!0,this.setActiveCohortIfLatestRequest(Q.mapKey),this.emitSectionControllerLifecycle({type:"ready",key:Q.key,controller:Q.controller}),await this.hooks.onSectionControllerReady?.(Q.context,Q.controller),this.retirePublishedSectionControllerIfNeeded(Q),await this.emitTelemetry("pie-toolkit-section-controller-ready",{assessmentId:Q.key.assessmentId,sectionId:Q.key.sectionId,attemptId:Q.key.attemptId}),this.retirePublishedSectionControllerIfNeeded(Q)}handleSectionControllerInitError(Q,Y){if(Q instanceof s||Q instanceof C9)return;this.handleError(Q,{phase:"section-controller-init",details:{sectionId:Y.sectionId,attemptId:Y.attemptId}})}disposeSectionController(Q){let Y={assessmentId:this.assessmentId,sectionId:Q.sectionId,attemptId:Q.attemptId},J=this.getSectionControllerMapKey(Y),G=this.sectionControllerInitEntries.get(J);if(G)G.token.retired=!0;let X=this.sectionControllers.get(J);if(!X){let K=this.sectionControllerDisposePromises.get(J);if(K)return K;if(!G)return Promise.resolve();let U=Promise.allSettled([G.promise]).then(()=>{return});return this.trackSectionControllerDisposal(J,U)}let j=this.sectionPersistenceStrategies.get(J);if(this.clearActiveCohortIfMatches(J),this.sectionControllers.get(J)===X)this.sectionControllers.delete(J),this.sectionControllerKeys.delete(J),this.sectionPersistenceStrategies.delete(J),this.emitSectionControllerLifecycle({type:"disposed",key:Y});let Z=this.createSectionControllerContext({key:Y,input:void 0}),B=this.disposeSectionControllerEntry({args:Q,key:Y,context:Z,controller:X,persistenceStrategy:j}),W=G?Promise.allSettled([G.promise]).then(()=>B):B;return this.trackSectionControllerDisposal(J,W)}trackSectionControllerDisposal(Q,Y){this.sectionControllerDisposePromises.set(Q,Y);let J=()=>{if(this.sectionControllerDisposePromises.get(Q)===Y)this.sectionControllerDisposePromises.delete(Q)};return Y.then(J,J),Y}async disposeSectionControllerEntry(Q){try{await this.runSectionControllerDisposePipeline({key:Q.key,context:Q.context,controller:Q.controller,persistBeforeDispose:Q.args.persistBeforeDispose})}catch(Y){this.handleError(Y,{phase:"section-controller-dispose",details:{sectionId:Q.args.sectionId,attemptId:Q.args.attemptId}})}finally{await this.finalizeSectionControllerDispose({context:Q.context,persistenceStrategy:Q.persistenceStrategy,clearPersistence:Q.args.clearPersistence})}}async runSectionControllerDisposePipeline(Q){let Y=[];if(Q.persistBeforeDispose!==!1)try{await Q.controller.persist?.()}catch(J){Y.push(J)}try{await Q.controller.dispose?.()}catch(J){Y.push(J)}if(Y.length===1)throw Y[0];if(Y.length>1)throw AggregateError(Y,"Section controller persistence and disposal both failed.");await this.hooks.onSectionControllerDispose?.(Q.context,Q.controller),await this.emitTelemetry("pie-toolkit-section-controller-disposed",{assessmentId:Q.key.assessmentId,sectionId:Q.key.sectionId,attemptId:Q.key.attemptId})}async finalizeSectionControllerDispose(Q){if(Q.clearPersistence)await Q.persistenceStrategy?.clearSession?.(Q.context)}dispose(){if(this.disposePromise)return this.disposePromise;return this.disposePromise=Promise.resolve().then(()=>this.disposeOwnedResources()),this.disposePromise}async disposeOwnedResources(){let Q=[],Y=async(G)=>{try{await G()}catch(X){Q.push(X)}};await this.waitForAdmittedInitialization();let J=new Map;for(let[G,X]of this.sectionControllerInitEntries)J.set(G,X.key);for(let[G,X]of this.sectionControllerKeys)J.set(G,X);for(let G of J.values())this.disposeSectionController({sectionId:G.sectionId,attemptId:G.attemptId});await Promise.allSettled(Array.from(this.sectionControllerDisposePromises.values())),this.sectionControllers.clear(),this.sectionControllerKeys.clear(),this.sectionControllerInitEntries.clear(),this.sectionPersistenceStrategies.clear();for(let G of this.activeSubscriptions.values())await Y(()=>G.unsubscribeCurrent?.()),G.unsubscribeCurrent=null;this.activeSubscriptions.clear(),this.activeCohortMapKey=null,this.latestRequestedActiveCohortMapKey=null,await Y(()=>this.ttsService.stop()),await Y(()=>this.toolProviderRegistry.destroy()),await Y(()=>this.highlightCoordinator.destroy());for(let G of this.toolCoordinator.getRegisteredTools())await Y(()=>this.toolCoordinator.releaseTool(G));if(await Y(()=>this.catalogResolver.destroy()),await Y(()=>this.toolRequests.dispose()),await Y(()=>this.policyEngine.dispose()),this.toolContextResolvers.clear(),this.toolContextResolverChangeListeners.clear(),this.sectionControllerLifecycleListeners.clear(),this.telemetryListeners.clear(),this.frameworkErrorHookUnsubscribe?.(),this.frameworkErrorHookUnsubscribe=null,this.ownsFrameworkErrorBus)this.frameworkErrorBus.dispose();if(Q.length===1)throw Q[0];if(Q.length>1)throw AggregateError(Q,"ToolkitCoordinator cleanup failed for multiple owned resources.")}async waitForAdmittedInitialization(){let Q=new Set;if(this.coordinatorReadyPromise)Q.add(this.coordinatorReadyPromise);if(this.ttsInitPromise)Q.add(this.ttsInitPromise);if(this.ttsReconfigurePromise)Q.add(this.ttsReconfigurePromise);for(let Y of this.providerInitPromises.values())Q.add(Y);await Promise.allSettled(Q)}async ensureTTSReady(Q){if(this.assertNotDisposed(),await this.waitForPendingTTSReconfigure(),this.assertNotDisposed(),this.ttsInitialized)return;if(this.ttsInitPromise)return this.ttsInitPromise;return this.ttsInitPromise=this._initializeTTS(Q).then(()=>this.assertNotDisposed()).finally(()=>{this.ttsInitPromise=void 0}),this.ttsInitPromise}async waitForPendingTTSReconfigure(){let Q=this.ttsReconfigurePromise;while(Q)await Q,Q=this.ttsReconfigurePromise}async _initializeTTS(Q){if(this.ttsInitialized)return;let Y=this.resolveTTSToolConfig(Q),J=y8(Y),G=L9(J),X=f8(J);if(await this.hooks.onBeforeTTSInit?.({phase:"tts-init",details:{backend:G}}),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-tts-init-start",{backend:G}),await this.emitTelemetry("pie-tool-init-start",{toolId:"textToSpeech",operation:"tts-init",backend:G}),this.toolProviderRegistry.has("tts"))try{let B=await(await this.ensureProviderReady("tts")).createInstance();await this.initializeTTSService(B,X),await this.emitTelemetry("pie-toolkit-tts-init-success",{provider:"registry"}),await this.emitTelemetry("pie-tool-init-success",{toolId:"textToSpeech",operation:"tts-init",backend:G,provider:"registry"}),console.log("[ToolkitCoordinator] TTS initialized via ToolProviderRegistry");return}catch(Z){if(Z instanceof s)throw Z;let B=Z instanceof Error?Z:Error(String(Z));await this.emitTelemetry("pie-tool-init-error",{toolId:"textToSpeech",providerId:"tts",operation:"tts-init",backend:G,errorType:"TTSRegistryInitError",message:B.message,recovered:!0}),await this.emitTelemetry("pie-tool-init-fallback",{toolId:"textToSpeech",providerId:"tts",operation:"tts-init",backend:G,fromProvider:"registry",toProvider:"browser",reason:B.message}),console.warn("[ToolkitCoordinator] Failed to initialize TTS via registry, falling back to browser provider:",B)}else if(G!=="browser")this.reportMissingTTSProvider(G);let j=new g7;try{await this.initializeTTSService(j,X),await this.emitTelemetry("pie-toolkit-tts-init-success",{provider:"browser-fallback"}),await this.emitTelemetry("pie-tool-init-success",{toolId:"textToSpeech",operation:"tts-init",backend:G,provider:"browser-fallback"})}catch(Z){if(Z instanceof s)throw Z;let B=Z instanceof Error?Z:Error(String(Z));throw this.handleError(B,{phase:"tts-init"}),await this.emitTelemetry("pie-toolkit-tts-init-error",{message:B.message}),await this.emitTelemetry("pie-tool-init-error",{toolId:"textToSpeech",operation:"tts-init",backend:G,errorType:"TTSInitError",message:B.message}),B}}resolveTTSToolConfig(Q){return Q||this.getTTSConfigFromProviders()||{}}async initializeTTSService(Q,Y){let J={...Y.providerOptions||{},__pieTelemetry:async(X,j)=>{await this.emitTelemetry(X,{toolId:"textToSpeech",...j||{}})}},G={...Y,providerOptions:J};await this.ttsService.initialize(Q,G),await this.ensureBrowserVoicesReady(Q),this.assertNotDisposed(),this.ttsService.setCatalogResolver(this.catalogResolver),this.ttsInitialized=!0,await this.hooks.onTTSReady?.(),this.assertNotDisposed()}async ensureBrowserVoicesReady(Q,Y=1200){if(Q.providerId!=="browser")return;if(typeof window>"u")return;if(!("speechSynthesis"in window))return;let J=window.speechSynthesis;if(J.getVoices().length>0)return;await new Promise((j)=>{let Z=!1,B=typeof J.addEventListener==="function"&&typeof J.removeEventListener==="function",W=!B&&"onvoiceschanged"in J,K=W?J.onvoiceschanged:null,U=!1,_=()=>{if(Z)return;if(Z=!0,window.clearTimeout(N),B)J.removeEventListener("voiceschanged",$);else if(U&&J.onvoiceschanged===$)J.onvoiceschanged=K;j()},$=(D)=>{if(!B&&typeof K==="function"&&D)K.call(J,D);_()},N=window.setTimeout(_,Y);if(B)J.addEventListener("voiceschanged",$,{once:!0});else if(W)J.onvoiceschanged=$,U=!0});let X=J.getVoices();await this.emitTelemetry("pie-toolkit-tts-browser-voices-ready",{voiceCount:X.length,timedOut:X.length===0})}getServiceBundle(){return{ttsService:this.ttsService,toolCoordinator:this.toolCoordinator,highlightCoordinator:this.highlightCoordinator,elementToolStateStore:this.elementToolStateStore,catalogResolver:this.catalogResolver,toolProviderRegistry:this.toolProviderRegistry}}async getToolProvider(Q){return this.ensureProviderReady(Q)}async waitUntilReady(){if(this.assertNotDisposed(),this.isReady())return;if(this.coordinatorReadyPromise)return this.coordinatorReadyPromise;return this.coordinatorReadyPromise=(async()=>{await this.ensureStateLoaded(),this.assertNotDisposed();let Q=this.getTTSConfigFromProviders();if(Q?.enabled!==!1)await this.ensureTTSReady(Q);if(this.assertNotDisposed(),!this.coordinatorReadyNotified)this.coordinatorReadyNotified=!0,await this.hooks.onCoordinatorReady?.(this),this.assertNotDisposed(),await this.emitTelemetry("pie-toolkit-coordinator-ready",{assessmentId:this.assessmentId})})().finally(()=>{this.coordinatorReadyPromise=void 0}),this.coordinatorReadyPromise}isReady(){return this.getInitStatus().coordinator}getInitStatus(){let Q={};for(let J of this.toolProviderRegistry.getProviderIds())Q[J]=this.toolProviderRegistry.isInitialized(J);let Y=this.getTTSConfigFromProviders();return{tts:this.ttsInitialized,stateLoaded:this.stateLoaded||!this.hooks.loadToolState,coordinator:(this.stateLoaded||!this.hooks.loadToolState)&&(this.ttsInitialized||Y?.enabled===!1),providers:Q}}getTTSConfigFromProviders(){return this.config.tools?.providers?.textToSpeech}assertCanonicalToolId(Q){if(typeof Q!=="string"||Q.trim().length===0)throw Error("Tool id must be a non-empty string.");if(Q==="tts")throw Error('Tool id "tts" is no longer supported. Use "textToSpeech".');if(this.toolRegistry.getAllToolIds().length===0)return;if(!this.toolRegistry.get(Q))throw Error(`Unknown tool id "${Q}".`)}installToolContextResolvers(Q){if(!Q)return;for(let[Y,J]of Object.entries(Q)){if(J==null)continue;if(this.assertCanonicalToolId(Y),typeof J!=="function")throw Error(`Invalid tool context resolver for "${Y}": expected a function.`);this.toolContextResolvers.set(Y,J)}}setToolContextResolvers(Q){this.toolContextResolvers.clear(),this.installToolContextResolvers(Q??void 0),this.notifyToolContextResolverChange()}notifyToolContextResolverChange(){for(let Q of this.toolContextResolverChangeListeners)try{Q()}catch(Y){console.warn("[ToolkitCoordinator] Tool context resolver listener threw:",Y)}}isToolEnabled(Q){return this.assertCanonicalToolId(Q),this.config.tools?.providers?.[Q]?.enabled!==!1}getToolConfig(Q){return this.assertCanonicalToolId(Q),this.config.tools?.providers?.[Q]||null}updateToolConfig(Q,Y){this.assertCanonicalToolId(Q);let J=this.getToolConfig(Q)||{};if(!this.config.tools)this.config.tools=this.validateToolsConfig(void 0,{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolConfig",toolRegistry:this.toolRegistry});if(!this.config.tools.providers)this.config.tools.providers={};let G={...this.config.tools.providers||{},[Q]:M2(Q,J,Y)};this.config.tools=this.validateToolsConfig({...this.config.tools,providers:G},{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolConfig",toolRegistry:this.toolRegistry}),this.policyEngine.updateInputs({tools:this.config.tools}),this.emitTelemetry("pie-toolkit-tool-config-updated",{toolId:Q}),this._applyToolConfigChange(Q,J)}updateToolPlacement(Q,Y){this.updateToolsPlacement({[Q]:[...Y]})}updateToolsPlacement(Q){if(!this.config.tools)this.config.tools=this.validateToolsConfig(void 0,{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolsPlacement",toolRegistry:this.toolRegistry});let Y=this.config.tools?.placement??{section:[],item:[],passage:[]},J={section:[...Q.section??Y.section??[]],item:[...Q.item??Y.item??[]],passage:[...Q.passage??Y.passage??[]]},G=this.validateToolsConfig({...this.config.tools,placement:J},{strictness:this.config.toolConfigStrictness??"error",source:"ToolkitCoordinator.updateToolsPlacement",toolRegistry:this.toolRegistry});G.placement=J,this.config.tools=G,this.policyEngine.updateInputs({tools:this.config.tools})}decideToolPolicy(Q){return this.policyEngine.decide(Q)}decideFeaturePolicy(Q){let Y=this.policyEngine.decideFeature(Q),J=this.config.assessmentOptional!==!0||this.pnpEnforcementOverride==="on";if(!Y.assessmentBound&&J&&!this.reportedUnboundFeaturePolicy)this.reportedUnboundFeaturePolicy=!0,console.warn(`[ToolkitCoordinator] Feature policy was asked about "${Q}" with no assessment bound, so every capability will be declined for want of a profile to read. Call updateAssessment(...) with the assessment (its personalNeedsProfile, settings.districtPolicy and settings.testAdministration are what policy reads) before relying on any accommodation. Reported once per coordinator.`);return Y}onPolicyChange(Q){return this.policyEngine.onPolicyChange(Q)}onCatalogsChange(Q){return this.catalogResolver.onCatalogsChange(Q)}updateAssessment(Q){this.boundAssessment=Q,this.policyEngine.updateInputs({assessment:Q,pnpEnforcement:this.resolveEffectivePnpEnforcement()})}updateCurrentItemRef(Q){this.boundCurrentItemRef=Q,this.policyEngine.updateInputs({currentItemRef:Q,pnpEnforcement:this.resolveEffectivePnpEnforcement()})}setPnpEnforcement(Q){this.pnpEnforcementOverride=Q,this.policyEngine.updateInputs({pnpEnforcement:this.resolveEffectivePnpEnforcement()})}getPolicyInputs(){return this.policyEngine.getInputs()}registerPolicySource(Q){return this.policyEngine.registerPolicySource(Q)}registerToolContextResolver(Q,Y){if(this.assertCanonicalToolId(Q),typeof Y!=="function")throw Error(`Invalid tool context resolver for "${Q}": expected a function.`);return this.toolContextResolvers.set(Q,Y),this.notifyToolContextResolverChange(),()=>{if(this.toolContextResolvers.get(Q)!==Y)return;this.toolContextResolvers.delete(Q),this.notifyToolContextResolverChange()}}hasToolContextResolver(Q){return this.assertCanonicalToolId(Q),this.toolContextResolvers.has(Q)}resolveToolContext(Q){this.assertCanonicalToolId(Q.toolId);let Y=this.toolContextResolvers.get(Q.toolId);if(!Y)return null;let J;try{J=Y(Q)}catch(X){return console.error(`[ToolkitCoordinator] Tool context resolver for "${Q.toolId}" threw:`,X),{toolId:Q.toolId,visible:!1,params:{},reason:"Tool context resolver threw."}}if(!J)return{toolId:Q.toolId,visible:!0,params:{}};let G=J.params&&typeof J.params==="object"&&!Array.isArray(J.params)?J.params:{};return{toolId:Q.toolId,visible:J.visible!==!1,params:G,reason:typeof J.reason==="string"?J.reason:void 0}}onToolContextResolverChange(Q){return this.toolContextResolverChangeListeners.add(Q),()=>{this.toolContextResolverChangeListeners.delete(Q)}}registerToolRequestTarget(Q){return this.toolRequests.registerTarget(Q)}requestTool(Q){return this.assertCanonicalToolId(Q.toolId),this.toolRequests.request(Q)}canRequestTool(Q,Y){try{this.assertCanonicalToolId(Q)}catch{return!1}return this.toolRequests.canRequest(Q,Y)}onToolRequestTargetsChange(Q){return this.toolRequests.onTargetsChange(Q)}resolveEffectivePnpEnforcement(){if(this.pnpEnforcementOverride!==null)return this.pnpEnforcementOverride;return d7({assessment:this.boundAssessment,currentItemRef:this.boundCurrentItemRef})}resolveConfiguredPnpEnforcement(){return this.config.tools?.pnpEnforcement??null}_applyToolConfigChange(Q,Y){if(this.disposePromise!==null)return;switch(Q){case"textToSpeech":this.scheduleTTSReconfigure();break;case"answerEliminator":break;default:this._registerChangedToolProvider(Q,Y)}}_registerChangedToolProvider(Q,Y){let J=this.getProviderDescriptorTools().find((Z)=>Z.toolId===Q);if(!J)return;this.registerProviderFromTool(J);let G=(Z)=>{try{return b9(J,Z)}catch{return null}},X=G(Y),j=G(this.getToolConfig(Q)||void 0);if(!X||X===j||!this.toolProviderRegistry.has(X))return;this.toolProviderRegistry.unregister(X).catch((Z)=>{console.warn(`[ToolkitCoordinator] Failed to unregister provider "${X}":`,Z)})}scheduleTTSReconfigure(){let Q=this.ttsInitPromise,Y=Q?Q.catch(()=>{}).then(()=>this._reconfigureTTSProvider()):this._reconfigureTTSProvider();this.ttsReconfigurePromise=Y,Y.finally(()=>{if(this.ttsReconfigurePromise===Y)this.ttsReconfigurePromise=void 0}),Y.then(async()=>{if(this.disposePromise!==null)return;let J=this.getTTSConfigFromProviders();if(!this.lazyInit&&J?.enabled!==!1)await this.ensureTTSReady(J)})}async _reconfigureTTSProvider(){this.ttsInitialized=!1,this.ttsInitPromise=void 0;try{this.ttsService.stop()}catch{}if(this.toolProviderRegistry.has("tts"))await this.toolProviderRegistry.unregister("tts");if(this.disposePromise!==null)return;let Q=this.getProviderDescriptorTools().find((Y)=>Y.toolId==="textToSpeech");if(!Q)return;await this.registerProviderFromTool(Q)}}var P2=()=>{};function m8(Q){let{ttsService:Y,listenerId:J,silence:G}=Q;if(typeof Y?.onStateChange!=="function")return P2;let X=(j)=>{if(j!==w.PLAYING&&j!==w.LOADING)return;G()};return Y.onStateChange(J,X),()=>{try{Y.offStateChange?.(J,X)}catch{}}}function u8(Q){try{if(Q?.isPlaying?.())Q.pause?.()}catch{}}import{timedMediaProjectionSignature as Q4}from"@pie-players/pie-players-shared/timed-media";var p8="pie-register",g8="pie-unregister",c8="pie-item-session-changed";var d8="pie-content-loaded",l8="pie-item-player-error",i8="pie-formative-action",s8="pie-media-time-source";var L2={bubbles:!0,composed:!0,cancelable:!1};function w2(Q,Y,J={}){return new CustomEvent(Q,{detail:Y,...L2,...J})}function y9(Q,Y,J,G={}){return Q.dispatchEvent(w2(Y,J,G))}function x7(){return{phase:"idle",cohort:null,controllerResolved:!1,readinessSignals:{sectionReady:!1,interactionReady:!1,allLoadingComplete:!1,runtimeError:!1},effectiveRuntime:null,effectiveToolsConfig:null,loadingCompleteEmitted:!1,lastFrameworkError:null,itemCount:0,loadedCount:0}}function f9(Q,Y){if(Q===Y)return!0;if(!Q||!Y)return!1;return Q.sectionId===Y.sectionId&&Q.attemptId===Y.attemptId}function R2(Q){if(Q.runtimeError)return"error";if(Q.allLoadingComplete)return"ready";if(Q.interactionReady)return"interaction-ready";if(Q.sectionReady)return"loading";return"bootstrapping"}function n8(Q){let Y=Q.signals.sectionReady&&Q.signals.allLoadingComplete,J=Q.mode==="strict"?Y:Q.signals.interactionReady;return{phase:R2({...Q.signals,allLoadingComplete:Y,interactionReady:J}),interactionReady:J,allLoadingComplete:Y,reason:Q.reason}}function r8(Q){switch(Q){case"idle":return null;case"booting-section":return"composed";case"engine-ready":return"engine-ready";case"interactive":return"interactive";case"disposed":return"disposed"}}function z1(Q,Y,J,G="entered"){let X=r8(Y);if(!X)return;Q.push({kind:"stage-change",stage:X,status:G,cohort:J})}function o8(Q){let Y={...x7(),phase:"booting-section",cohort:Q.cohort,effectiveRuntime:Q.effectiveRuntime,effectiveToolsConfig:Q.effectiveToolsConfig,itemCount:Q.itemCount},J=[];return z1(J,"booting-section",Q.cohort),{state:Y,outputs:J}}function E2(Q,Y){if(Q.phase==="idle"||Q.phase==="disposed")return{state:Q,outputs:[]};let J=n8({mode:Y.mode,signals:Y.signals}),G=[],X=Q.phase,j=Q.loadingCompleteEmitted;if(X==="engine-ready"&&J.interactionReady)X="interactive",z1(G,X,Q.cohort);if(J.allLoadingComplete&&Q.cohort&&!j)j=!0,G.push({kind:"loading-complete",cohort:Q.cohort,itemCount:Y.itemCount,loadedCount:Y.loadedCount});return{state:{...Q,phase:X,readinessSignals:Y.signals,loadedCount:Y.loadedCount,itemCount:Y.itemCount,loadingCompleteEmitted:j},outputs:G}}function l7(Q,Y){switch(Y.kind){case"initialize":{if(Q.phase==="disposed")return{state:Q,outputs:[]};if(Q.phase!=="idle"){if(f9(Q.cohort,Y.cohort))return l7(Q,{kind:"update-runtime",effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig});return l7(Q,{kind:"cohort-change",cohort:Y.cohort,effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig,itemCount:Y.itemCount})}return o8({state:Q,cohort:Y.cohort,effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig,itemCount:Y.itemCount})}case"update-runtime":{if(Q.phase==="idle"||Q.phase==="disposed")return{state:Q,outputs:[]};return{state:{...Q,effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig},outputs:[]}}case"cohort-change":{if(Q.phase==="disposed")return{state:Q,outputs:[]};if(f9(Q.cohort,Y.cohort))return l7(Q,{kind:"update-runtime",effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig});let J=[];if(Q.phase!=="idle")J.push({kind:"stage-change",stage:"disposed",status:"entered",cohort:Q.cohort});let G=o8({state:Q,cohort:Y.cohort,effectiveRuntime:Y.effectiveRuntime,effectiveToolsConfig:Y.effectiveToolsConfig,itemCount:Y.itemCount});return{state:G.state,outputs:[...J,...G.outputs]}}case"section-controller-resolved":{if(Q.phase!=="booting-section")return{state:{...Q,controllerResolved:!0},outputs:[]};let J=[];return z1(J,"engine-ready",Q.cohort),{state:{...Q,phase:"engine-ready",controllerResolved:!0},outputs:J}}case"update-readiness-signals":return E2(Q,{signals:Y.signals,mode:Y.mode,loadedCount:Y.loadedCount,itemCount:Y.itemCount});case"framework-error":return{state:{...Q,lastFrameworkError:Y.error,readinessSignals:{...Q.readinessSignals,runtimeError:Y.error.recoverable===!0?Q.readinessSignals.runtimeError:!0}},outputs:[{kind:"framework-error",error:Y.error}]};case"dispose":{if(Q.phase==="disposed")return{state:Q,outputs:[]};let J=[];if(Q.phase!=="idle")z1(J,"disposed",Q.cohort);return{state:{...Q,phase:"disposed"},outputs:J}}default:{let J=Y;return{state:Q,outputs:[]}}}}class x9{state=x7();listeners=new Set;getState(){return this.state}dispatch(Q){let Y=l7(this.state,Q);if(this.state=Y.state,Y.outputs.length>0)this.fanOut(Y.outputs);return Y.outputs}subscribe(Q){this.listeners.add(Q);let Y=!0;return()=>{if(!Y)return;Y=!1,this.listeners.delete(Q)}}disposeListeners(){this.listeners.clear()}fanOut(Q){let Y=Array.from(this.listeners),J=Object.freeze(Q.slice());for(let G of Y)try{G(J)}catch(X){console.warn("[SectionEngineCore] listener failed:",X)}}}function a8(Q){let{coordinator:Y,dispatchCoreInput:J}=Q,G=0,X=null,j=null,Z=!1,B=Y.subscribeFrameworkErrors((_)=>{try{J({kind:"framework-error",error:_})}catch($){console.warn("[CoordinatorBridge] framework-error dispatch failed:",$)}});function W(){if(!j)return;try{j()}catch(_){console.warn("[CoordinatorBridge] controller unsubscribe failed:",_)}j=null}async function K(_){if(Z)return;G+=1;let $=G;X=_.cohort;let N=await Y.getOrCreateSectionController({sectionId:_.cohort.sectionId,attemptId:_.cohort.attemptId||void 0,input:{section:_.section,sectionId:_.cohort.sectionId,assessmentId:_.assessmentId,view:_.view},updateExisting:!0,createDefaultController:_.createDefaultController});if($!==G||Z)return;W(),_.onControllerResolved?.(N);let D=N.getCompositionModel;if(_.onCompositionChanged?.(D?.()),typeof N.subscribe==="function")j=N.subscribe((O)=>{if($!==G||Z)return;_.onCompositionChanged?.(D?.())});J({kind:"section-controller-resolved"})}async function U(){if(Z)return;Z=!0,G+=1,W();try{B()}catch($){console.warn("[CoordinatorBridge] framework-error unsubscribe failed:",$)}let _=X;if(X=null,_)try{await Y.disposeSectionController({sectionId:_.sectionId,attemptId:_.attemptId||void 0})}catch($){console.warn("[CoordinatorBridge] section-controller dispose failed:",$)}}return{resolveSectionController:K,dispose:U}}function t8(Q){let{runtimeId:Y,sourceCe:J}=Q,G=Q.host,X=Q.now??(()=>new Date().toISOString());function j(U){let _={stage:U.stage,status:U.status,runtimeId:Y,sectionId:U.cohort?.sectionId,attemptId:U.cohort?.attemptId?U.cohort.attemptId:void 0,timestamp:X(),sourceCe:J};G.dispatchEvent(new CustomEvent("pie-stage-change",{detail:_}))}function Z(U){let _={runtimeId:Y,sectionId:U.cohort.sectionId,attemptId:U.cohort.attemptId?U.cohort.attemptId:void 0,itemCount:U.itemCount,loadedCount:U.loadedCount,timestamp:X(),sourceCe:J};G.dispatchEvent(new CustomEvent("pie-loading-complete",{detail:_}))}function B(U){G.dispatchEvent(new CustomEvent("framework-error",{detail:U.error}))}function W(U){switch(U.kind){case"stage-change":j(U);return;case"loading-complete":Z(U);return;case"framework-error":B(U);return;default:{let _=U;return}}}function K(U){G=U}return{dispatch:W,setHost:K}}function e8(Q){let{bus:Y}=Q;function J(G){switch(G.kind){case"framework-error":Y.reportFrameworkError(G.error);return;case"stage-change":case"loading-complete":return;default:{let X=G;return}}}return{dispatch:J}}function Q6(Q={}){let Y=Q.hook;function J(X){if(!Y)return;try{Y(X)}catch(j){console.warn("[InstrumentationBridge] hook failed:",j)}}function G(X){Y=X}return{dispatch:J,setHook:G}}function Y6(){let Q=new Set;function Y(j){if(j.length===0)return;let Z=Array.from(Q),B=Object.freeze(j.slice());for(let W of Z)try{W(B)}catch(K){console.warn("[SubscriberFanout] listener failed:",K)}}function J(j){Q.add(j);let Z=!0;return()=>{if(!Z)return;Z=!1,Q.delete(j)}}function G(){Q.clear()}function X(){return Q.size}return{emit:Y,subscribe:J,dispose:G,getListenerCount:X}}class k9{core;domEventBridge;frameworkErrorBridge;instrumentationBridge;subscriberFanout;coordinatorBridge;unsubscribeCore;disposed=!1;constructor(Q){this.core=Q.core??new x9,this.domEventBridge=t8({host:Q.host,runtimeId:Q.runtimeId,sourceCe:Q.sourceCe,now:Q.now}),this.frameworkErrorBridge=e8({bus:Q.frameworkErrorBus}),this.instrumentationBridge=Q6({hook:Q.instrumentationHook}),this.subscriberFanout=Y6(),this.coordinatorBridge=Q.coordinator?a8({coordinator:Q.coordinator,dispatchCoreInput:(Y)=>this.dispatchInput(Y)}):null,this.unsubscribeCore=this.core.subscribe((Y)=>{this.routeOutputs(Y)})}getState(){return this.core.getState()}dispatchInput(Q){if(this.disposed)return[];return this.core.dispatch(Q)}subscribe(Q){return this.subscriberFanout.subscribe(Q)}setHost(Q){this.domEventBridge.setHost(Q)}setInstrumentationHook(Q){this.instrumentationBridge.setHook(Q)}resolveSectionController(Q){if(!this.coordinatorBridge)throw Error("[SectionEngineAdapter] resolveSectionController called without a coordinator.");return this.coordinatorBridge.resolveSectionController(Q)}async dispose(){if(this.disposed)return;if(this.disposed=!0,this.core.dispatch({kind:"dispose"}),this.unsubscribeCore(),this.subscriberFanout.dispose(),this.coordinatorBridge)await this.coordinatorBridge.dispose()}routeOutputs(Q){for(let Y of Q)this.routeOne(Y);this.subscriberFanout.emit(Q)}routeOne(Q){switch(Q.kind){case"stage-change":case"loading-complete":this.domEventBridge.dispatch(Q);break;case"framework-error":this.domEventBridge.dispatch(Q),this.frameworkErrorBridge.dispatch(Q);break;default:{let Y=Q;return}}this.instrumentationBridge.dispatch(Q)}}var b2={mode:"gather",role:"student"};function O1(Q,Y){return Q!==void 0?Q:Y}function S2(Q){let Y=Q.runtime??{};if(Y.onFrameworkError!==void 0)return Y.onFrameworkError;return Q.onFrameworkError}function C2(Q){let Y=Q.runtime?.tools||{},J=Y.placement||{};return{...Y,placement:{...J}}}function T2(Q){let Y=Q.runtime||{},J=Y.player?{...Y.player}:null;return{...Y,assessmentId:O1(Y.assessmentId,Q.assessmentId),playerType:Y.playerType??"iife",player:J,lazyInit:Y.lazyInit??!0,accessibility:Y.accessibility??null,coordinator:Y.coordinator??null,createSectionController:Y.createSectionController,isolation:Y.isolation??"inherit",env:Y.env??b2,toolConfigStrictness:O1(Y.toolConfigStrictness,Q.toolConfigStrictness)??"error",onFrameworkError:S2({runtime:Q.runtime,onFrameworkError:Q.onFrameworkError}),onStageChange:O1(Y.onStageChange,Q.onStageChange),onLoadingComplete:O1(Y.onLoadingComplete,Q.onLoadingComplete),tools:Q.effectiveToolsConfig}}function J6(Q,Y){let J=Q.assessmentId??"section-demo-direct",G=C2({runtime:Q.runtime}),X=T2({assessmentId:J,runtime:Q.runtime,effectiveToolsConfig:G,toolConfigStrictness:Q.toolConfigStrictness,onFrameworkError:Q.onFrameworkError,onStageChange:Q.onStageChange,onLoadingComplete:Q.onLoadingComplete}),j=Y.resolvePlayerRuntime({effectiveRuntime:X,playerType:String(X.playerType??"iife"),env:X.env??null});return{effectiveToolsConfig:G,effectiveRuntime:X,playerRuntime:j}}import{createPieLogger as f2,isGlobalDebugEnabled as x2}from"@pie-players/pie-players-shared";function y2(Q,Y){if(Q===Y)return 0;let J=Q.compareDocumentPosition(Y);if(J&Node.DOCUMENT_POSITION_PRECEDING)return 1;if(J&Node.DOCUMENT_POSITION_FOLLOWING)return-1;return 0}class I9{shellsByElement=new Map;register(Q){let Y=this.shellsByElement.get(Q.element),J={...Q,sortKey:Date.now()};if(Y&&Y.kind===J.kind&&Y.itemId===J.itemId&&Y.canonicalItemId===J.canonicalItemId)return!1;return this.shellsByElement.set(Q.element,J),!0}unregister(Q){return this.shellsByElement.delete(Q)}getOrderedShells(Q){let Y=Array.from(this.shellsByElement.values()).filter((J)=>!Q||J.kind===Q);return Y.sort((J,G)=>y2(J.element,G.element)),Y}getCanonicalIdMap(){let Q={};for(let Y of this.getOrderedShells("item")){if(!Y.itemId)continue;Q[Y.itemId]=Y.canonicalItemId||Y.itemId}return Q}clear(){this.shellsByElement.clear()}}function P1(Q="runtime"){return`${Q}-${Math.random().toString(16).slice(2)}-${Date.now()}`}var k2=f2("section-runtime-engine",()=>x2());class v9{registry=new I9;runtimeId=P1("section-engine");adapter=null;controller=null;coordinator=null;sectionId="";attemptId;unsubscribeController=null;activeInitToken=0;loadedRenderableKeys=new Set;attachHost(Q){if(this.adapter){if(this.adapter.setHost(Q.host),Q.instrumentationHook!==void 0)this.adapter.setInstrumentationHook(Q.instrumentationHook);return}this.adapter=new k9({host:Q.host,runtimeId:this.runtimeId,sourceCe:Q.sourceCe,frameworkErrorBus:Q.frameworkErrorBus,coordinator:Q.coordinator,instrumentationHook:Q.instrumentationHook,now:Q.now})}dispatchInput(Q){return this.adapter?.dispatchInput(Q)??[]}subscribe(Q){return this.adapter?.subscribe(Q)??I2}getState(){return this.adapter?.getState()??x7()}getEffectiveRuntime(Q,Y){return J6(Q,Y).effectiveRuntime}setInstrumentationHook(Q){this.adapter?.setInstrumentationHook(Q)}getRuntimeId(){return this.runtimeId}async initialize(Q){this.activeInitToken+=1;let Y=this.activeInitToken;this.coordinator=Q.coordinator,this.sectionId=Q.sectionId,this.attemptId=Q.attemptId;let J=await Q.coordinator.getOrCreateSectionController({sectionId:Q.sectionId,attemptId:Q.attemptId,input:{section:Q.section,sectionId:Q.sectionId,assessmentId:Q.assessmentId,view:Q.view},updateExisting:!0,createDefaultController:Q.createDefaultController});if(Y!==this.activeInitToken)return;this.unsubscribeController?.(),this.controller=J,this.replayRegisteredShellsIntoController(J),Q.onCompositionChanged?.(J.getCompositionModel?.()),this.unsubscribeController=J.subscribe?.((G)=>{try{Q.onControllerEvent?.(G)}catch(X){k2.warn("onControllerEvent handler threw",X)}Q.onCompositionChanged?.(J.getCompositionModel?.())})||null}replayRegisteredShellsIntoController(Q){if(!Q.handleContentRegistered)return;let Y=this.registry.getOrderedShells();if(Y.length===0)return;for(let G of Y){let X=G.canonicalItemId||G.itemId;Q.handleContentRegistered({itemId:G.itemId,canonicalItemId:X,contentKind:G.contentKind||G.kind})}let J=Date.now();for(let G of Y){let X=G.canonicalItemId||G.itemId,j=this.getLoadedKey(X,G.contentKind);if(this.loadedRenderableKeys.has(j))Q.handleContentLoaded?.({itemId:G.itemId,canonicalItemId:X,contentKind:G.contentKind||G.kind,timestamp:J})}}getLoadedKey(Q,Y){return`${Y??""}:${Q}`}register(Q){return this.registry.register(Q)}unregister(Q){return this.registry.unregister(Q)}getCompositionModel(){return this.controller?.getCompositionModel?.()??null}getCanonicalItemId(Q){return this.registry.getCanonicalIdMap()[Q]||this.controller?.getCanonicalItemId?.(Q)||Q}handleContentRegistered(Q){this.controller?.handleContentRegistered?.({itemId:Q.itemId,canonicalItemId:Q.canonicalItemId||Q.itemId,contentKind:Q.contentKind||Q.kind})}handleContentUnregistered(Q){let Y=Q.canonicalItemId||Q.itemId;this.loadedRenderableKeys.delete(this.getLoadedKey(Y,Q.contentKind)),this.controller?.handleContentUnregistered?.({itemId:Q.itemId,canonicalItemId:Y,contentKind:Q.contentKind||Q.kind})}handleContentLoaded(Q){let Y=Q.canonicalItemId||Q.itemId;this.loadedRenderableKeys.add(this.getLoadedKey(Y,Q.contentKind)),this.controller?.handleContentLoaded?.(Q)}handleItemPlayerError(Q){this.controller?.handleItemPlayerError?.(Q)}reportSectionError(Q){this.controller?.reportSectionError?.(Q)}updateItemSession(Q,Y){let J=this.getCanonicalItemId(Q);return this.controller?.updateItemSession?.(J,Y)??null}navigateToItem(Q){return this.controller?.navigateToItem?.(Q)??null}handleFormativeAction(Q){if(!Q?.itemId)return;let Y=this.getCanonicalItemId(Q.itemId);if(Q.action==="retry"){this.controller?.retryFormativeItem?.({itemId:Y});return}this.controller?.recordFormativeTry?.({itemId:Y,outcomes:Q.outcomes})}handleMediaTimeSource(Q){if(Q?.action==="detach"){this.controller?.detachMediaTimeSource?.({origin:Q.origin??"host"});return}if(!Q?.source)return;this.controller?.attachMediaTimeSource?.(Q.source,{origin:Q.origin??"host",renderableId:Q.renderableId})}requestMediaPauseForCompetingAudio(){return this.controller?.pauseMediaForCompetingAudio?.()??!0}async persist(){await this.controller?.persist?.()}async hydrate(){await this.controller?.hydrate?.()}getRegistry(){return this.registry}async dispose(){if(this.activeInitToken+=1,this.unsubscribeController?.(),this.unsubscribeController=null,this.coordinator&&this.sectionId)await this.coordinator.disposeSectionController({sectionId:this.sectionId,attemptId:this.attemptId});if(this.registry.clear(),this.loadedRenderableKeys.clear(),this.controller=null,this.coordinator=null,this.adapter){let Q=this.adapter;this.adapter=null,await Q.dispose()}}}var I2=()=>{};import{connectContextWithRetry as v2,createContext as h2}from"@pie-players/pie-context";var m2=h2(Symbol.for("pie.sectionRuntimeEngineHostContext"));function G6(Q,Y){return v2(Q,m2,Y)}var u2=(Q)=>{console.error("[pie-assessment-toolkit] onStageChange handler threw",Q)};function X6(Q,Y){if(Q.isSuppressed())return!1;Q.dispatchDomEvent(Y);let J=Q.getOnStageChange();if(J)try{J(Y)}catch(G){(Q.logHandlerError??u2)(G)}return!0}function i7(Q,Y){if(typeof Q==="function")return Q;if(Q===null)return null;return typeof Y==="function"?Y:null}function Z6(Q={}){let Y=Q.frameDeadlineMs??100,J=!1,G=null,X=null,j=null,Z=null,B=null;function W(){if(J=!1,X!==null)Z?.(X),X=null;if(j!==null)B?.(j),j=null;Z=null,B=null}function K($){if(!J)return;if($==="frame")X=null;if($==="timer")j=null;let N=G;G=null,W(),N?.()}function U($){if(G=$,J)return;J=!0;let N=globalThis,D=i7(Q.requestFrame,N.requestAnimationFrame);Z=i7(Q.cancelFrame,N.cancelAnimationFrame);let O=i7(Q.setTimer,N.setTimeout);if(B=i7(Q.clearTimer,N.clearTimeout),D){let F=D(()=>K("frame"));if(!J)return;if(X=F,O){let L=O(()=>K("timer"),Y);if(J)j=L}return}let P=i7(Q.queueMicrotaskFn,N.queueMicrotask);if(P){P(()=>K("microtask"));return}if(O){let F=O(()=>K("timer"),0);if(J)j=F;return}K("microtask")}function _(){if(!J)return;G=null,W()}return{schedule:U,cancel:_,isPending:()=>J}}function j6(){return{lastSessionEventSignatureByItemId:new Map,lastMetadataSignatureByItemId:new Map}}function B6(Q){Q.lastSessionEventSignatureByItemId.clear(),Q.lastMetadataSignatureByItemId.clear()}function q6(Q){let{state:Y,itemId:J,payload:G}=Q;if(g2(G)){let Z=c2(G);if(Y.lastMetadataSignatureByItemId.get(J)===Z)return!1;Y.lastMetadataSignatureByItemId.set(J,Z)}let X=p2(G);if(Y.lastSessionEventSignatureByItemId.get(J)===X)return!1;return Y.lastSessionEventSignatureByItemId.set(J,X),!0}function p2(Q){let Y={...Q};delete Y.timestamp,delete Y.sourceRuntimeId;try{return JSON.stringify(Y)}catch{return String(Y.itemId||"")}}function g2(Q){return Q.intent==="metadata-only"}function c2(Q){try{return JSON.stringify({itemId:Q.itemId,canonicalItemId:Q.canonicalItemId,intent:Q.intent,complete:Q.complete??null,component:Q.component??null})}catch{return String(Q.itemId||"")}}var d2=(Q,Y)=>{if(customElements.get(Q))return;try{customElements.define(Q,Y)}catch(J){if(!(J instanceof DOMException&&J.name==="NotSupportedError"||J&&typeof J==="object"&&J.name==="NotSupportedError")||!customElements.get(Q))throw J}},Y4=p9('<div class="pie-assessment-toolkit-error svelte-15pthty" role="alert" aria-live="assertive"><div class="pie-assessment-toolkit-error-title svelte-15pthty"> </div> <div class="pie-assessment-toolkit-error-message svelte-15pthty"> </div> <pre class="pie-assessment-toolkit-error-details svelte-15pthty"> </pre></div>'),J4=p9('<div class="pie-assessment-toolkit-anchor svelte-15pthty" aria-hidden="true"></div> <!>',1),G4={hash:"svelte-15pthty",code:`.pie-assessment-toolkit-anchor.svelte-15pthty {display:none;}.pie-assessment-toolkit-error.svelte-15pthty {margin:0.75rem;padding:0.75rem 1rem;border-radius:0.5rem;border:1px solid
|
|
224
|
+
color-mix(in srgb, var(--pie-incorrect-icon, #dc2626) 40%, transparent);background:color-mix(in srgb, var(--pie-incorrect-icon, #dc2626) 12%, transparent);color:var(--pie-incorrect, #7f1d1d);font-size:0.9rem;}.pie-assessment-toolkit-error-title.svelte-15pthty {font-weight:600;margin-bottom:0.25rem;}.pie-assessment-toolkit-error-message.svelte-15pthty {margin-bottom:0.5rem;}.pie-assessment-toolkit-error-details.svelte-15pthty {margin:0;white-space:pre-wrap;word-break:break-word;}`};function w6(Q,Y){V6(Y,!0),N6(Q,G4);let J=P1("toolkit"),G=new v9,X=m(null),j=new u7,Z={mode:"gather",role:"student"},B={iife:"pie-item-player",esm:"pie-item-player",preloaded:"pie-item-player",custom:""},W=f(Y,"assessmentId",7,""),K=f(Y,"section",7,null),U=f(Y,"sectionId",7,""),_=f(Y,"attemptId",7,""),$=f(Y,"env",23,()=>({})),N=f(Y,"ndsIcons",7,!1),D=f(Y,"locale",7,""),O=f(Y,"lazyInit",7,!0),P=f(Y,"toolConfigStrictness",7,"error"),F=f(Y,"tools",23,()=>({})),L=f(Y,"toolContextResolvers",7,null),C=f(Y,"enabledTools",7,""),v=f(Y,"toolRegistry",7,null),k=f(Y,"accessibility",23,()=>({})),p=f(Y,"player",7,null),R=f(Y,"playerType",7,""),g=f(Y,"coordinator",7,null),B7=f(Y,"createSectionController",7,null),q7=f(Y,"onFrameworkError",7,null),W7=f(Y,"errorRenderer",7,null),w7=f(Y,"onStageChange",7,null),s7=f(Y,"assessment",7,null),n7=f(Y,"currentItemRef",7,null),r7=f(Y,"pnpEnforcement",7,null),K7=f(Y,"isolation",7,"inherit"),k7=m(null),d=m(null),G7=m(null),g9=null,I7=null,v7=null,o7=null,h7=null,a7=null,t7=m(0),b1=m(null),o=m(null),S1=m("Unable to initialize assessment toolkit."),C1=m(h9([])),c9="",T1="",d9=null,y1=!1,l9=!1,i9=m(""),s9=null,n9=Z6(),U7=[],e7=new Map,f1=new WeakMap,r9=j6(),n=n2({sourceCe:"pie-assessment-toolkit",sourceCeShape:"toolkit",runtimeId:J,sectionId:h(()=>U()||void 0),attemptId:h(()=>_()||void 0),emit:(q)=>{X6({isSuppressed:()=>A(X)!==null,dispatchDomEvent:(V)=>V7("pie-stage-change",V),getOnStageChange:()=>w7()},q)}}),o9=m(h9(h(()=>`${U()}|${_()}`))),Q1=m(!1),t=m(!1),x1=m(!1),k1=m(!1);function R6(){if(!A(k7))return null;let q=A(k7).getRootNode();if(q&&"host"in q)return q.host;return A(k7).parentElement}let x=c(()=>R6());function V7(q,V){if(!A(x)){U7=[...U7,{name:q,detail:V}];return}y9(A(x),q,V)}b(()=>{if(!A(x))return;if(U7.length===0)return;let q=U7;U7=[],queueMicrotask(()=>{let V=A(x);if(!V){U7=[...q,...U7];return}for(let M of q)y9(V,M.name,M.detail)})});function E6(q){if(!W7())return{title:"Unable to initialize assessment toolkit.",details:q.details.length>0?q.details:[q.message]};try{let V=W7()(q)||{};return{title:typeof V.title==="string"&&V.title.trim().length>0?V.title:"Unable to initialize assessment toolkit.",details:Array.isArray(V.details)&&V.details.length>0?V.details.map((M)=>String(M)):q.details.length>0?q.details:[q.message]}}catch(V){let M=V instanceof Error&&V.message.trim().length>0?V.message:String(V||"Unknown renderer error");return{title:"Unable to initialize assessment toolkit.",details:[...q.details,`Error renderer failed: ${M}`]}}}function R7(q){let V=g1({kind:q.kind,source:q.source,error:q.error,recoverable:q.recoverable});return j.reportFrameworkError(V),V}function b6(q){if(q?.type==="timed-media-policy-degraded"){let M=q.degradations||[];j.reportFrameworkError(B1({kind:"timed-media",severity:"warning",source:"pie-assessment-toolkit",message:"A timed-media playback policy degraded to advisory: the media time source does not report the capability it needs.",details:M.map((z)=>z?.message).filter((z)=>typeof z==="string"),recoverable:!0}));return}if(q?.type!=="timed-media-invalid")return;let V=q.errors||[];j.reportFrameworkError(B1({kind:"timed-media",severity:"error",source:"pie-assessment-toolkit",message:'This section declares sectionType: "timed-media" but its timedMedia data is not deliverable; the section renders without cue behavior.',details:V.map((M)=>M?.message).filter((M)=>typeof M==="string"),recoverable:!1}))}function S6(q){if(q?.type!=="timed-media-audio-started")return;if(!A(S))return;u8(A(S).getServiceBundle().ttsService)}function C6(q){return q==="coordinator-init"||q==="runtime-init"||q==="tool-config"}function a9(q){if(!q7())return;try{q7()(q),c9=`${q.kind}|${q.source}|${q.message}`}catch(V){console.error(`[pie-framework:${q.kind}:${q.source}] framework error hook failed`,V)}}let t9=new WeakSet;b(()=>{let q=j.subscribeFrameworkErrors((V)=>{if(console.error(K0(V),V.cause),C6(V.kind)&&!t9.has(V)){let M=E6(V);E(o,V,!0),E(S1,M.title,!0),E(C1,M.details,!0)}V7("framework-error",V),a9(V)});return()=>{q()}}),b(()=>{let q=g();if(!q||A(S)!==q)return;if(typeof q.subscribeFrameworkErrors!=="function")return;return h(()=>q.subscribeFrameworkErrors((V)=>{t9.add(V),j.reportFrameworkError(V)}))}),b(()=>{let q=g(),V=v();if(!q||A(S)!==q)return;if(typeof q.adoptToolRegistry!=="function")return;h(()=>q.adoptToolRegistry(V))}),b(()=>{if(!A(o))return;let q=`${A(o).kind}|${A(o).source}|${A(o).message}`;if(c9===q)return;a9(A(o))});function T6(q){let V=5381;for(let M=0;M<q.length;M+=1)V=(V<<5)+V^q.charCodeAt(M);return(V>>>0).toString(36)}function r(q){return q&&typeof q==="object"?q:{}}function y6(q){let V=r(q.section),M=typeof V.identifier==="string"?V.identifier:"",z=typeof q.sectionId==="string"?q.sectionId:"";return M||z}function f6(q){return typeof q.currentItemIndex==="number"?q.currentItemIndex:-1}function x6(q){return(Array.isArray(q.renderables)?q.renderables:[]).map((M,z)=>{let H=r(M),I=r(H.entity),Q7=typeof I.id==="string"&&I.id||`renderable-${z}`,j1=r(I.config),p1=typeof I.version==="string"&&I.version||(typeof I.version==="number"?String(I.version):"")||(typeof j1.version==="string"?j1.version:"");return{id:Q7,version:p1}})}function k6(q){let V=r(q.itemSessionsByItemId);return Object.keys(V).sort((M,z)=>M.localeCompare(z)).map((M)=>{let z=r(V[M]),H=typeof z.id==="string"?z.id:"",I=Array.isArray(z.data)?z.data:[],Q7="";try{Q7=T6(JSON.stringify(I))}catch{Q7=String(I.length)}return{itemId:M,sessionId:H,payloadSignature:Q7}})}function I6(q){let V=r(r(q.formative).states);return Object.entries(V).map(([M,z])=>{let H=r(z),I=r(H.lastOutcome).correctness??"";return`${M}:${H.tryCount??0}:${H.revealed===!0?1:0}:${String(I)}:${String(H.revealOverride??"")}`}).sort().join("|")}function v6(q){let V=q.timedMedia;return Q4(V)}function h6(q){let V=r(q),M=x6(V).map((H)=>`${H.id}:${H.version}`).join("|"),z=k6(V).map((H)=>`${H.itemId}:${H.sessionId}:${H.payloadSignature}`).join("|");return{sectionId:y6(V),currentItemIndex:f6(V),renderableSignature:M,itemSessionSignature:z,formativeSignature:I6(V),timedMediaSignature:v6(V)}}function m6(q){let V=h6(q);return`${V.sectionId}|${V.currentItemIndex}|${V.renderableSignature}|${V.itemSessionSignature}|${V.formativeSignature}|${V.timedMediaSignature}`}function e9(q){return q==="iife"||q==="esm"||q==="preloaded"||q==="custom"}function u6(q,V){let M=q?.type,z=e9(M)?M:e9(V)?V:q?.tagName?"custom":"iife",H=q?.tagName?.trim();if(z==="custom"&&!H)return{type:"iife",tagName:B.iife,version:void 0,source:void 0,isDefault:!0};return{type:z,tagName:H||B[z],version:q?.version,source:q?.source,loaderConfig:q?.loaderConfig,loaderOptions:q?.loaderOptions,isDefault:!q&&!V}}function Q0(q){let V=q||{},M=typeof V.mode==="string"&&V.mode.trim()?V.mode.trim():Z.mode,z=typeof V.role==="string"&&V.role.trim()?V.role.trim():Z.role;return{mode:M,role:z}}function p6(q){let V=Q0(q);if(V.mode==="author")return"author";if(V.role==="instructor")return"scorer";return"candidate"}async function g6(){if(B7())return B7()();throw Error("pie-assessment-toolkit requires createSectionController when no coordinator hook provides one")}function I1(){let q=F()||{},V=L6(C());if(V.length===0)return q;let M=q.placement||{},z=Array.isArray(M.section)?M.section:null;if(z&&z.length>0)return q;return{...q,placement:{...M,section:V}}}function c6(){return A0(I1(),{strictness:P(),source:"pie-assessment-toolkit.bootstrap",toolRegistry:v()}).config}function d6(){let q="",V="";try{q=JSON.stringify(I1())}catch{q="[unserializable-tools]"}try{V=JSON.stringify(Object.entries(L()??{}).map(([M,z])=>[M,typeof z]))}catch{V="[unserializable-resolvers]"}return[W()||"",String(P()||"error"),q,V].join("|")}function Y0(q){return q==="on"||q==="off"?q:null}function l6(q,V){let M=Y0(q);if(M)return M;if(V&&typeof V==="object"){let H=V.pnpEnforcement;return Y0(typeof H==="string"?H:null)}return null}function i6(q){let V=W()||K()?.identifier||`assessment-${Math.random().toString(16).slice(2)}`;return new T9({assessmentId:V,lazyInit:O(),toolConfigStrictness:P(),deferToolConfigValidation:!0,assessmentOptional:!0,tools:q,toolRegistry:v(),toolContextResolvers:L(),accessibility:k(),frameworkErrorBus:j})}function J0(q){try{return JSON.stringify(q??null)}catch{return"[unserializable]"}}function G0(){return{signatures:{assessmentId:W()||"",toolConfigStrictness:String(P()||"error"),lazyInit:String(O()),tools:J0({...I1(),pnpEnforcement:void 0}),accessibility:J0(k())},toolRegistry:v()}}function s6(){let q=d9;if(!q)return[];let V=G0(),M=Object.keys(V.signatures).filter((z)=>V.signatures[z]!==q.signatures[z]);if(V.toolRegistry!==q.toolRegistry)M.push("toolRegistry");return M}function n6(q){if(l9)return;l9=!0,console.warn(`[pie-assessment-toolkit] ${q.join(", ")} changed after a section initialized with the coordinator this toolkit built, and that coordinator keeps the values it was built with. Set these inputs no later than the section, pass a coordinator of your own, or update this one from toolkit-ready with updateToolConfig(...) or updateToolsPlacement(...). Reported once per toolkit.`)}function Y1(){let q=A(d);if(!q)return Promise.resolve();return E(d,null),q.dispose()}function J1(q){R7({kind:"runtime-dispose",source:"pie-assessment-toolkit",error:q,recoverable:!0})}let S=c(()=>{if(K7()!=="force"&&A(G7)?.coordinator)return A(G7).coordinator;return g()||A(d)}),r6=c(()=>K()!=null);b(()=>{A(x),g(),K7(),A(G7),L(),A(r6),F(),C(),W(),P(),O(),k(),v(),h(()=>{if(!A(x))return;if(g()){if(A(d))Y1().catch(J1);I7=null;return}if(K7()!=="force"&&A(G7)?.coordinator){if(A(d))Y1().catch(J1);I7=null;return}if(A(d)){let q=s6();if(q.length>0&&y1)n6(q);else if(q.length>0&&K())Y1().catch(J1)}if(A(d)&&I7!==L()){try{A(d).setToolContextResolvers(L()),I7=L()}catch(q){R7({kind:"coordinator-init",source:"pie-assessment-toolkit",error:q})}return}if(!A(d)){let q=d6();if(T1===q)return;try{let V=c6();E(d,i6(V),!0),d9=G0(),y1=!1,I7=L(),T1="",E(o,null),E(S1,"Unable to initialize assessment toolkit."),E(C1,[],!0)}catch(V){E(d,null),T1=q,R7({kind:"coordinator-init",source:"pie-assessment-toolkit",error:V})}}})});let G1=t2(),v1=m(0);b(()=>G1.subscribe(()=>{E(v1,A(v1)+1)})),b(()=>{let q=typeof D()==="string"?D().trim():"";h(()=>{Promise.resolve(G1.setLocale(q||e2)).catch((V)=>{R7({kind:"i18n-locale-load",source:"pie-assessment-toolkit",error:V instanceof Error?V:Error(String(V))})})})});let X7=c(()=>W()||A(S)?.assessmentId||""),e=c(()=>U()||K()?.identifier||`section-${A(X7)||"default"}`),h1=c(()=>Q0($())),o6=c(()=>p6(A(h1))),E7=c(()=>u6(p(),R())),m7=c(()=>r2({player:A(E7),component:"pie-assessment-toolkit"})),X1=c(()=>{if(!A(S))return null;let q=A(S).getServiceBundle();return{toolkitCoordinator:A(S),toolCoordinator:A(S).toolCoordinator,ttsService:q.ttsService,highlightCoordinator:q.highlightCoordinator,catalogResolver:q.catalogResolver,elementToolStateStore:q.elementToolStateStore,assessmentId:A(X7),sectionId:A(e),itemPlayer:A(E7),ndsIcons:N()===!0,locale:(A(v1),G1.getLocale()),i18n:G1,reportSessionChanged:(V,M)=>{let z=G.updateItemSession(V,M);j0({itemId:V,result:z,fallbackSession:M})},reportSectionError:(V)=>{G.reportSectionError({source:"section-runtime",error:V,timestamp:Date.now()})}}}),Z1=c(()=>{if(!A(S))return null;return{runtimeId:J,coordinator:A(S)}});function a6(q){let V=m6(q);if(V===A(i9))return;E(i9,V,!0),E(t7,A(t7)+1),E(b1,q,!0),V7("composition-changed",{composition:A(b1),version:A(t7)})}function m1(q){s9=q??G.getCompositionModel(),n9.schedule(()=>{a6(s9)})}function u1(q){if(!q)return;let V=f1.get(q);if(!V)return;for(let M of V)M();f1.delete(q)}function X0(){for(let q of e7.values())u1(q.element)}function Z0(q){if(u1(q.element),!A(S))return;let V=A(S).getServiceBundle().catalogResolver;f1.set(q.element,[V.registerOwner({owner:{kind:q.kind,itemId:q.itemId,canonicalItemId:q.canonicalItemId,assessmentId:A(X7),sectionId:A(e)},entity:q.item})])}function t6(){X0();for(let q of e7.values())Z0(q)}function j0(q){let M={...q.result?.eventDetail||q.fallbackSession,itemId:q.itemId,canonicalItemId:q.canonicalItemId||q.itemId,sourceRuntimeId:J};if(!q6({state:r9,itemId:q.itemId,payload:M}))return;V7("session-changed",M)}function e6(q){if(!(q instanceof HTMLElement))return!1;return i2(q,u9)?.runtimeId===J}function A7(q){return q.detail??null}function Q3(q,V){for(let M of V)q.addEventListener(M.name,M.handler);return()=>{for(let M of V)q.removeEventListener(M.name,M.handler)}}b(()=>{if(!A(x))return;if(K7()==="force"){E(G7,null);return}return P6(A(x),(q)=>{if(q.runtimeId===J)return;E(G7,q,!0)})}),b(()=>{let q=A(x);return h(()=>{if(!q){E(X,null);return}let V=G6(q,(M)=>{if(M.engine===A(X))return;E(X,M.engine,!0)});return()=>{V(),E(X,null)}})}),b(()=>{let q=A(S);if(!q)return;return h(()=>m8({ttsService:q.getServiceBundle().ttsService,listenerId:`timed-media-audio-handoff:${J}`,silence:()=>G.requestMediaPauseForCompetingAudio()}))}),b(()=>{let q=K7()!=="force"&&A(G7)?A(G7).runtimeId:null,V=q?"inherited":"owned";if(V!==g9)g9=V,V7(V==="inherited"?"runtime-inherited":"runtime-owned",{runtimeId:J,parentRuntimeId:q})}),b(()=>{let q=A(e),V=_()||"";B6(r9)});let Y3=c(()=>A(Z1)!==null),J3=c(()=>A(X1)!==null);b(()=>{if(!A(x)||!A(Y3))return;let q=h(()=>A(Z1));if(!q)return;return h7=new W6(A(x),{context:u9,initialValue:q}),h7.connect(),a7=new K6(A(x)),a7.attach(),()=>{a7?.detach(),a7=null,h7?.disconnect(),h7=null}}),b(()=>{if(!A(Z1))return;h7?.setValue(A(Z1))}),b(()=>{if(!A(x))return;A(x).setAttribute("data-item-player-type",A(E7).type),A(x).setAttribute("data-item-player-tag",A(E7).tagName),A(x).setAttribute("data-env-mode",String(A(h1)?.mode||"")),A(x).setAttribute("data-env-role",String(A(h1)?.role||""))}),b(()=>{if(!A(x)||!A(J3))return;let q=h(()=>A(X1));if(!q)return;return v7=new W6(A(x),{context:O6,initialValue:q}),v7.connect(),o7=new K6(A(x)),o7.attach(),()=>{o7?.detach(),o7=null,v7?.disconnect(),v7=null}}),b(()=>{if(A(X1))v7?.setValue(A(X1))}),b(()=>{return A(S),A(X7),A(e),t6(),()=>{X0()}}),b(()=>{if(!A(x))return;return s2({host:A(x),instrumentationProvider:A(m7),component:"pie-assessment-toolkit",eventMap:o2,staticAttributes:{instrumentationLayer:"toolkit",assessmentId:A(X7),sectionId:A(e),attemptId:_()||void 0}})}),b(()=>{s7(),n7(),r7(),F();let q=A(S);if(!q)return;if(q!==A(d))return;h(()=>{q.setPnpEnforcement(l6(r7(),F())),q.updateAssessment(s7()),q.updateCurrentItemRef(n7())})}),b(()=>{if(!A(S))return;return A(S).subscribeTelemetry(({eventName:q,payload:V})=>{if(!a2(A(m7)))return;if(!A(m7).isReady())return;let M=q,z=new Date().toISOString(),H={...V||{},instrumentationLayer:"toolkit",assessmentId:A(X7),sectionId:A(e),attemptId:_()||void 0,component:"pie-assessment-toolkit",sourceEventName:q,timestamp:z};A(m7).trackEvent(M,H);let I=V&&typeof V.errorType==="string"?V.errorType:void 0;if(!q.endsWith("-error")&&!I)return;let Q7=V&&typeof V.message==="string"?V.message:`Toolkit telemetry error: ${q}`;A(m7).trackError(Error(Q7),{component:"pie-assessment-toolkit",errorType:I||"ToolkitTelemetryError",...H})})}),b(()=>{if(!K()||!A(S))return;let q=!1;if(A(S)===h(()=>A(d)))y1=!0;return G.initialize({coordinator:A(S),section:K(),sectionId:A(e),assessmentId:A(X7),attemptId:_()||void 0,view:A(o6),createDefaultController:g6,onCompositionChanged:(V)=>{if(q)return;m1(V)},onControllerEvent:(V)=>{if(q)return;S6(V),b6(V)}}).then(()=>{if(q)return;V7("toolkit-ready",{runtimeId:J,assessmentId:A(X7),sectionId:A(e),itemPlayer:A(E7),coordinator:A(S)}),V7("section-ready",{sectionId:A(e)}),h(()=>{E(k1,!0)})}).catch((V)=>{if(q)return;h(()=>{if(!A(t))E(t,!0),n.enter("engine-ready","skipped");n.enter("interactive","failed")}),G.reportSectionError({source:"section-runtime",error:V,timestamp:Date.now()}),R7({kind:"runtime-init",source:"pie-assessment-toolkit",error:V})}),()=>{q=!0}}),b(()=>{if(!A(x))return;let q=A(x),V=(z)=>{if(!e6(z.target))return!1;return z.stopPropagation(),!0};return Q3(q,[{name:p8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.element||!H?.itemId)return;let I=G.register(H);if(e7.set(H.element,H),Z0(H),G.handleContentRegistered(H),I)m1()}},{name:g8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.itemId)return;let I=H?.element?G.unregister(H.element):!1;if(u1(H.element),H.element)e7.delete(H.element);if(G.handleContentUnregistered(H),I)m1()}},{name:c8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.itemId)return;let I=G.updateItemSession(H.itemId,H.session);j0({itemId:H.itemId,canonicalItemId:G.getCanonicalItemId(H.itemId),result:I,fallbackSession:H.session})}},{name:d8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.itemId)return;G.handleContentLoaded({itemId:H.itemId,canonicalItemId:H.canonicalItemId,contentKind:H.contentKind,detail:H.detail,timestamp:Date.now()})}},{name:l8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.itemId)return;G.handleItemPlayerError({itemId:H.itemId,canonicalItemId:H.canonicalItemId,contentKind:H.contentKind,error:H.error,timestamp:Date.now()})}},{name:i8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.itemId)return;if(H.action!=="check"&&H.action!=="retry")return;G.handleFormativeAction({itemId:H.canonicalItemId||H.itemId,action:H.action,outcomes:H.outcomes})}},{name:s8,handler:(z)=>{if(!V(z))return;let H=A7(z);if(!H?.renderableId)return;if(H.action!=="attach"&&H.action!=="detach")return;G.handleMediaTimeSource({renderableId:H.renderableId,action:H.action,source:H.source,origin:H.origin})}}])});async function G3(){if(!A(S))throw Error("Coordinator not initialized");await A(S).waitUntilReady()}function X3(){if(!A(S))throw Error("Coordinator not initialized");return A(S).getServiceBundle()}function Z3(q){if(!A(S))throw Error("Coordinator not initialized");A(S).setHooks(q)}function j3(q){return G.navigateToItem(q)}function B3(){return G.getCompositionModel()}function q3(){return A(E7)}async function W3(){await G.persist()}async function K3(){await G.hydrate()}b(()=>{return()=>{h(()=>{if(n.getCurrent()!==null)n.enter("disposed")})}}),b(()=>{let q=`${U()}|${_()}`;h(()=>{if(q===A(o9))return;if(n.getCurrent()!==null)n.enter("disposed");n.reset({sectionId:U()||void 0,attemptId:_()||void 0}),E(o9,q),E(Q1,!1),E(t,!1),E(x1,!1),E(k1,!1)})}),b(()=>{let q=A(t)&&A(k1);h(()=>{if(!q)return;if(A(x1))return;E(x1,!0),n.enter("interactive")})}),b(()=>{let q=A(t7)>0||A(b1)!==null;h(()=>{if(!A(Q1)&&q)E(Q1,!0),n.enter("composed")})}),b(()=>{if(!A(S))return;if(!A(Q1))return;if(A(t))return;let q=A(S),V=!1;return q.waitUntilReady().then(()=>{if(V)return;h(()=>{if(A(t))return;E(t,!0),n.enter("engine-ready")})}).catch(()=>{if(V)return;h(()=>{if(A(t))return;E(t,!0),n.enter("engine-ready","failed")})}),()=>{V=!0}}),b(()=>{return()=>{n9.cancel(),G.dispose().catch((q)=>{R7({kind:"runtime-dispose",source:"pie-assessment-toolkit",error:q,recoverable:!0})}).then(()=>Y1()).catch(J1).finally(()=>{j.dispose()})}});var U3={waitUntilReady:G3,getServiceBundle:X3,setHooks:Z3,navigateToItem:j3,getCompositionModel:B3,getItemPlayerConfig:q3,persist:W3,hydrate:K3,get assessmentId(){return W()},set assessmentId(q){W(q),y()},get section(){return K()},set section(q){K(q),y()},get sectionId(){return U()},set sectionId(q){U(q),y()},get attemptId(){return _()},set attemptId(q){_(q),y()},get env(){return $()},set env(q){$(q),y()},get ndsIcons(){return N()},set ndsIcons(q){N(q),y()},get locale(){return D()},set locale(q){D(q),y()},get lazyInit(){return O()},set lazyInit(q){O(q),y()},get toolConfigStrictness(){return P()},set toolConfigStrictness(q){P(q),y()},get tools(){return F()},set tools(q){F(q),y()},get toolContextResolvers(){return L()},set toolContextResolvers(q){L(q),y()},get enabledTools(){return C()},set enabledTools(q){C(q),y()},get toolRegistry(){return v()},set toolRegistry(q){v(q),y()},get accessibility(){return k()},set accessibility(q){k(q),y()},get player(){return p()},set player(q){p(q),y()},get playerType(){return R()},set playerType(q){R(q),y()},get coordinator(){return g()},set coordinator(q){g(q),y()},get createSectionController(){return B7()},set createSectionController(q){B7(q),y()},get onFrameworkError(){return q7()},set onFrameworkError(q){q7(q),y()},get errorRenderer(){return W7()},set errorRenderer(q){W7(q),y()},get onStageChange(){return w7()},set onStageChange(q){w7(q),y()},get assessment(){return s7()},set assessment(q){s7(q),y()},get currentItemRef(){return n7()},set currentItemRef(q){n7(q),y()},get pnpEnforcement(){return r7()},set pnpEnforcement(q){r7(q),y()},get isolation(){return K7()},set isolation(q){K7(q),y()}},B0=J4(),q0=m9(B0);M6(q0,(q)=>E(k7,q),()=>A(k7));var V3=w1(q0,2);{var A3=(q)=>{var V=Y4(),M=_6(V),z=L1(M,!0),H=w1(M,2),I=L1(H,!0),Q7=w1(H,2),j1=L1(Q7,!0);U6(V),$6((p1)=>{E1(z,A(S1)),E1(I,A(o).message),E1(j1,p1)},[()=>A(C1).join(`
|
|
225
|
+
`)]),R1(q,V)},_3=(q)=>{var V=F6(),M=m9(V);D6(M,Y,"default",{},null),R1(q,V)};H6(V3,(q)=>{if(A(o)&&!A(o).recoverable)q(A3);else q(_3,-1)})}return R1(Q,B0),A6(U3)}d2("pie-assessment-toolkit",z6(w6,{assessmentId:{attribute:"assessment-id",type:"String"},section:{attribute:"section",type:"Object"},sectionId:{attribute:"section-id",type:"String"},attemptId:{attribute:"attempt-id",type:"String"},env:{attribute:"env",type:"Object"},ndsIcons:{attribute:"nds-icons",type:"Boolean"},locale:{attribute:"locale",type:"String"},lazyInit:{attribute:"lazy-init",type:"Boolean"},toolConfigStrictness:{attribute:"tool-config-strictness",type:"String"},tools:{attribute:"tools",type:"Object"},toolContextResolvers:{type:"Object"},enabledTools:{attribute:"enabled-tools",type:"String"},toolRegistry:{type:"Object"},accessibility:{type:"Object"},player:{attribute:"player",type:"Object"},playerType:{attribute:"player-type",type:"String"},coordinator:{type:"Object"},createSectionController:{type:"Object"},onFrameworkError:{type:"Object"},errorRenderer:{type:"Object"},onStageChange:{type:"Object"},assessment:{type:"Object"},currentItemRef:{type:"Object"},pnpEnforcement:{attribute:"pnp-enforcement",type:"String"},isolation:{type:"Object"}},["default"],["waitUntilReady","getServiceBundle","setHooks","navigateToItem","getCompositionModel","getItemPlayerConfig","persist","hydrate"],{mode:"open"},l2));export{w6 as default};
|