@usedocent/sdk-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,352 @@
1
+ "use strict";var Se=Object.defineProperty;var Dt=Object.getOwnPropertyDescriptor;var Lt=Object.getOwnPropertyNames;var Nt=Object.prototype.hasOwnProperty;var It=(e,n)=>{for(var t in n)Se(e,t,{get:n[t],enumerable:!0})},Ot=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of Lt(n))!Nt.call(e,r)&&r!==t&&Se(e,r,{get:()=>n[r],enumerable:!(o=Dt(n,r))||o.enumerable});return e};var Ft=e=>Ot(Se({},"__esModule",{value:!0}),e);var $n={};It($n,{CONFIDENCE:()=>q,DEFAULT_PLACEMENT:()=>ce,DEFAULT_THRESHOLD:()=>Ye,DELTA_BUDGET_BYTES:()=>yt,DESTRUCTIVE_PATTERN:()=>_t,EDGE_DARK:()=>ze,EDGE_LIGHT:()=>Z,FIRST_RUN_CAPTION:()=>at,INSET:()=>Un,MASK:()=>B,NAME_FROM_CONTENT:()=>pt,STATE_ANNOUNCEMENTS:()=>Le,accessibleName:()=>W,captureSnapshot:()=>he,containsMask:()=>J,cornerOrder:()=>ue,createCaptionPanel:()=>Ie,createDocent:()=>Ct,createLiveRegion:()=>Ne,createOverlay:()=>Je,createPresence:()=>fe,createStorage:()=>De,createTools:()=>ve,createTransport:()=>Qe,deltaBytes:()=>Ve,describeElement:()=>Q,diffSnapshots:()=>Ue,edgeForAccent:()=>ye,elementFor:()=>gn,evaluateAction:()=>Ke,implicitRole:()=>V,isInteractiveRole:()=>oe,isMasked:()=>ht,labelElements:()=>$e,labelledByTargets:()=>ge,locationAdapter:()=>je,nearestCorner:()=>Te,nodeKey:()=>bt,overlayStyles:()=>me,placementToPoint:()=>z,rectNear:()=>pe,rectsOverlap:()=>Ae,redactPII:()=>Y,relativeLuminance:()=>Xe,resolveAnchor:()=>We,resolveKeepOut:()=>Ce,safeMask:()=>Be,snapPlacement:()=>Me,startSync:()=>Ze,watchDOM:()=>Ge});module.exports=Ft($n);var Un=10,ce={kind:"corner",corner:"bottom-right"},Ht=["top-left","top-right","bottom-left","bottom-right"],le=(e,n,t,o)=>({x:e.endsWith("left")?10:n-o-10,y:e.startsWith("top")?10:t-o-10}),$t=(e,n,t)=>Math.min(t,Math.max(n,e)),Te=(e,n,t,o)=>{let r=n<o/2?"top":"bottom",l=e<t/2?"left":"right";return`${r}-${l}`},ue=(e,n,t,o)=>{let r=le(e,n,t,o);return[...Ht].sort((l,m)=>{let a=le(l,n,t,o),f=le(m,n,t,o);return Math.hypot(a.x-r.x,a.y-r.y)-Math.hypot(f.x-r.x,f.y-r.y)})},z=(e,n,t,o)=>e.kind==="corner"?le(e.corner,n,t,o):{x:e.edge==="left"?10:n-o-10,y:$t(e.y,10,t-o-10)},Ae=(e,n)=>e.x<n.x+n.width&&n.x<e.x+e.width&&e.y<n.y+n.height&&n.y<e.y+e.height,pe=(e,n,t)=>Ae({x:e.x-t,y:e.y-t,width:e.width+2*t,height:e.height+2*t},n),Ce=(e,n,t,o,r)=>{let l=f=>{let g=z(f,t,o,r),d={x:g.x,y:g.y,width:r,height:r};return n.some(b=>Ae(d,b))};if(!l(e))return e;let m=z(e,t,o,r),a=e.kind==="corner"?e.corner:Te(m.x,m.y,t,o);for(let f of ue(a,t,o,r)){let g={kind:"corner",corner:f};if(!l(g))return g}return e},Me=(e,n,t,o,r,l)=>l?{kind:"edge",edge:e<t/2?"left":"right",y:n-r/2}:{kind:"corner",corner:Te(e,n,t,o)};var Bt=new Set(["top-left","top-right","bottom-left","bottom-right"]),Ut=e=>{if(typeof e!="object"||e===null)return!1;let n=e;return n.kind==="corner"?typeof n.corner=="string"&&Bt.has(n.corner):n.kind==="edge"?(n.edge==="left"||n.edge==="right")&&typeof n.y=="number":!1},Pe=(e,n)=>{try{return e?.getItem(n)??null}catch{return null}},Re=(e,n,t)=>{try{e?.setItem(n,t)}catch{}},De=(e,n,t=window)=>{let o=()=>{try{return t.localStorage}catch{return}},r=()=>{try{return t.sessionStorage}catch{return}},l=`docent:placement:${e}:${n}`,m=`docent:seen:${e}`,a=`docent:dismissals:${e}`,f=0,g=()=>{let d=Number(Pe(r(),a));return Number.isFinite(d)&&d>0?d:f};return{loadPlacement(){let d=Pe(o(),l);if(!d)return null;try{let b=JSON.parse(d);return Ut(b)?b:null}catch{return null}},savePlacement(d){Re(o(),l,JSON.stringify(d))},hasSeen(){return Pe(r(),m)==="1"},markSeen(){Re(r(),m,"1")},dismissals:g,addDismissal(){let d=g()+1;return f=d,Re(r(),a,String(d)),d}}};var Le={dormant:"Docent is resting",listening:"Docent is listening",thinking:"Docent is thinking",speaking:"Docent is speaking",pointing:"Docent is pointing at something on the page",celebrating:"Docent marked a goal as done",muted:"Docent is muted"},Ne=e=>{let t=e.ownerDocument.createElement("div");return t.setAttribute("role","status"),t.setAttribute("aria-live","polite"),t.setAttribute("aria-atomic","true"),t.className="docent-sr-only",e.appendChild(t),{el:t,announce(o){t.textContent="",t.textContent=o}}};var at="I'm Docent. Tap if you want a hand.";var Ie=(e,n)=>{let t=e.ownerDocument,o=new Set,r=!1,l=!1,m=!1,a=t.createElement("section");a.className="docent-panel",a.hidden=!0,a.setAttribute("role","region"),a.setAttribute("aria-labelledby","docent-panel-title");let f=t.createElement("header"),g=t.createElement("h2");g.id="docent-panel-title",g.tabIndex=-1,g.textContent="Docent";let d=t.createElement("button");d.type="button",d.className="docent-iconbtn",d.setAttribute("aria-pressed","false"),d.setAttribute("aria-label","Mute Docent"),d.textContent="\u{1F508}";let b=t.createElement("button");b.type="button",b.className="docent-iconbtn",b.setAttribute("aria-label","Close"),b.textContent="\xD7";let w=t.createElement("ol");w.className="docent-transcript",w.setAttribute("aria-label","Transcript"),f.append(g,d,b),a.append(f,w),e.appendChild(a);let i=t.createElement("form");i.className="docent-composer";let c=t.createElement("input");c.type="text",c.maxLength=2e3,c.autocomplete="off",c.setAttribute("aria-label","Ask Docent"),c.placeholder="Ask Docent";let s=t.createElement("button");s.type="submit",s.className="docent-send",s.textContent="Send",i.append(c,s);let x=null;i.addEventListener("submit",h=>{h.preventDefault();let k=c.value.trim();!k||!x||(c.value="",x(k),c.focus())});let S=t.createElement("div");S.className="docent-offer",S.hidden=!0;let T=t.createElement("span");T.setAttribute("aria-live","polite");let y=t.createElement("button");y.type="button",y.className="docent-offer-yes",y.textContent="Yes, do it";let E=t.createElement("button");E.type="button",E.className="docent-offer-no",E.textContent="No",S.append(T,y,E),a.append(S,i);let L=null,M=0,I=()=>{L=null,S.hidden=!0,T.textContent=""};y.addEventListener("click",()=>{let h=L;I(),h?.()}),E.addEventListener("click",()=>{M+=1,I()});let _=h=>{l=h,d.setAttribute("aria-pressed",String(h)),d.setAttribute("aria-label",h?"Unmute Docent":"Mute Docent"),d.textContent=h?"\u{1F507}":"\u{1F508}"},H=(h=!0)=>{r&&(r=!1,a.hidden=!0,h&&a.contains(e.activeElement)&&n.returnFocusTo.focus(),n.onClose())},ee=h=>{h.key==="Escape"&&(h.stopPropagation(),H())};d.addEventListener("click",()=>{_(!l),n.onToggleMute(l)}),b.addEventListener("click",()=>H()),a.addEventListener("keydown",ee);let ae=2,te=9,u=new WeakMap,A=h=>{let k=u.get(h)?.caret;if(k)return k;let C=t.createElement("span");return C.className="docent-caret",C.setAttribute("aria-hidden","true"),C},R=h=>{let k=u.get(h);k&&(h.textContent=k.target.slice(0,k.shown),k.shown<k.target.length&&h.appendChild(k.caret),w.scrollTop=w.scrollHeight)},P=h=>{let k=u.get(h);if(!k)return;if(k.shown>=k.target.length){R(h);return}k.shown=Math.min(k.target.length,k.shown+ae),R(h);let C=setTimeout(()=>{o.delete(C),P(h)},te);o.add(C)},N=(h,k)=>{let C=u.get(h);if(C){let j=C.shown<C.target.length;C.target+=k,j||P(h);return}u.set(h,{target:k,shown:0,caret:A(h)}),P(h)};return{el:a,get isOpen(){return r},get isMuted(){return l},open(h=!0){r||(r=!0,a.hidden=!1,h&&g.focus())},close:h=>H(h),setMuted:_,addCaption:(h,k)=>{let C=t.createElement("li");return C.className="docent-caption",C.dataset.role=h,h==="docent"&&!n.reducedMotion?N(C,k):C.textContent=k,w.appendChild(C),w.scrollTop=w.scrollHeight,C},get composer(){return c},setComposer(h){x=h},streamCaption(h,k,C){if(n.reducedMotion){k.textContent=(k.textContent??"")+C;return}N(k,C)},settleCaption:h=>{let k=u.get(h);k&&(k.shown=k.target.length,h.textContent=k.target,u.delete(h),w.scrollTop=w.scrollHeight)},offer(h,k){return M>=2?!1:(L=k,T.textContent=h,S.hidden=!1,!0)},clearOffer:I,showFirstRun(){if(m)return;m=!0;let h=t.createElement("li");h.className="docent-caption",h.dataset.role="docent",h.textContent=at,w.appendChild(h)},destroy(){for(let h of o)clearTimeout(h);o.clear(),a.removeEventListener("keydown",ee),a.remove()}}};var me=`
2
+ :host {
3
+ /* Read the host's value, fall back to ours. Declaring --docent-accent here instead would set
4
+ the property ON the host element, which beats the value inherited from the page: the
5
+ documented theming hook silently did nothing, and every overlay stayed purple inside every
6
+ customer's app no matter what they set. The rules below use the internal names, so the
7
+ public --docent-* names stay purely inputs. */
8
+ --dk-accent: var(--docent-accent, #7f77dd);
9
+ --dk-radius: var(--docent-radius, 16px);
10
+ --dk-font: var(--docent-font, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif);
11
+ --dk-ink: var(--docent-ink, #130e30);
12
+ --dk-surface: var(--docent-surface, #ffffff);
13
+ --docent-ease: cubic-bezier(0.2, 0, 0, 1);
14
+ /* A drop is not a state change. --docent-ease decelerates hard, which is right for a face
15
+ changing expression and wrong for an object being put down: it spends its last 200ms
16
+ crawling the final 20px, and a mascot with visible weight reads that crawl as lag rather
17
+ than as easing. The snap curve keeps speed most of the way and settles quickly. */
18
+ --docent-snap: cubic-bezier(0.32, 0.72, 0, 1);
19
+ --docent-snap-dur: 260ms;
20
+ position: fixed;
21
+ inset: 0;
22
+ pointer-events: none;
23
+ z-index: 2147483000;
24
+ font-family: var(--dk-font);
25
+ color: var(--dk-ink);
26
+ }
27
+ .docent-dot {
28
+ position: absolute;
29
+ left: 0;
30
+ top: 0;
31
+ translate: var(--docent-x, 0px) var(--docent-y, 0px);
32
+ transition-property: translate;
33
+ transition-duration: var(--docent-snap-dur);
34
+ transition-timing-function: var(--docent-snap);
35
+ pointer-events: auto;
36
+ touch-action: none;
37
+ appearance: none;
38
+ border: 0;
39
+ padding: 0;
40
+ margin: 0;
41
+ background: transparent;
42
+ line-height: 0;
43
+ cursor: grab;
44
+ border-radius: 9999px;
45
+ }
46
+ .docent-dot[data-dragging='true'] { transition-duration: 0ms; cursor: grabbing; }
47
+ .docent-dot:active { scale: 0.96; transition-property: translate, scale; }
48
+ .docent-dot:focus-visible { outline: 3px solid var(--dk-accent); outline-offset: 2px; }
49
+ .docent-panel {
50
+ position: absolute;
51
+ width: min(360px, calc(100vw - 20px));
52
+ max-height: min(60vh, 480px);
53
+ display: flex;
54
+ flex-direction: column;
55
+ pointer-events: auto;
56
+ /* Glass, so the panel reads as sitting on the host's page rather than as a white card
57
+ dropped over it. The surface colour still comes from the host token, just at low alpha,
58
+ so a dark app gets dark glass. */
59
+ background: color-mix(in oklab, var(--dk-surface) 55%, transparent);
60
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
61
+ backdrop-filter: blur(20px) saturate(180%);
62
+ color: var(--dk-ink);
63
+ border-radius: var(--dk-radius);
64
+ /* A hairline rather than a border: enough to hold an edge against a busy page. */
65
+ border: 1px solid color-mix(in oklab, var(--dk-ink) 8%, transparent);
66
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 8px 24px rgb(0 0 0 / 0.08);
67
+ font-size: 14px;
68
+ line-height: 1.4;
69
+ }
70
+ /* Without backdrop-filter there is no glass, only a see-through panel over live text, so this
71
+ falls back to the opaque surface instead. */
72
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
73
+ .docent-panel { background: var(--dk-surface); }
74
+ }
75
+ .docent-panel[hidden] { display: none; }
76
+ .docent-panel header { display: flex; align-items: center; gap: 4px; padding: 8px 8px 8px 16px; }
77
+ .docent-panel h2 { flex: 1; margin: 0; font-size: 14px; font-weight: 600; }
78
+ .docent-panel h2:focus { outline: none; }
79
+ .docent-iconbtn {
80
+ appearance: none; border: 0; background: transparent; color: inherit; cursor: pointer;
81
+ width: 40px; height: 40px; border-radius: 9999px; display: inline-grid; place-items: center; font: inherit;
82
+ }
83
+ .docent-iconbtn:hover { background: rgb(0 0 0 / 0.06); }
84
+ .docent-iconbtn:focus-visible { outline: 2px solid var(--dk-accent); outline-offset: -2px; }
85
+ .docent-iconbtn[aria-pressed='true'] { color: var(--dk-accent); }
86
+ @media (pointer: coarse) { .docent-iconbtn { width: 44px; height: 44px; } }
87
+ .docent-transcript { list-style: none; margin: 0; padding: 0 16px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
88
+ .docent-transcript li { padding: 6px 2px; border-radius: 12px; max-width: 92%; }
89
+ /* Docent's own words sit directly on the glass. A filled bubble here would put a card inside
90
+ a card, which is the thing the glass is meant to get rid of. */
91
+ .docent-transcript li[data-role='docent'] { align-self: flex-start; }
92
+ .docent-transcript li[data-role='user'] {
93
+ padding: 8px 12px;
94
+ background: color-mix(in oklab, var(--dk-accent) 88%, transparent);
95
+ color: #fff;
96
+ align-self: flex-end;
97
+ }
98
+ /* The caret marks text still arriving, and goes when the sentence is complete. */
99
+ .docent-caret {
100
+ display: inline-block; width: 2px; height: 1em; margin-left: 2px; vertical-align: -0.15em;
101
+ background: currentColor; opacity: 0.7; animation: docent-caret-blink 1s steps(1) infinite;
102
+ }
103
+ @keyframes docent-caret-blink { 0%, 49% { opacity: 0.7; } 50%, 100% { opacity: 0; } }
104
+ .docent-sr-only {
105
+ position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
106
+ clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
107
+ }
108
+ .docent-overlay { position: absolute; inset: 0; pointer-events: none; }
109
+ .docent-overlay[hidden] { display: none; }
110
+ .docent-dim { position: absolute; inset: 0; width: 100%; height: 100%; }
111
+ .docent-dim[hidden] { display: none; }
112
+ .docent-marker {
113
+ position: absolute; left: 0; top: 0; width: 24px; height: 24px;
114
+ translate: 0 0; transition-property: translate; transition-duration: 700ms; transition-timing-function: var(--docent-ease);
115
+ }
116
+ .docent-cursor {
117
+ position: absolute; inset: 0; width: 24px; height: 24px;
118
+ fill: var(--dk-accent);
119
+ /* Derived, never configured: the edge contrasts with the host's accent, so a pale brand does
120
+ not lose its silhouette on a pale page. Computed in tools/contrast.ts. */
121
+ stroke: var(--docent-pointer-edge, #fff); stroke-width: 2.25; stroke-linejoin: round;
122
+ paint-order: stroke fill;
123
+ /* Separation from the page behind is the shadow's job; the edge separates fill from outline.
124
+ Two jobs, two devices. */
125
+ filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.28));
126
+ }
127
+ /* Mirrored about the tip, so the body swings away from the control rather than across it. */
128
+ .docent-marker[data-facing='left'] .docent-cursor { transform: scaleX(-1); transform-origin: 4px 2px; }
129
+ /* The click: two rings leaving the tip. */
130
+ .docent-pulse, .docent-pulse::after {
131
+ position: absolute; left: 4px; top: 2px; width: 14px; height: 14px; margin: -7px 0 0 -7px;
132
+ border-radius: 9999px; border: 2px solid var(--dk-accent); opacity: 0;
133
+ }
134
+ .docent-pulse { content: ''; }
135
+ .docent-pulse::after { content: ''; left: 7px; top: 7px; animation-delay: 260ms; }
136
+ .docent-marker[data-arrived] .docent-pulse,
137
+ .docent-marker[data-arrived] .docent-pulse::after {
138
+ animation: docent-click 1200ms var(--docent-ease) 3;
139
+ }
140
+ @keyframes docent-click {
141
+ from { opacity: 0.75; scale: 0.4; }
142
+ to { opacity: 0; scale: 2.2; }
143
+ }
144
+ .docent-marker[hidden] { display: none; }
145
+ .docent-composer { display: flex; gap: 6px; padding: 8px 12px 12px; }
146
+ .docent-offer {
147
+ display: flex; align-items: center; gap: 8px; padding: 8px 12px 0; font-size: 13px;
148
+ }
149
+ .docent-offer span { flex: 1; min-width: 0; }
150
+ .docent-offer button {
151
+ font: inherit; font-size: 12px; padding: 6px 10px; border-radius: 9999px; cursor: pointer;
152
+ transition-property: scale; transition-duration: 120ms;
153
+ }
154
+ .docent-offer button:active { scale: 0.96; }
155
+ .docent-offer-yes { border: 0; background: var(--dk-accent); color: #fff; font-weight: 600; }
156
+ .docent-offer-no {
157
+ border: 1px solid color-mix(in oklab, var(--dk-ink) 20%, transparent);
158
+ background: transparent; color: inherit;
159
+ }
160
+ .docent-offer[hidden] { display: none; }
161
+ .docent-composer input { flex: 1; min-width: 0; height: 40px; padding: 0 12px; border-radius: 9999px; border: 1px solid color-mix(in oklab, var(--dk-ink) 20%, transparent); background: transparent; color: inherit; font: inherit; }
162
+ .docent-composer input:focus-visible { outline: 2px solid var(--dk-accent); outline-offset: 1px; }
163
+ .docent-send { height: 40px; padding: 0 14px; border-radius: 9999px; border: 0; background: var(--dk-accent); color: #fff; font: inherit; font-weight: 600; cursor: pointer; transition-property: scale; transition-duration: 120ms; }
164
+ .docent-send:active { scale: 0.96; }
165
+ .docent-send:focus-visible { outline: 2px solid var(--dk-accent); outline-offset: 1px; }
166
+ @media (pointer: coarse) { .docent-composer input, .docent-send { height: 44px; } }
167
+ @media (prefers-reduced-motion: reduce) {
168
+ .docent-dot, .docent-panel { transition-duration: 0ms !important; }
169
+ .docent-marker { transition-duration: 0ms !important; }
170
+ /* The caret still marks unfinished text, it just stops blinking (PRD rule 6). */
171
+ .docent-caret { animation: none !important; }
172
+ /* The cursor still arrives and still points; it just does not pulse. */
173
+ .docent-pulse, .docent-pulse::after { animation: none !important; }
174
+ }
175
+ `;var Oe=e=>Math.max(0,Math.min(255,Math.round(e))),Vt=e=>{let n=Number.parseInt(e.slice(1),16),t=Oe(((n>>16&255)+255)/2),o=Oe(((n>>8&255)+255)/2),r=Oe(((n&255)+255)/2);return`#${[t,o,r].map(l=>l.toString(16).padStart(2,"0")).join("").toUpperCase()}`},ct={purple:{color:"#7F77DD",dormantColor:"#AFA9EC",ink:"#26215C",badge:"#EEEDFE",badgeStroke:"#534AB7",accent:"#D85A30"},teal:{color:"#5DCAA5",dormantColor:"#9FE1CB",ink:"#04342C",badge:"#E1F5EE",badgeStroke:"#0F6E56",accent:"#EF9F27"},coral:{color:"#F0997B",dormantColor:"#F5C4B3",ink:"#4A1B0C",badge:"#FAECE7",badgeStroke:"#993C1D",accent:"#7F77DD"},blue:{color:"#85B7EB",dormantColor:"#B5D3F3",ink:"#042C53",badge:"#E6F1FB",badgeStroke:"#185FA5",accent:"#EF9F27"},pink:{color:"#ED93B1",dormantColor:"#F5BFD1",ink:"#4B1528",badge:"#FBEAF0",badgeStroke:"#993556",accent:"#0F6E56"},slate:{color:"#B4B2A9",dormantColor:"#D3D1CB",ink:"#2C2C2A",badge:"#F1EFE8",badgeStroke:"#5F5E5A",accent:"#D85A30"}},Gt=e=>typeof e=="string"&&Object.hasOwn(ct,e),it=/^#[0-9a-fA-F]{6}$/,st=e=>{if(Gt(e))return ct[e];if(typeof e!="object"||e===null)throw new RangeError("Invalid mascot palette: not an object");let n=e;for(let o of["color","ink","badge","badgeStroke","accent"]){let r=n[o];if(typeof r!="string"||!it.test(r))throw new RangeError(`Invalid mascot palette: ${o}`)}if(n.dormantColor!==void 0&&(typeof n.dormantColor!="string"||!it.test(n.dormantColor)))throw new RangeError("Invalid mascot palette: dormantColor");let t=n;return{...t,dormantColor:t.dormantColor??Vt(t.color)}};var Yt=()=>`
176
+ <svg class="dot" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="64" height="64"
177
+ data-state="dormant" role="img" aria-label="Docent" overflow="visible">
178
+ <g class="dot__pose">
179
+ <g class="dot__extras">
180
+ <path class="dot__ripples" d="M84 36C88 44 88 52 84 60M92 30C98 42 98 54 92 66"
181
+ fill="none" stroke="var(--dot-accent)" stroke-width="2" stroke-linecap="round"/>
182
+ <g class="dot__dots" fill="var(--dot-badge-stroke)">
183
+ <circle cx="82" cy="30" r="2.5"/><circle cx="88" cy="22" r="3"/><circle cx="95" cy="13" r="3.5"/>
184
+ </g>
185
+ <g class="dot__bars">
186
+ <rect class="dot__bar" x="82" y="42" width="3" height="12" rx="1.5" fill="var(--dot-badge-stroke)"/>
187
+ <rect class="dot__bar" x="89" y="36" width="3" height="24" rx="1.5" fill="var(--dot-badge-stroke)"/>
188
+ <rect class="dot__bar" x="96" y="45" width="3" height="6" rx="1.5" fill="var(--dot-badge-stroke)"/>
189
+ </g>
190
+ <path class="dot__sparks" d="M10 18L16 24M4 34H12M86 18L80 24M92 34H84"
191
+ fill="none" stroke="var(--dot-accent)" stroke-width="2" stroke-linecap="round"/>
192
+ <g class="dot__mute-glyph" fill="var(--dot-badge-stroke)" stroke="var(--dot-badge-stroke)">
193
+ <path d="M82 44H86L91 39V57L86 52H82Z" stroke="none"/>
194
+ <path d="M95 45L101 51M101 45L95 51" fill="none" stroke-width="2" stroke-linecap="round"/>
195
+ </g>
196
+ </g>
197
+ <g class="dot__arm-wrap">
198
+ <path class="dot__arm dot__arm-outer" d="M74 46L102 34" fill="none" stroke="var(--dot-color)" stroke-width="7" stroke-linecap="round"/>
199
+ <path class="dot__arm dot__arm-core" d="M74 46L102 34" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
200
+ </g>
201
+ <rect class="dot__body" x="20" y="23" width="56" height="50" rx="22" fill="var(--dot-body-fill)"/>
202
+ <g class="dot__head">
203
+ <g class="dot__face-open">
204
+ <circle class="dot__eye-open" cx="39" cy="43" r="7" fill="#fff"/>
205
+ <circle class="dot__eye-open" cx="57" cy="43" r="7" fill="#fff"/>
206
+ <g class="dot__pupils">
207
+ <circle class="dot__pupil" cx="39" cy="43" r="3.5" fill="var(--dot-ink)"/>
208
+ <circle class="dot__pupil" cx="57" cy="43" r="3.5" fill="var(--dot-ink)"/>
209
+ </g>
210
+ </g>
211
+ <path class="dot__eye-closed" d="M34 44H44M52 44H62" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
212
+ <path class="dot__eye-happy" d="M33 45C37 40.33 41 40.33 45 45M51 45C55 40.33 59 40.33 63 45" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
213
+ <path class="dot__mouth-smile" d="M42 58C46 60.67 50 60.67 54 58" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
214
+ <path class="dot__mouth-flat" d="M43 59H53" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
215
+ <path class="dot__mouth-pursed" d="M42 60C46 58 50 58 54 60" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
216
+ <ellipse class="dot__mouth-open" cx="48" cy="59" rx="5" ry="4" fill="var(--dot-ink)"/>
217
+ <path class="dot__mouth-half" d="M44 59C48 61.67 52 61.33 56 58" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
218
+ <path class="dot__mouth-big" d="M39 56C45 62.67 51 62.67 57 56" fill="none" stroke="var(--dot-ink)" stroke-width="2.5" stroke-linecap="round"/>
219
+ </g>
220
+ <circle class="dot__badge" cx="64" cy="60" r="4" fill="var(--dot-badge)" stroke="var(--dot-badge-stroke)" stroke-width="1"/>
221
+ <path class="dot__badge-slash" d="M60.5 56.5L67.5 63.5" fill="none" stroke="var(--dot-badge-stroke)" stroke-width="1.5" stroke-linecap="round"/>
222
+ </g>
223
+ </svg>`,qt=`
224
+ /* Dot state machine. One data-state on .dot; everything else is attribute selectors. */
225
+ .dot {
226
+ --dot-body-fill: var(--dot-color);
227
+ --dot-amplitude: 0;
228
+ --dot-aim: 0deg;
229
+ --dot-pupil-x: 0px;
230
+ --dot-pupil-y: 0px;
231
+ --dot-ease: cubic-bezier(0.2, 0, 0, 1);
232
+ --dot-dur: 400ms;
233
+ display: block;
234
+ overflow: visible;
235
+ }
236
+
237
+ /* Everything hidden by default; each state turns its parts on. */
238
+ .dot__eye-closed, .dot__eye-happy, .dot__face-open,
239
+ .dot__mouth-smile, .dot__mouth-flat, .dot__mouth-pursed, .dot__mouth-open, .dot__mouth-half, .dot__mouth-big,
240
+ .dot__ripples, .dot__dots, .dot__bars, .dot__sparks, .dot__mute-glyph, .dot__badge-slash {
241
+ opacity: 0;
242
+ transition-property: opacity;
243
+ transition-duration: var(--dot-dur);
244
+ transition-timing-function: var(--dot-ease);
245
+ }
246
+
247
+ .dot__body { transition-property: fill; transition-duration: var(--dot-dur); transition-timing-function: var(--dot-ease); }
248
+
249
+ /* Pose wrapper carries the -8deg lean and the breathing bob. The lean rotates about the body
250
+ center (48,48) regardless of decorations, so transform-box is view-box, not fill-box (fill-box
251
+ would pivot on the bounding box of all children, including hidden extras). */
252
+ .dot__pose {
253
+ transform-box: view-box;
254
+ transform-origin: 48px 48px;
255
+ transition-property: transform;
256
+ transition-duration: var(--dot-dur);
257
+ transition-timing-function: var(--dot-ease);
258
+ animation: dot-breathe 3s ease-in-out infinite;
259
+ }
260
+
261
+ /* Arm scales from 0 (hidden) to 1 (pointing) from its shoulder at (74,46) and aims via --dot-aim.
262
+ transform-box is view-box here as a deliberate exception to the usual fill-box rule: the pivot
263
+ is the shoulder joint, not the arm path's own bounding box. */
264
+ .dot__arm-wrap {
265
+ transform-box: view-box;
266
+ transform-origin: 74px 46px;
267
+ transform: rotate(var(--dot-aim)) scale(0);
268
+ transition-property: transform;
269
+ transition-duration: var(--dot-dur);
270
+ transition-timing-function: var(--dot-ease);
271
+ }
272
+
273
+ /* Pupils drift toward the attention target, max 3 units of the 96 viewBox (PRD \xA713.2). */
274
+ .dot__pupils { transform: translate(var(--dot-pupil-x), var(--dot-pupil-y)); transition-property: transform; transition-duration: 200ms; }
275
+
276
+ /* Blink: scaleY 0.1 for 60ms every ~4.5s, only while eyes are open. */
277
+ .dot__face-open { transform-box: fill-box; transform-origin: 50% 50%; }
278
+ .dot:not([data-state='dormant']):not([data-state='celebrating']) .dot__face-open { animation: dot-blink 4.5s step-end infinite; }
279
+
280
+ /* ---- states ---- */
281
+ .dot[data-state='dormant'] { --dot-body-fill: var(--dot-dormant); }
282
+ .dot[data-state='dormant'] .dot__eye-closed,
283
+ .dot[data-state='dormant'] .dot__mouth-smile { opacity: 1; }
284
+ .dot[data-state='dormant'] .dot__pose { animation: none; }
285
+
286
+ .dot[data-state='listening'] .dot__face-open,
287
+ .dot[data-state='listening'] .dot__mouth-flat,
288
+ .dot[data-state='listening'] .dot__ripples { opacity: 1; }
289
+ .dot[data-state='listening'] .dot__ripples { animation: dot-ripple 1.1s ease-in-out infinite alternate; }
290
+
291
+ .dot[data-state='thinking'] .dot__face-open,
292
+ .dot[data-state='thinking'] .dot__mouth-pursed,
293
+ .dot[data-state='thinking'] .dot__dots { opacity: 1; }
294
+ .dot[data-state='thinking'] .dot__dots circle { animation: dot-float 0.9s ease-in-out infinite alternate; }
295
+ .dot[data-state='thinking'] .dot__dots circle:nth-child(2) { animation-delay: 0.3s; }
296
+ .dot[data-state='thinking'] .dot__dots circle:nth-child(3) { animation-delay: 0.6s; }
297
+
298
+ .dot[data-state='speaking'] .dot__face-open,
299
+ .dot[data-state='speaking'] .dot__mouth-open,
300
+ .dot[data-state='speaking'] .dot__bars { opacity: 1; }
301
+ .dot[data-state='speaking'] .dot__bar {
302
+ transform-box: fill-box;
303
+ transform-origin: 50% 50%;
304
+ transform: scaleY(calc(0.3 + 0.7 * var(--dot-amplitude)));
305
+ transition-property: transform;
306
+ transition-duration: 80ms;
307
+ }
308
+ /* Fallback loop when no amplitude is being driven (--dot-amplitude stays 0). */
309
+ .dot[data-state='speaking'][data-amplitude='loop'] .dot__bar { animation: dot-bars 0.6s ease-in-out infinite alternate; }
310
+ .dot[data-state='speaking'][data-amplitude='loop'] .dot__bar:nth-child(2) { animation-delay: 0.2s; }
311
+ .dot[data-state='speaking'][data-amplitude='loop'] .dot__bar:nth-child(3) { animation-delay: 0.4s; }
312
+ /* Barge-in: speaking -> listening collapses within 100ms. */
313
+ .dot[data-state='listening'] .dot__bars { transition-duration: 100ms; }
314
+
315
+ .dot[data-state='pointing'] .dot__face-open,
316
+ .dot[data-state='pointing'] .dot__mouth-half { opacity: 1; }
317
+ .dot[data-state='pointing'] .dot__pose { transform: rotate(-8deg); }
318
+ .dot[data-state='pointing'] .dot__arm-wrap { transform: rotate(var(--dot-aim)) scale(1); }
319
+
320
+ .dot[data-state='celebrating'] .dot__eye-happy,
321
+ .dot[data-state='celebrating'] .dot__mouth-big,
322
+ .dot[data-state='celebrating'] .dot__sparks { opacity: 1; }
323
+ .dot[data-state='celebrating'] .dot__sparks { animation: dot-sparks 1.2s var(--dot-ease) 1 forwards; }
324
+
325
+ .dot[data-state='muted'] .dot__face-open,
326
+ .dot[data-state='muted'] .dot__mouth-flat,
327
+ .dot[data-state='muted'] .dot__mute-glyph,
328
+ .dot[data-state='muted'] .dot__badge-slash { opacity: 1; }
329
+
330
+ /* Arrival beat: awake face, no mic indicator (PRD 13.3). */
331
+ .dot[data-quiet='true'] .dot__ripples { opacity: 0; animation: none; }
332
+
333
+ /* Dragging: 6deg lean and open eyes regardless of state (PRD 13.5). */
334
+ .dot[data-dragging='true'] .dot__pose { transform: rotate(6deg); }
335
+ .dot[data-dragging='true'] .dot__face-open { opacity: 1; }
336
+ .dot[data-dragging='true'] .dot__eye-closed,
337
+ .dot[data-dragging='true'] .dot__eye-happy { opacity: 0; }
338
+
339
+ /* ---- keyframes ---- */
340
+ @keyframes dot-breathe { 0%, 100% { translate: 0 0; } 50% { translate: 0 -2px; } }
341
+ @keyframes dot-blink { 0%, 98.6% { transform: scaleY(1); } 98.7%, 99.9% { transform: scaleY(0.1); } 100% { transform: scaleY(1); } }
342
+ @keyframes dot-ripple { from { opacity: 0.35; } to { opacity: 1; } }
343
+ @keyframes dot-float { from { translate: 0 0; } to { translate: 1px -2px; } }
344
+ @keyframes dot-bars { from { transform: scaleY(0.4); } to { transform: scaleY(1); } }
345
+ @keyframes dot-sparks { 0% { opacity: 0; scale: 0.6; } 30% { opacity: 1; scale: 1; } 100% { opacity: 0; scale: 1.15; } }
346
+
347
+ /* PRD rule 6 / 13.8: reduced motion => instant swaps, no loops. */
348
+ @media (prefers-reduced-motion: reduce) {
349
+ .dot *, .dot { animation: none !important; transition-duration: 0ms !important; }
350
+ }
351
+ `,dt="data-docent-dot",Wt=e=>{let n=e instanceof Document?e.head:e,t=n.querySelector(`style[${dt}]`);if(t)return t;let o=(e instanceof Document?e:e.ownerDocument).createElement("style");return o.setAttribute(dt,""),o.textContent=qt,n.appendChild(o),o},lt=(e,n)=>{e.style.setProperty("--dot-color",n.color),e.style.setProperty("--dot-dormant",n.dormantColor),e.style.setProperty("--dot-ink",n.ink),e.style.setProperty("--dot-badge",n.badge),e.style.setProperty("--dot-badge-stroke",n.badgeStroke),e.style.setProperty("--dot-accent",n.accent)},Kt=e=>Math.min(1,Math.max(0,Number.isFinite(e)?e:0)),Fe=(e,n={})=>{let t=e.getRootNode();Wt(t);let o=(t instanceof Document?t:t.ownerDocument).createElement("template");o.innerHTML=Yt().trim();let r=o.content.firstElementChild;e.appendChild(r);let l=n.state??"dormant";r.dataset.state=l,r.setAttribute("aria-label",n.label??"Docent"),lt(r,st(n.palette??"purple"));let m=a=>{r.setAttribute("width",String(a)),r.setAttribute("height",String(a))};return m(n.size??64),{el:r,get state(){return l},setState(a){l=a,r.dataset.state=a,a==="speaking"?r.dataset.amplitude="loop":delete r.dataset.amplitude},setPalette(a){lt(r,st(a))},setAmplitude(a){r.style.setProperty("--dot-amplitude",Kt(a).toFixed(3)),delete r.dataset.amplitude},setAim(a){r.style.setProperty("--dot-aim",`${Number.isFinite(a)?a:0}deg`)},setAttention(a,f){let g=d=>Math.min(1,Math.max(-1,Number.isFinite(d)?d:0))*3;r.style.setProperty("--dot-pupil-x",`${g(a)}px`),r.style.setProperty("--dot-pupil-y",`${g(f)}px`)},setSize:m,setQuiet(a){a?r.dataset.quiet="true":delete r.dataset.quiet},setDragging(a){a?r.dataset.dragging="true":delete r.dataset.dragging},destroy(){r.remove()}}};var jt="(max-width: 640px)",zt="(prefers-reduced-motion: reduce)",Xt=6,ut=24,Jt='input, textarea, select, [contenteditable]:not([contenteditable="false"])',He=e=>({x:e.x,y:e.y,width:e.width,height:e.height}),fe=e=>{let n=(e.mount??document.body).ownerDocument,t=n.defaultView??window,o=e.mount??n.body,r=De(e.appId,e.user?.id??"anonymous",t),l=t.matchMedia(zt).matches,m=()=>t.matchMedia(jt).matches,a=()=>m()?56:64,f=e.arrivalMs??{first:8e3,later:2e3},g=n.createElement("docent-root"),d=g.attachShadow({mode:"open"}),b=n.createElement("style");b.textContent=me,d.appendChild(b);let w=Ne(d),i=n.createElement("button");i.type="button",i.className="docent-dot",i.setAttribute("aria-label","Open Docent"),i.setAttribute("aria-expanded","false"),i.setAttribute("aria-controls","docent-panel"),d.appendChild(i);let c=(p,v)=>{let D=p(i,{...e.palette?{palette:e.palette}:p===Fe?{palette:"purple"}:{},size:a(),state:v});return D.el.setAttribute("aria-hidden","true"),D.el.removeAttribute("role"),D},s=c(e.mascot??Fe,"dormant"),x=ce,S=r.dismissals(),T=!1,y=!1,E=!1,L=!1,M,I=!1,_=Ie(d,{reducedMotion:l,returnFocusTo:i,onClose:()=>j(!0),onToggleMute:p=>et(p)});_.el.id="docent-panel",_.el.addEventListener("pointerdown",()=>{I=!0}),_.el.addEventListener("focusin",()=>{I=!0}),o.appendChild(g);let H=()=>({vw:t.innerWidth,vh:t.innerHeight}),ee=()=>Array.from(n.querySelectorAll("[data-guide-primary]")).map(p=>He(p.getBoundingClientRect())),ae=(p,v,D)=>{D||(i.dataset.dragging="true"),i.style.setProperty("--docent-x",`${p}px`),i.style.setProperty("--docent-y",`${v}px`),D||(i.offsetWidth,delete i.dataset.dragging),te(p,v)},te=(p,v)=>{let{vw:D,vh:$}=H(),F=a();v+F/2>$/2?(_.el.style.bottom=`${$-v+8}px`,_.el.style.top="auto"):(_.el.style.top=`${v+F+8}px`,_.el.style.bottom="auto"),p+F/2>D/2?(_.el.style.right=`${D-(p+F)}px`,_.el.style.left="auto"):(_.el.style.left=`${p}px`,_.el.style.right="auto")},u=p=>(p.kind==="edge"?p.edge:p.corner.endsWith("left")?"left":"right")==="left"?0:180,A=(p,v=!0)=>{let{vw:D,vh:$}=H();x=Ce(p,ee(),D,$,a());let F=z(x,D,$,a());ae(F.x,F.y,v&&!l),s.state!=="pointing"&&s.setAim(u(x))},R=()=>{s.setSize(a()),A(x,!1)},P=p=>{if(s.state===p)return;let v=s.state==="pointing";s.setState(p),w.announce(Le[p]),v&&p!=="pointing"&&s.setAim(u(x)),p==="dormant"?k():h()},N,O,ke=p=>{O={x:p.clientX,y:p.clientY},N===void 0&&(N=t.requestAnimationFrame(()=>{if(N=void 0,!O||!E)return;let v=i.getBoundingClientRect(),D=v.x+v.width/2,$=v.y+v.height/2,{vw:F,vh:G}=H();s.setAttention((O.x-D)/(F/2),(O.y-$)/(G/2))}))},h=()=>{E||(E=!0,t.addEventListener("pointermove",ke))},k=()=>{E&&(E=!1,t.removeEventListener("pointermove",ke),s.setAttention(0,0))},C=(p=!0)=>{T||(T=!0,i.setAttribute("aria-expanded","true"),i.setAttribute("aria-label","Close Docent"),_.open(p),s.setQuiet(!0),y||P("listening"))},j=(p,v=!0)=>{if(T){if(T=!1,i.setAttribute("aria-expanded","false"),i.setAttribute("aria-label","Open Docent"),_.isOpen&&_.close(v),s.setQuiet(!1),p){S=r.addDismissal();for(let D of we)D()}y||P("dormant")}},we=new Set,Ee=new Set,et=p=>{y=p,_.setMuted(p);for(let v of Ee)v(p);P(p?"muted":T?"listening":"dormant")},se=!r.hasSeen();r.markSeen(),!se&&S>=2?P("dormant"):l?(se&&(_.showFirstRun(),C(!1)),P("dormant")):(s.setQuiet(!0),se?(_.showFirstRun(),C(!1)):P("listening"),M=setTimeout(()=>{M=void 0,s.setQuiet(!1),T&&!I?j(!1,!1):!T&&!y&&P("dormant")},se?f.first:f.later));let U,ie=!1,de=!1,Mt=()=>{let{vw:p,vh:v}=H();return z(x,p,v,a())};i.addEventListener("pointerdown",p=>{if(p.button!==0)return;de=!1;let v=Mt();U={x:p.clientX,y:p.clientY,dotX:v.x,dotY:v.y,id:p.pointerId},typeof i.setPointerCapture=="function"&&i.setPointerCapture(p.pointerId)}),i.addEventListener("pointermove",p=>{if(!U||p.pointerId!==U.id)return;let v=p.clientX-U.x,D=p.clientY-U.y;!ie&&Math.hypot(v,D)<Xt||(ie||(ie=!0,s.setDragging(!0),i.dataset.dragging="true"),i.style.setProperty("--docent-x",`${U.dotX+v}px`),i.style.setProperty("--docent-y",`${U.dotY+D}px`))});let tt=p=>{if(!U||p.pointerId!==U.id)return;let v=ie;if(U=void 0,ie=!1,typeof i.releasePointerCapture=="function"&&i.hasPointerCapture?.(p.pointerId)&&i.releasePointerCapture(p.pointerId),!v)return;de=!0,s.setDragging(!1),delete i.dataset.dragging;let{vw:D,vh:$}=H(),F=a(),G=i.getBoundingClientRect(),ne=Me(G.x+G.width/2,G.y+G.height/2,D,$,F,m());A(ne,!0),r.savePlacement(x)};i.addEventListener("pointerup",tt),i.addEventListener("pointercancel",tt),i.addEventListener("click",()=>{if(de){de=!1;return}M!==void 0&&(clearTimeout(M),M=void 0,s.setQuiet(!1)),T?j(!0):C()});let nt=p=>{let v=p.target;if(!(v instanceof Element)||!v.matches(Jt)||g.contains(v))return;let D=He(v.getBoundingClientRect()),$=He(i.getBoundingClientRect());if(!pe($,D,ut))return;let{vw:F,vh:G}=H(),ne=a(),Pt=x.kind==="corner"?x.corner:"bottom-right";for(let Rt of ue(Pt,F,G,ne).slice(1)){let ot={kind:"corner",corner:Rt},rt=z(ot,F,G,ne);if(!pe({x:rt.x,y:rt.y,width:ne,height:ne},D,ut)){A(ot,!0);return}}};n.addEventListener("focusin",nt),t.addEventListener("resize",R),A(r.loadPlacement()??ce,!1);let _e={host:g,root:d,get dot(){return s},trigger:i,panel:_,get placement(){return x},get isOpen(){return T},get isMuted(){return y},get proactiveMuted(){return S>=2},open:C,close:()=>j(!0),toggle(){T?j(!0):C()},setMuted:et,onDismiss(p){return we.add(p),()=>we.delete(p)},onMuteChange(p){return Ee.add(p),()=>Ee.delete(p)},setPlacement(p,v=!0){A(p,v),r.savePlacement(x)},setState:P,setMascot(p){if(L)return;let v=s.state;s.destroy(),s=c(p,v),s.setAim(u(x))},addCaption:(p,v)=>_.addCaption(p,v),relayout:R,destroy(){L||(L=!0,M!==void 0&&clearTimeout(M),N!==void 0&&t.cancelAnimationFrame(N),k(),n.removeEventListener("focusin",nt),t.removeEventListener("resize",R),_.destroy(),s.destroy(),g.remove(),e.debug&&t.__docent?.presence===_e&&delete t.__docent)}};return e.debug&&(t.__docent={presence:_e}),_e};var Qt={button:"button",submit:"button",reset:"button",image:"button",checkbox:"checkbox",radio:"radio",range:"slider",number:"spinbutton",search:"searchbox"},Zt={button:"button",textarea:"textbox",option:"option",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",nav:"navigation",main:"main",header:"banner",footer:"contentinfo",aside:"complementary",form:"form",img:"img",table:"table",th:"columnheader",td:"cell",li:"listitem",ul:"list",ol:"list",summary:"button",dialog:"dialog"},pt=new Set(["button","link","heading","cell","columnheader","rowheader","option","tab","menuitem","listitem","summary"]),en=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","option","switch","slider","spinbutton","tab","menuitem","searchbox"]),oe=e=>en.has(e),V=e=>{let n=e.getAttribute("role")?.trim().split(/\s+/)[0];if(n)return n;let t=e.tagName.toLowerCase();if(t==="a")return e.hasAttribute("href")?"link":null;if(t==="input"){let o=(e.getAttribute("type")??"text").toLowerCase();return o==="hidden"?null:Qt[o]??"textbox"}return t==="select"?e.hasAttribute("multiple")||Number(e.getAttribute("size")??"0")>1?"listbox":"combobox":Zt[t]??null},tn=120,X=e=>e.replace(/\s+/g," ").trim().slice(0,tn),mt=e=>{let n=e.getAttribute("id");return n?e.ownerDocument.querySelector(`label[for="${n.replace(/["\\]/g,"\\$&")}"]`):null},ft=e=>e.closest("label"),$e=e=>{let n=mt(e);if(n)return[n];let t=ft(e);return t?[t]:[]},ge=e=>{let n=e.getAttribute("aria-labelledby");return n?n.split(/\s+/).map(t=>e.ownerDocument.getElementById(t)).filter(t=>t!==null):[]},nn=e=>{let n=mt(e);if(n)return X(n.textContent??"");let t=ft(e);if(t){let o=t.cloneNode(!0);return o.querySelectorAll("input, select, textarea, button").forEach(r=>r.remove()),X(o.textContent??"")}return""},W=e=>{if(e.getAttribute("aria-labelledby")){let m=ge(e).map(a=>a.textContent??"").filter(Boolean);if(m.length)return X(m.join(" "))}let t=e.getAttribute("aria-label");if(t?.trim())return X(t);let o=e.tagName.toLowerCase();if(o==="input"||o==="textarea"||o==="select"){let m=nn(e);if(m)return m}if(o==="img")return X(e.getAttribute("alt")??"");let r=V(e);if(r&&pt.has(r)){let m=X(e.textContent??"");if(m)return m}let l=e.getAttribute("title");return l?.trim()?X(l):""};var B="\u2022\u2022\u2022",on=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}(?![A-Z0-9])/gi,rn=/\b(?:\d[ -]?){12,18}\d\b/g,an=/(?<![\d-])(?:\+\d{1,3}[ -]?)?(?:\(\d{2,4}\)[ -]?)?\d{2,4}[ -]\d{3,4}(?:[ -]\d{3,4})?(?![\d-])|(?<![\d-])\+\d{7,15}\b/g,Y=e=>e.replace(on,B).replace(rn,B).replace(an,B),ht=e=>{let n=e.closest("[data-guide-mask]");if(!n)return!1;let t=e.closest("[data-guide-readable]");return!(t&&n.contains(t))},gt=e=>ht(e)||e.querySelector("[data-guide-mask]")!==null,J=e=>gt(e)||[...ge(e),...$e(e)].some(gt),Be=e=>{try{return e()}catch{return null}};var sn=400,dn=new Set(["SCRIPT","STYLE","TEMPLATE","NOSCRIPT","DOCENT-ROOT"]),ln=new Set(["heading","navigation","main","banner","contentinfo","complementary","form","dialog"]),cn=e=>{if(e.hasAttribute("hidden")||e.getAttribute("aria-hidden")==="true")return!0;let n=e.ownerDocument.defaultView;if(!n)return!1;let t=n.getComputedStyle(e);return t.display==="none"||t.visibility==="hidden"},un=(e,n,t)=>e.width>0&&e.height>0&&e.right>0&&e.bottom>0&&e.left<n&&e.top<t,bt=(e,n,t,o=0)=>{let r=e.getAttribute("data-guide");return r||`${n}|${t}|${e.tagName.toLowerCase()}#${o}`},pn=(e,n,t)=>e.hasAttribute("data-guide")?!0:n?oe(n)||t&&ln.has(n):!1,mn=e=>{let n=e.getAttribute("data-guide-allow");if(n===null)return;let t=new Set(n.split(/\s+/).filter(Boolean));return t.has("click")&&t.has("fill")?"click fill":t.has("fill")?"fill":"click"},fn=e=>{let n={};return(e.hasAttribute("disabled")||e.getAttribute("aria-disabled")==="true")&&(n.disabled=!0),e instanceof HTMLInputElement&&(e.type==="checkbox"||e.type==="radio")?n.checked=e.checked:e.hasAttribute("aria-checked")&&(n.checked=e.getAttribute("aria-checked")==="true"),e.hasAttribute("aria-expanded")&&(n.expanded=e.getAttribute("aria-expanded")==="true"),e.hasAttribute("aria-selected")&&(n.selected=e.getAttribute("aria-selected")==="true"),Object.keys(n).length?n:void 0},he=(e,n={})=>Be(()=>{let t=n.maxNodes??sn,o=n.includeLandmarks??!0,r=e.defaultView,l=r?.innerWidth??0,m=r?.innerHeight??0,a=[],f=new Map,g=!1,d=e.createTreeWalker(e.body,NodeFilter.SHOW_ELEMENT,{acceptNode:w=>{let i=w;return dn.has(i.tagName)||cn(i)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),b=d.nextNode();for(;b;){let w=V(b);if(pn(b,w,o)){let i=b.getBoundingClientRect();if(un(i,l,m)){if(a.length>=t){g=!0;break}let c=J(b),s=c?B:Y(W(b)),x=w??"generic",S=`${x}|${s}|${b.tagName.toLowerCase()}`,T=f.get(S)??0;f.set(S,T+1);let y={key:bt(b,x,s,T),role:x,name:s,tag:b.tagName.toLowerCase(),rect:{x:i.x,y:i.y,width:i.width,height:i.height}},E=b.getAttribute("data-guide");E&&(y.guide=E);let L=mn(b);L&&(y.allow=L),b.closest("[data-guide-forbid]")&&(y.forbid=!0),c&&(y.masked=!0);let M=fn(b);M&&(y.states=M),a.push(y)}}b=d.nextNode()}return{route:Y(`${e.location.pathname}${e.location.search}`),scrollY:r?.scrollY??0,viewport:{width:l,height:m},nodes:a,truncated:g,capturedAt:Date.now()}}),gn=(e,n)=>{if(e.guide)return n.querySelector(`[data-guide="${e.guide.replace(/["\\]/g,"\\$&")}"]`);let[t,o,r]=e.key.split("|"),[l,m]=(r??"").split("#"),a=0;for(let f of Array.from(n.querySelectorAll(l||"*")))if(!((V(f)??"generic")!==t||(J(f)?B:Y(W(f)))!==o)){if(a===Number(m??0))return f;a++}return null};var yt=20480,hn=(e,n)=>JSON.stringify(e)===JSON.stringify(n),Ue=(e,n)=>{let t=new Map((e?.nodes??[]).map(a=>[a.key,a])),o=[],r=[],l=new Set;for(let a of n.nodes){l.add(a.key);let f=t.get(a.key);f?hn(f,a)||r.push(a):o.push(a)}let m=[...t.keys()].filter(a=>!l.has(a));return{added:o,removed:m,changed:r,route:n.route,scrollY:n.scrollY}},Ve=e=>new TextEncoder().encode(JSON.stringify(e)).length;var bn=["class","style","hidden","disabled","checked","aria-hidden","aria-expanded","aria-checked","aria-selected","aria-disabled","aria-label","data-guide","data-guide-allow","data-guide-forbid","data-guide-mask"],yn=e=>!!(e.nodeType===Node.ELEMENT_NODE?e:e.parentElement)?.closest("docent-root"),Ge=(e,n,t={})=>{let o=t.debounceMs??150,r,l=new MutationObserver(m=>{m.every(a=>yn(a.target))||(r!==void 0&&clearTimeout(r),r=setTimeout(()=>{r=void 0,n()},o))});return l.observe(e.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:bn,characterData:!0}),()=>{l.disconnect(),r!==void 0&&clearTimeout(r)}};var q={guide:1,roleNameExact:.9,roleNameContains:.7,text:.6,position:.4},Ye=.6,xn=120,be=e=>e.replace(/\s+/g," ").trim().toLowerCase(),wt=e=>{if(e.closest("docent-root")||e.hasAttribute("hidden")||e.getAttribute("aria-hidden")==="true")return!1;let n=(e.ownerDocument.defaultView??window).getComputedStyle(e);if(n.visibility==="hidden"||n.display==="none")return!1;let t=e.getBoundingClientRect();return t.width>0&&t.height>0},qe=e=>Array.from(e.body.querySelectorAll("*")).filter(wt),Et=e=>J(e)?B:Y(W(e)),vn={button:"button",link:"link",textbox:"text field",searchbox:"search field",checkbox:"checkbox",radio:"option",combobox:"dropdown",listbox:"list",switch:"switch",slider:"slider",spinbutton:"number field",tab:"tab",menuitem:"menu item",heading:"heading",img:"image"},kn=e=>{let n=e.ownerDocument.defaultView,t=e.getBoundingClientRect(),o=n?.innerWidth??1,r=n?.innerHeight??1,l=t.x+t.width/2,m=t.y+t.height/2,a=m<r/3?"top":m>2*r/3?"bottom":"middle",f=l<o/3?"left":l>2*o/3?"right":"center";return a==="middle"&&f==="center"?"the middle":`the ${a} ${f}`.replace(" center","").replace("middle ","")},Q=e=>{let n=V(e)??"element",t=vn[n]??n,o=Et(e);return o&&o!==B?`the "${o}" ${t}`:`a ${t} near ${kn(e)}`},xt=(e,n)=>{let t=e.startsWith("#")?e.slice(1):e;if(!t)return null;let o=n.querySelector(`[data-guide="${t.replace(/["\\]/g,"\\$&")}"]`);return o&&wt(o)?o:null},vt=(e,n,t)=>{let o=be(n),r=null;for(let l of qe(t)){let m=V(l);if(!m||(e?m!==e:!oe(m)))continue;let a=be(Et(l));if(!(!a||a===B)){if(a===o)return{el:l,confidence:q.roleNameExact,method:"role-name",describe:Q(l)};!r&&a.includes(o)&&(r=l)}}return r?{el:r,confidence:q.roleNameContains,method:"role-name",describe:Q(r)}:null},kt=(e,n)=>{let t=be(e),o=null;for(let r of qe(n))r.children.length>0&&!V(r)||J(r)||be(r.textContent??"").includes(t)&&(!o||(r.textContent?.length??0)<(o.textContent?.length??0))&&(o=r);return o?{el:o,confidence:q.text,method:"text",describe:Q(o)}:null},wn=(e,n)=>{let t=null;for(let o of qe(n)){let r=V(o);if(!r||!oe(r))continue;let l=o.getBoundingClientRect(),m=Math.hypot(l.x+l.width/2-e.x,l.y+l.height/2-e.y);m<=xn&&(!t||m<t.d)&&(t={el:o,d:m})}return t?{el:t.el,confidence:q.position,method:"position",describe:Q(t.el)}:null},We=(e,n)=>{if(typeof e=="string"){let t=xt(e,n);return t?{el:t,confidence:q.guide,method:"guide",describe:Q(t)}:vt(void 0,e,n)??kt(e,n)}if(e.guide){let t=xt(e.guide,n);if(t)return{el:t,confidence:q.guide,method:"guide",describe:Q(t)}}if(e.name){let t=vt(e.role,e.name,n);if(t)return t}if(e.text){let t=kt(e.text,n);if(t)return t}return e.near?wn(e.near,n):null};var _t=/\b(buy|pay|purchase|checkout|order now|subscribe|upgrade|delete|remove|destroy|erase|wipe|cancel (subscription|account|plan)|unsubscribe|transfer|withdraw|send money|confirm purchase)\b/i,En=new Set(["checkbox","radio","button","submit","reset","image","file","hidden","range","color"]),_n=e=>{let n=e.tagName.toLowerCase();if(n==="input"){let t=(e.getAttribute("type")??"text").toLowerCase();return t==="submit"||t==="image"}if(n==="button"){let t=e.getAttribute("type");return(t&&t.trim()?t:"submit").toLowerCase()!=="submit"?!1:t!==null&&t.trim()!==""?!0:e.form!==null}return!1},Sn=e=>{let n=e.tagName.toLowerCase();if(n==="textarea")return!0;if(n==="input")return!En.has((e.getAttribute("type")??"text").toLowerCase());let t=e.getAttribute("contenteditable");return t!==null&&t!=="false"},Tn=(e,n)=>{let t=e.getAttribute("data-guide-allow");return t===null?!1:t.split(/\s+/).includes(n)},Ke=(e,n,t)=>{if(e.closest("docent-root"))return{allowed:!1,reason:"forbidden"};if(e.closest("[data-guide-forbid]"))return{allowed:!1,reason:"forbidden"};if(n==="click"){if(_n(e))return{allowed:!1,reason:"forbidden"};let o=`${W(e)} ${e.textContent??""}`;if(_t.test(o))return{allowed:!1,reason:"forbidden"}}return n==="fill"&&!Sn(e)?{allowed:!1,reason:"unsupported"}:Tn(e,n)?t.userRequested?{allowed:!0}:{allowed:!1,reason:"not_requested"}:{allowed:!1,reason:"not_allowlisted"}};var je=e=>({navigate(n){e.history.pushState({},"",n),e.dispatchEvent(new PopStateEvent("popstate"))},currentPath(){return`${e.location.pathname}${e.location.search}`}});var ze="#130e30",Z="#ffffff",Xe=(e,n,t)=>{let o=r=>r<=.03928?r/12.92:((r+.055)/1.055)**2.4;return .2126*o(e)+.7152*o(n)+.0722*o(t)},ye=e=>{let n=/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/i.exec(e);if(!n)return Z;let[t,o,r]=[Number(n[1]),Number(n[2]),Number(n[3])];return[t,o,r].every(l=>Number.isFinite(l))&&Xe(t/255,o/255,r/255)>.5?ze:Z};var xe=8,An=12,St=4,Tt=2,K="http://www.w3.org/2000/svg",Cn="M4 2.4 L4 16.8 L7.9 13.4 L10.2 18.6 L12.6 17.5 L10.4 12.6 L15.6 12.6 Z",Je=(e,n)=>{let t=e.ownerDocument,o=t.createElement("div");o.className="docent-overlay",o.setAttribute("aria-hidden","true"),o.hidden=!0;let r=t.createElementNS(K,"svg");r.setAttribute("class","docent-dim");let l=t.createElementNS(K,"defs"),m=t.createElementNS(K,"mask");m.setAttribute("id","docent-hole");let a=t.createElementNS(K,"rect");a.setAttribute("width","100%"),a.setAttribute("height","100%"),a.setAttribute("fill","#fff");let f=t.createElementNS(K,"rect");f.setAttribute("fill","#000"),f.setAttribute("rx",String(An)),m.append(a,f),l.appendChild(m);let g=t.createElementNS(K,"rect");g.setAttribute("width","100%"),g.setAttribute("height","100%"),g.setAttribute("fill","rgb(0 0 0 / 0.45)"),g.setAttribute("mask","url(#docent-hole)"),r.append(l,g),r.setAttribute("hidden","");let d=t.createElement("div");d.className="docent-marker",d.hidden=!0;let b=t.createElementNS(K,"svg");b.setAttribute("viewBox","0 0 24 24"),b.setAttribute("class","docent-cursor"),b.setAttribute("aria-hidden","true");let w=t.createElementNS(K,"path");w.setAttribute("d",Cn),b.appendChild(w);let i=t.createElement("span");i.className="docent-pulse",d.append(i,b),n.reducedMotion&&(d.style.transitionDuration="0ms"),o.append(r,d),e.appendChild(o);let c,s=()=>{let y=t.defaultView;if(!y)return;d.style.color="var(--docent-accent, #7f77dd)";let E=y.getComputedStyle(d).color;d.style.setProperty("--docent-pointer-edge",E?ye(E):Z)},x,S=y=>{if(x||!t.defaultView)return;let L=()=>y();t.addEventListener("pointerdown",L,!0),x=()=>{t.removeEventListener("pointerdown",L,!0),x=void 0}},T=(y,E)=>{let L=E.x+E.width/2,M=E.y+E.height/2,I=y.x-L,_=y.y-M;return Math.abs(I)*E.height>Math.abs(_)*E.width?{x:I>0?E.right:E.left,y:M}:{x:L,y:_>0?E.bottom:E.top}};return{spotlight(y){S(()=>this.clear()),o.hidden=!1,r.removeAttribute("hidden"),f.setAttribute("x",String(y.x-xe)),f.setAttribute("y",String(y.y-xe)),f.setAttribute("width",String(y.width+2*xe)),f.setAttribute("height",String(y.height+2*xe))},point(y,E){S(()=>this.clear()),s(),o.hidden=!1,d.hidden=!1,d.style.transitionDuration="0ms",d.style.translate=`${y.x-St}px ${y.y-Tt}px`;let L=T(y,E);d.dataset.facing=L.x<=E.x+E.width/2?"left":"right";let M=t.defaultView;c!==void 0&&M&&typeof M.cancelAnimationFrame=="function"&&(M.cancelAnimationFrame(c),c=void 0);let I=()=>{c=void 0,d.style.transitionDuration=n.reducedMotion?"0ms":"700ms",d.style.translate=`${L.x-St}px ${L.y-Tt}px`,d.dataset.arrived="",i.getAnimations?.().forEach(_=>{_.cancel(),_.play()})};M&&typeof M.requestAnimationFrame=="function"?c=M.requestAnimationFrame(I):I()},clear(){x?.(),o.hidden=!0,r.setAttribute("hidden",""),d.hidden=!0},destroy(){x?.();let y=t.defaultView;c!==void 0&&y&&typeof y.cancelAnimationFrame=="function"&&(y.cancelAnimationFrame(c),c=void 0),o.remove()}}};var At=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,Mn=(e,n)=>{if(!(e.type==="email"||e.inputMode==="email")||At.test(n.trim()))return n;let r=n.trim().replace(/\s+at\s+/gi,"@").replace(/\s+dot\s+/gi,".").replace(/\s+underscore\s+/gi,"_").replace(/\s+dash\s+|\s+hyphen\s+/gi,"-").replace(/\s+/g,"").toLowerCase();return At.test(r)?r:n},Pn=(e,n)=>e==="fill"?`Fill in ${n} for you?`:`Click ${n} for you?`,Rn=(e,n)=>n.el.getAttribute("data-guide")??(typeof e=="string"?e:e.guide??e.name??e.text??n.describe),ve=e=>{let{presence:n}=e,t=e.doc??n.host.ownerDocument,o=t.defaultView??window,r=e.router??je(o),l=e.threshold??Ye,m=o.matchMedia("(prefers-reduced-motion: reduce)").matches,a=Je(n.root,{reducedMotion:m}),f=!1,g=(i,c=l)=>{let s=We(i,t);return s?s.confidence<c?{fail:{ok:!1,reason:"low_confidence",describe:s.describe}}:{res:s}:{fail:{ok:!1,reason:"not_found"}}},d=()=>{let i=n.trigger.getBoundingClientRect();return{x:i.x+i.width/2,y:i.y+i.height/2}},b=i=>{let c=d(),s=Math.atan2(i.y+i.height/2-c.y,i.x+i.width/2-c.x)*180/Math.PI;n.dot.setAim(s),n.isMuted||n.setState("pointing"),f=!0},w=(i,c)=>({ok:!0,anchor:Rn(i,c),confidence:c.confidence});return{spotlight(i){let c=g(i);if("fail"in c)return c.fail;let s=c.res.el.getBoundingClientRect();return a.spotlight(s),a.point(d(),s),b(s),w(i,c.res)},point(i){let c=g(i);if("fail"in c)return c.fail;let s=c.res.el.getBoundingClientRect();return a.point(d(),s),b(s),w(i,c.res)},scroll_to(i){let c=g(i);return"fail"in c?c.fail:(c.res.el.scrollIntoView({block:"center",behavior:m?"auto":"smooth"}),w(i,c.res))},async navigate(i){try{return await r.navigate(i),{ok:!0,anchor:i,confidence:1}}catch{return{ok:!1,reason:"navigation_failed"}}},act(i,c,s){let x=g(i,Math.max(l,q.text));if("fail"in x)return x.fail;let S=x.res.el,T=Ke(S,c,{userRequested:s.userRequested});if(!T.allowed){if(T.reason==="not_requested"){let y=Pn(c,x.res.describe);n.panel.offer(y,()=>{this.act(i,c,{...s,userRequested:!0})})}return{ok:!1,reason:T.reason}}if(c==="click")S.click();else{let y=Mn(S,s.value??"");S instanceof HTMLInputElement||S instanceof HTMLTextAreaElement?S.value=y:S.textContent=y,S.dispatchEvent(new Event("input",{bubbles:!0})),S.dispatchEvent(new Event("change",{bubbles:!0}))}return w(i,x.res)},clear(){n.panel.clearOffer(),a.clear(),f&&(f=!1,n.dot.setAim(0),n.setState(n.isMuted?"muted":n.isOpen?"listening":"dormant"))},destroy(){a.destroy()}}};var Dn=[500,1e3,2e3,5e3],Qe=(e,n={})=>{let t=n.WebSocketImpl??WebSocket,o=n.backoffMs??Dn,r=n.queueLimit??50,l=new Set,m=[],a=null,f=0,g=!1,d,b=c=>{for(m.push(c);m.length>r;){let s=m.findIndex(x=>x.type==="delta");m.splice(s>=0?s:0,1)}},w=()=>{if(!(!a||a.readyState!==t.OPEN))for(;m.length;)a.send(JSON.stringify(m.shift()))},i=()=>{if(g)return;let c=new t(e);a=c,c.addEventListener("open",()=>w()),c.addEventListener("message",s=>{let x;try{x=JSON.parse(typeof s.data=="string"?s.data:"")}catch{return}if(!x||typeof x!="object"||typeof x.type!="string")return;let S=x;S.type==="ready"&&(f=0);for(let T of l)T(S)}),c.addEventListener("close",()=>{if(a!==c||(a=null,g))return;let s=o[Math.min(f,o.length-1)]??5e3;f++,d=setTimeout(i,s)})};return i(),{send(c){b(c),w()},onFrame(c){return l.add(c),()=>l.delete(c)},get connected(){return!!a&&a.readyState===t.OPEN},close(){g=!0,d!==void 0&&clearTimeout(d),a?.close(),a=null}}};var Ze=(e,n,t={})=>{let o=null,r=()=>{let g=he(e);g&&(o=g,n.send({type:"snapshot",snapshot:g}))},l=()=>{let g=he(e);if(!g)return;let d=Ue(o,g);d.added.length+d.removed.length+d.changed.length===0&&d.route===o?.route&&d.scrollY===o?.scrollY||(Ve(d)<=20480?n.send({type:"delta",delta:d}):n.send({type:"snapshot",snapshot:g}),o=g)};r();let m=Ge(e,l,{debounceMs:t.debounceMs??150}),a=e.defaultView;a?.addEventListener("popstate",l);let f=n.onFrame(g=>{g.type==="ready"&&r()});return()=>{m(),a?.removeEventListener("popstate",l),f()}};var Ln=2e4,Nn=1200,In=6e3,Ct=e=>{let n=e.fetchImpl??fetch,t=fe({appId:e.appId,user:{id:e.user.id},...e.debug?{debug:!0}:{},...e.presence??{}}),o=ve({presence:t,...e.router?{router:e.router}:{}}),r=new Set,l=u=>{for(let A of r)A(u)},m=null,a="",f=null,g=null,d=null,b=null,w=!1,i,c,s=null,x=()=>{d||t.setState(t.isMuted?"muted":t.isOpen?"listening":"dormant")},S=()=>{c!==void 0&&clearTimeout(c),c=void 0,o.clear()},T=u=>f?.send(u),y=async u=>{try{switch(u.tool){case"spotlight":return o.spotlight(u.anchor);case"point":return o.point(u.anchor);case"scroll_to":return o.scroll_to(u.anchor);case"navigate":return await o.navigate(u.route);case"act":return o.act(u.anchor,u.action,{userRequested:u.userRequested,...u.value!==void 0?{value:u.value}:{}})}}catch{return{ok:!1,reason:"unsupported",describe:"client error"}}},E=u=>{switch(u.type){case"ready":return;case"text_delta":{if(!s||s.turnId!==u.turnId)return;s.caption||(s.caption=t.addCaption("docent",""),t.setState("speaking")),t.panel.streamCaption("docent",s.caption,u.text),s.text+=u.text;return}case"tool_call":y(u.call).then(A=>T({type:"tool_result",callId:u.callId,result:A}));return;case"turn_end":{s&&s.turnId===u.turnId&&(clearTimeout(s.timer),s.caption&&t.panel.settleCaption(s.caption),s.resolve(s.text),s=null),c!==void 0&&clearTimeout(c),c=setTimeout(()=>{c=void 0,o.clear()},In),x();return}case"goal_done":{t.setState("celebrating"),i!==void 0&&clearTimeout(i),i=setTimeout(x,Nn),l({type:"goal_done",goalKey:u.goalKey});return}case"open_docs":{let A=t.addCaption("docent","");if(!On(u.url)){A.textContent=u.title??"I have a link for that, but it did not look safe to open.";return}let R=A.ownerDocument.createElement("a");R.href=u.url,R.target="_blank",R.rel="noopener noreferrer",R.textContent=u.title??u.url,A.append("Here are the docs: ",R),l({type:"open_docs",url:u.url,...u.title?{title:u.title}:{}});return}case"handoff":t.addCaption("docent","I've passed this to support."),l({type:"handoff",reason:u.reason,route:u.route,transcript:u.transcript});return;case"error":{if(s!==null&&(u.turnId===void 0||u.turnId===s.turnId)&&u.code!=="bad_frame"){let R=s;clearTimeout(R.timer),s=null,t.addCaption("docent",u.message),x(),R.reject(new Error(u.code))}l({type:"error",code:u.code,message:u.message});return}}},M=(async()=>{let u=t.host.ownerDocument,A=u.defaultView,R=A?Y(A.location.pathname+A.location.search):"/",P;try{P=await n(`${e.apiUrl}/v1/sessions`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({appId:e.appId,publishableKey:e.publishableKey,user:e.user,...e.userToken?{userToken:e.userToken}:{},route:R,voice:!1})})}catch(O){l({type:"error",code:"mint_failed",message:String(O)});return}if(!P.ok){l({type:"error",code:"mint_failed",message:`HTTP ${P.status}`});return}let N=await P.json();w||(N.presence&&e.loadPresence&&!e.presence?.mascot&&e.loadPresence(N.presence).then(O=>{w||t.setMascot(O)}).catch(O=>{l({type:"error",code:"presence_failed",message:String(O)})}),m=N.sessionId,a=new URL(N.wsUrl).searchParams.get("t")??"",f=Qe(N.wsUrl,e.WebSocketImpl?{WebSocketImpl:e.WebSocketImpl}:{}),f.onFrame(E),g=Ze(u,f))})(),I=async u=>(f||await M,new Promise((A,R)=>{if(!f)return t.addCaption("user",u),t.addCaption("docent","I cannot reach the guide service right now."),R(new Error("no_session"));if(s)return R(new Error("busy"));let P=crypto.randomUUID();S(),t.addCaption("user",u),t.setState("thinking");let N=setTimeout(()=>{s?.turnId===P&&(s=null,x(),R(new Error("timeout")))},Ln);s={turnId:P,caption:null,text:"",resolve:A,reject:R,timer:N},T({type:"user_text",turnId:P,text:u})})),_=async u=>{await I(u)};t.panel.setComposer(u=>{_(u).catch(()=>{})});let H=async()=>{await d?.end(),d=null},ee=t.onMuteChange(u=>d?.setMuted(u)),ae=t.onDismiss(()=>{H().catch(()=>{})}),te={presence:t,tools:o,get sessionId(){return m},ready:M,ask:_,track(u,A){T({type:"goal_event",event:u,...A?{payload:A}:{}})},on(u){return r.add(u),()=>r.delete(u)},startVoice(){if(b)return b;if(d||w)return Promise.resolve();let u=e.loadAudio,A=m;return!u||!A?Promise.reject(new Error("voice_unavailable")):(b=(async()=>{let R=await n(`${e.apiUrl}/v1/sessions/${A}/voice?t=${a}`,{method:"POST"});if(!R.ok)throw new Error("voice_unavailable");let P=Hn(await R.json(),A);if(!P)throw new Error("voice_unavailable");let O=await(await u(P.vendor)).startVoice({grant:P,tools:o,presence:t,onEnd:()=>d=null,apiUrl:e.apiUrl,clientSecret:a,delegate:I});if(w){await O.end();return}d=O,O.setMuted(t.isMuted)})(),b.finally(()=>{b=null}))},endVoice:H,destroy(){w=!0,s!==null&&clearTimeout(s.timer),s=null,i!==void 0&&clearTimeout(i),c!==void 0&&clearTimeout(c),ee(),ae(),g?.(),f?.close(),f=null,d?.end(),o.destroy(),t.destroy()}};return e.debug&&t.host.ownerDocument.defaultView?.__docent&&(t.host.ownerDocument.defaultView.__docent.docent=te),te},On=e=>{try{return/^https?:$/.test(new URL(e).protocol)}catch{return!1}},Fn=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,re=e=>typeof e=="string"&&e.length>0&&e.length<=128,Hn=(e,n)=>{if(typeof e!="object"||e===null)return null;let t=e;return!re(t.sessionId)||!Fn.test(t.sessionId)||t.sessionId!==n?null:t.vendor==="openai"?{vendor:"openai",sessionId:t.sessionId,...re(t.greeting)?{greeting:t.greeting}:{}}:t.vendor!=="telnyx"||!re(t.agentId)?null:{vendor:"telnyx",agentId:t.agentId,sessionId:t.sessionId,...re(t.versionId)?{versionId:t.versionId}:{},...re(t.region)?{region:t.region}:{},...re(t.greeting)?{greeting:t.greeting}:{}}};0&&(module.exports={CONFIDENCE,DEFAULT_PLACEMENT,DEFAULT_THRESHOLD,DELTA_BUDGET_BYTES,DESTRUCTIVE_PATTERN,EDGE_DARK,EDGE_LIGHT,FIRST_RUN_CAPTION,INSET,MASK,NAME_FROM_CONTENT,STATE_ANNOUNCEMENTS,accessibleName,captureSnapshot,containsMask,cornerOrder,createCaptionPanel,createDocent,createLiveRegion,createOverlay,createPresence,createStorage,createTools,createTransport,deltaBytes,describeElement,diffSnapshots,edgeForAccent,elementFor,evaluateAction,implicitRole,isInteractiveRole,isMasked,labelElements,labelledByTargets,locationAdapter,nearestCorner,nodeKey,overlayStyles,placementToPoint,rectNear,rectsOverlap,redactPII,relativeLuminance,resolveAnchor,resolveKeepOut,safeMask,snapPlacement,startSync,watchDOM});
352
+ //# sourceMappingURL=index.cjs.map