@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.js ADDED
@@ -0,0 +1,352 @@
1
+ var Rn=10,he={kind:"corner",corner:"bottom-right"},St=["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}),Tt=(e,n,t)=>Math.min(t,Math.max(n,e)),Oe=(e,n,t,o)=>{let r=n<o/2?"top":"bottom",l=e<t/2?"left":"right";return`${r}-${l}`},be=(e,n,t,o)=>{let r=le(e,n,t,o);return[...St].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:Tt(e.y,10,t-o-10)},Fe=(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,ye=(e,n,t)=>Fe({x:e.x-t,y:e.y-t,width:e.width+2*t,height:e.height+2*t},n),He=(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=>Fe(d,b))};if(!l(e))return e;let m=Z(e,t,o,r),a=e.kind==="corner"?e.corner:Oe(m.x,m.y,t,o);for(let f of be(a,t,o,r)){let g={kind:"corner",corner:f};if(!l(g))return g}return e},$e=(e,n,t,o,r,l)=>l?{kind:"edge",edge:e<t/2?"left":"right",y:n-r/2}:{kind:"corner",corner:Oe(e,n,t,o)};var At=new Set(["top-left","top-right","bottom-left","bottom-right"]),Ct=e=>{if(typeof e!="object"||e===null)return!1;let n=e;return n.kind==="corner"?typeof n.corner=="string"&&At.has(n.corner):n.kind==="edge"?(n.edge==="left"||n.edge==="right")&&typeof n.y=="number":!1},xe=(e,n)=>{try{return e?.getItem(n)??null}catch{return null}},ve=(e,n,t)=>{try{e?.setItem(n,t)}catch{}},Be=(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(xe(r(),a));return Number.isFinite(d)&&d>0?d:f};return{loadPlacement(){let d=xe(o(),l);if(!d)return null;try{let b=JSON.parse(d);return Ct(b)?b:null}catch{return null}},savePlacement(d){ve(o(),l,JSON.stringify(d))},hasSeen(){return xe(r(),m)==="1"},markSeen(){ve(r(),m,"1")},dismissals:g,addDismissal(){let d=g()+1;return f=d,ve(r(),a,String(d)),d}}};var Ue={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"},Ve=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 Mt="I'm Docent. Tap if you want a hand.";var Ge=(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())},X=h=>{h.key==="Escape"&&(h.stopPropagation(),H())};d.addEventListener("click",()=>{_(!l),n.onToggleMute(l)}),b.addEventListener("click",()=>H()),a.addEventListener("keydown",X);let re=2,J=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+re),R(h);let C=setTimeout(()=>{o.delete(C),P(h)},J);o.add(C)},N=(h,k)=>{let C=u.get(h);if(C){let K=C.shown<C.target.length;C.target+=k,K||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=Mt,w.appendChild(h)},destroy(){for(let h of o)clearTimeout(h);o.clear(),a.removeEventListener("keydown",X),a.remove()}}};var ke=`
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 we=e=>Math.max(0,Math.min(255,Math.round(e))),Pt=e=>{let n=Number.parseInt(e.slice(1),16),t=we(((n>>16&255)+255)/2),o=we(((n>>8&255)+255)/2),r=we(((n&255)+255)/2);return`#${[t,o,r].map(l=>l.toString(16).padStart(2,"0")).join("").toUpperCase()}`},je={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"}},Rt=e=>typeof e=="string"&&Object.hasOwn(je,e),Ye=/^#[0-9a-fA-F]{6}$/,qe=e=>{if(Rt(e))return je[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"||!Ye.test(r))throw new RangeError(`Invalid mascot palette: ${o}`)}if(n.dormantColor!==void 0&&(typeof n.dormantColor!="string"||!Ye.test(n.dormantColor)))throw new RangeError("Invalid mascot palette: dormantColor");let t=n;return{...t,dormantColor:t.dormantColor??Pt(t.color)}};var Dt=()=>`
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>`,Lt=`
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
+ `,We="data-docent-dot",Nt=e=>{let n=e instanceof Document?e.head:e,t=n.querySelector(`style[${We}]`);if(t)return t;let o=(e instanceof Document?e:e.ownerDocument).createElement("style");return o.setAttribute(We,""),o.textContent=Lt,n.appendChild(o),o},Ke=(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)},It=e=>Math.min(1,Math.max(0,Number.isFinite(e)?e:0)),Ee=(e,n={})=>{let t=e.getRootNode();Nt(t);let o=(t instanceof Document?t:t.ownerDocument).createElement("template");o.innerHTML=Dt().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"),Ke(r,qe(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){Ke(r,qe(a))},setAmplitude(a){r.style.setProperty("--dot-amplitude",It(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 Ot="(max-width: 640px)",Ft="(prefers-reduced-motion: reduce)",Ht=6,ze=24,$t='input, textarea, select, [contenteditable]:not([contenteditable="false"])',_e=e=>({x:e.x,y:e.y,width:e.width,height:e.height}),Se=e=>{let n=(e.mount??document.body).ownerDocument,t=n.defaultView??window,o=e.mount??n.body,r=Be(e.appId,e.user?.id??"anonymous",t),l=t.matchMedia(Ft).matches,m=()=>t.matchMedia(Ot).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=ke,d.appendChild(b);let w=Ve(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===Ee?{palette:"purple"}:{},size:a(),state:v});return D.el.setAttribute("aria-hidden","true"),D.el.removeAttribute("role"),D},s=c(e.mascot??Ee,"dormant"),x=he,S=r.dismissals(),T=!1,y=!1,E=!1,L=!1,M,I=!1,_=Ge(d,{reducedMotion:l,returnFocusTo:i,onClose:()=>K(!0),onToggleMute:p=>Re(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}),X=()=>Array.from(n.querySelectorAll("[data-guide-primary]")).map(p=>_e(p.getBoundingClientRect())),re=(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),J(p,v)},J=(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=He(p,X(),D,$,a());let F=Z(x,D,$,a());re(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(Ue[p]),v&&p!=="pointing"&&s.setAim(u(x)),p==="dormant"?k():h()},N,O,pe=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:V}=H();s.setAttention((O.x-D)/(F/2),(O.y-$)/(V/2))}))},h=()=>{E||(E=!0,t.addEventListener("pointermove",pe))},k=()=>{E&&(E=!1,t.removeEventListener("pointermove",pe),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"))},K=(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 me)D()}y||P("dormant")}},me=new Set,fe=new Set,Re=p=>{y=p,_.setMuted(p);for(let v of fe)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?K(!1,!1):!T&&!y&&P("dormant")},se?f.first:f.later));let B,ae=!1,de=!1,wt=()=>{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=wt();B={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(!B||p.pointerId!==B.id)return;let v=p.clientX-B.x,D=p.clientY-B.y;!ae&&Math.hypot(v,D)<Ht||(ae||(ae=!0,s.setDragging(!0),i.dataset.dragging="true"),i.style.setProperty("--docent-x",`${B.dotX+v}px`),i.style.setProperty("--docent-y",`${B.dotY+D}px`))});let De=p=>{if(!B||p.pointerId!==B.id)return;let v=ae;if(B=void 0,ae=!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(),V=i.getBoundingClientRect(),Q=$e(V.x+V.width/2,V.y+V.height/2,D,$,F,m());A(Q,!0),r.savePlacement(x)};i.addEventListener("pointerup",De),i.addEventListener("pointercancel",De),i.addEventListener("click",()=>{if(de){de=!1;return}M!==void 0&&(clearTimeout(M),M=void 0,s.setQuiet(!1)),T?K(!0):C()});let Le=p=>{let v=p.target;if(!(v instanceof Element)||!v.matches($t)||g.contains(v))return;let D=_e(v.getBoundingClientRect()),$=_e(i.getBoundingClientRect());if(!ye($,D,ze))return;let{vw:F,vh:V}=H(),Q=a(),Et=x.kind==="corner"?x.corner:"bottom-right";for(let _t of be(Et,F,V,Q).slice(1)){let Ne={kind:"corner",corner:_t},Ie=Z(Ne,F,V,Q);if(!ye({x:Ie.x,y:Ie.y,width:Q,height:Q},D,ze)){A(Ne,!0);return}}};n.addEventListener("focusin",Le),t.addEventListener("resize",R),A(r.loadPlacement()??he,!1);let ge={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:()=>K(!0),toggle(){T?K(!0):C()},setMuted:Re,onDismiss(p){return me.add(p),()=>me.delete(p)},onMuteChange(p){return fe.add(p),()=>fe.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",Le),t.removeEventListener("resize",R),_.destroy(),s.destroy(),g.remove(),e.debug&&t.__docent?.presence===ge&&delete t.__docent)}};return e.debug&&(t.__docent={presence:ge}),ge};var Bt={button:"button",submit:"button",reset:"button",image:"button",checkbox:"checkbox",radio:"radio",range:"slider",number:"spinbutton",search:"searchbox"},Ut={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"},Vt=new Set(["button","link","heading","cell","columnheader","rowheader","option","tab","menuitem","listitem","summary"]),Gt=new Set(["button","link","textbox","checkbox","radio","combobox","listbox","option","switch","slider","spinbutton","tab","menuitem","searchbox"]),ie=e=>Gt.has(e),G=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:Bt[o]??"textbox"}return t==="select"?e.hasAttribute("multiple")||Number(e.getAttribute("size")??"0")>1?"listbox":"combobox":Ut[t]??null},Yt=120,j=e=>e.replace(/\s+/g," ").trim().slice(0,Yt),Xe=e=>{let n=e.getAttribute("id");return n?e.ownerDocument.querySelector(`label[for="${n.replace(/["\\]/g,"\\$&")}"]`):null},Je=e=>e.closest("label"),Qe=e=>{let n=Xe(e);if(n)return[n];let t=Je(e);return t?[t]:[]},Te=e=>{let n=e.getAttribute("aria-labelledby");return n?n.split(/\s+/).map(t=>e.ownerDocument.getElementById(t)).filter(t=>t!==null):[]},qt=e=>{let n=Xe(e);if(n)return j(n.textContent??"");let t=Je(e);if(t){let o=t.cloneNode(!0);return o.querySelectorAll("input, select, textarea, button").forEach(r=>r.remove()),j(o.textContent??"")}return""},z=e=>{if(e.getAttribute("aria-labelledby")){let m=Te(e).map(a=>a.textContent??"").filter(Boolean);if(m.length)return j(m.join(" "))}let t=e.getAttribute("aria-label");if(t?.trim())return j(t);let o=e.tagName.toLowerCase();if(o==="input"||o==="textarea"||o==="select"){let m=qt(e);if(m)return m}if(o==="img")return j(e.getAttribute("alt")??"");let r=G(e);if(r&&Vt.has(r)){let m=j(e.textContent??"");if(m)return m}let l=e.getAttribute("title");return l?.trim()?j(l):""};var U="\u2022\u2022\u2022",Wt=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}(?![A-Z0-9])/gi,Kt=/\b(?:\d[ -]?){12,18}\d\b/g,jt=/(?<![\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(Wt,U).replace(Kt,U).replace(jt,U),zt=e=>{let n=e.closest("[data-guide-mask]");if(!n)return!1;let t=e.closest("[data-guide-readable]");return!(t&&n.contains(t))},Ze=e=>zt(e)||e.querySelector("[data-guide-mask]")!==null,ee=e=>Ze(e)||[...Te(e),...Qe(e)].some(Ze),et=e=>{try{return e()}catch{return null}};var Xt=400,Jt=new Set(["SCRIPT","STYLE","TEMPLATE","NOSCRIPT","DOCENT-ROOT"]),Qt=new Set(["heading","navigation","main","banner","contentinfo","complementary","form","dialog"]),Zt=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"},en=(e,n,t)=>e.width>0&&e.height>0&&e.right>0&&e.bottom>0&&e.left<n&&e.top<t,tn=(e,n,t,o=0)=>{let r=e.getAttribute("data-guide");return r||`${n}|${t}|${e.tagName.toLowerCase()}#${o}`},nn=(e,n,t)=>e.hasAttribute("data-guide")?!0:n?ie(n)||t&&Qt.has(n):!1,on=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"},rn=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},Ae=(e,n={})=>et(()=>{let t=n.maxNodes??Xt,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 Jt.has(i.tagName)||Zt(i)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}}),b=d.nextNode();for(;b;){let w=G(b);if(nn(b,w,o)){let i=b.getBoundingClientRect();if(en(i,l,m)){if(a.length>=t){g=!0;break}let c=ee(b),s=c?U:Y(z(b)),x=w??"generic",S=`${x}|${s}|${b.tagName.toLowerCase()}`,T=f.get(S)??0;f.set(S,T+1);let y={key:tn(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=on(b);L&&(y.allow=L),b.closest("[data-guide-forbid]")&&(y.forbid=!0),c&&(y.masked=!0);let M=rn(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()}}),Xn=(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(!((G(f)??"generic")!==t||(ee(f)?U:Y(z(f)))!==o)){if(a===Number(m??0))return f;a++}return null};var tt=20480,an=(e,n)=>JSON.stringify(e)===JSON.stringify(n),nt=(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?an(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}},ot=e=>new TextEncoder().encode(JSON.stringify(e)).length;var sn=["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"],dn=e=>!!(e.nodeType===Node.ELEMENT_NODE?e:e.parentElement)?.closest("docent-root"),rt=(e,n,t={})=>{let o=t.debounceMs??150,r,l=new MutationObserver(m=>{m.every(a=>dn(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:sn,characterData:!0}),()=>{l.disconnect(),r!==void 0&&clearTimeout(r)}};var q={guide:1,roleNameExact:.9,roleNameContains:.7,text:.6,position:.4},dt=.6,ln=120,ce=e=>e.replace(/\s+/g," ").trim().toLowerCase(),lt=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},Ce=e=>Array.from(e.body.querySelectorAll("*")).filter(lt),ct=e=>ee(e)?U:Y(z(e)),cn={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"},un=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 ","")},te=e=>{let n=G(e)??"element",t=cn[n]??n,o=ct(e);return o&&o!==U?`the "${o}" ${t}`:`a ${t} near ${un(e)}`},at=(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&&lt(o)?o:null},it=(e,n,t)=>{let o=ce(n),r=null;for(let l of Ce(t)){let m=G(l);if(!m||(e?m!==e:!ie(m)))continue;let a=ce(ct(l));if(!(!a||a===U)){if(a===o)return{el:l,confidence:q.roleNameExact,method:"role-name",describe:te(l)};!r&&a.includes(o)&&(r=l)}}return r?{el:r,confidence:q.roleNameContains,method:"role-name",describe:te(r)}:null},st=(e,n)=>{let t=ce(e),o=null;for(let r of Ce(n))r.children.length>0&&!G(r)||ee(r)||ce(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:te(o)}:null},pn=(e,n)=>{let t=null;for(let o of Ce(n)){let r=G(o);if(!r||!ie(r))continue;let l=o.getBoundingClientRect(),m=Math.hypot(l.x+l.width/2-e.x,l.y+l.height/2-e.y);m<=ln&&(!t||m<t.d)&&(t={el:o,d:m})}return t?{el:t.el,confidence:q.position,method:"position",describe:te(t.el)}:null},ut=(e,n)=>{if(typeof e=="string"){let t=at(e,n);return t?{el:t,confidence:q.guide,method:"guide",describe:te(t)}:it(void 0,e,n)??st(e,n)}if(e.guide){let t=at(e.guide,n);if(t)return{el:t,confidence:q.guide,method:"guide",describe:te(t)}}if(e.name){let t=it(e.role,e.name,n);if(t)return t}if(e.text){let t=st(e.text,n);if(t)return t}return e.near?pn(e.near,n):null};var mn=/\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,fn=new Set(["checkbox","radio","button","submit","reset","image","file","hidden","range","color"]),gn=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},hn=e=>{let n=e.tagName.toLowerCase();if(n==="textarea")return!0;if(n==="input")return!fn.has((e.getAttribute("type")??"text").toLowerCase());let t=e.getAttribute("contenteditable");return t!==null&&t!=="false"},bn=(e,n)=>{let t=e.getAttribute("data-guide-allow");return t===null?!1:t.split(/\s+/).includes(n)},pt=(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(gn(e))return{allowed:!1,reason:"forbidden"};let o=`${z(e)} ${e.textContent??""}`;if(mn.test(o))return{allowed:!1,reason:"forbidden"}}return n==="fill"&&!hn(e)?{allowed:!1,reason:"unsupported"}:bn(e,n)?t.userRequested?{allowed:!0}:{allowed:!1,reason:"not_requested"}:{allowed:!1,reason:"not_allowlisted"}};var mt=e=>({navigate(n){e.history.pushState({},"",n),e.dispatchEvent(new PopStateEvent("popstate"))},currentPath(){return`${e.location.pathname}${e.location.search}`}});var ft="#130e30",ne="#ffffff",gt=(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)},Me=e=>{let n=/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/i.exec(e);if(!n)return ne;let[t,o,r]=[Number(n[1]),Number(n[2]),Number(n[3])];return[t,o,r].every(l=>Number.isFinite(l))&&gt(t/255,o/255,r/255)>.5?ft:ne};var ue=8,yn=12,ht=4,bt=2,W="http://www.w3.org/2000/svg",xn="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",yt=(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(W,"svg");r.setAttribute("class","docent-dim");let l=t.createElementNS(W,"defs"),m=t.createElementNS(W,"mask");m.setAttribute("id","docent-hole");let a=t.createElementNS(W,"rect");a.setAttribute("width","100%"),a.setAttribute("height","100%"),a.setAttribute("fill","#fff");let f=t.createElementNS(W,"rect");f.setAttribute("fill","#000"),f.setAttribute("rx",String(yn)),m.append(a,f),l.appendChild(m);let g=t.createElementNS(W,"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(W,"svg");b.setAttribute("viewBox","0 0 24 24"),b.setAttribute("class","docent-cursor"),b.setAttribute("aria-hidden","true");let w=t.createElementNS(W,"path");w.setAttribute("d",xn),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?Me(E):ne)},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-ue)),f.setAttribute("y",String(y.y-ue)),f.setAttribute("width",String(y.width+2*ue)),f.setAttribute("height",String(y.height+2*ue))},point(y,E){S(()=>this.clear()),s(),o.hidden=!1,d.hidden=!1,d.style.transitionDuration="0ms",d.style.translate=`${y.x-ht}px ${y.y-bt}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-ht}px ${L.y-bt}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 xt=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,vn=(e,n)=>{if(!(e.type==="email"||e.inputMode==="email")||xt.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 xt.test(r)?r:n},kn=(e,n)=>e==="fill"?`Fill in ${n} for you?`:`Click ${n} for you?`,wn=(e,n)=>n.el.getAttribute("data-guide")??(typeof e=="string"?e:e.guide??e.name??e.text??n.describe),Pe=e=>{let{presence:n}=e,t=e.doc??n.host.ownerDocument,o=t.defaultView??window,r=e.router??mt(o),l=e.threshold??dt,m=o.matchMedia("(prefers-reduced-motion: reduce)").matches,a=yt(n.root,{reducedMotion:m}),f=!1,g=(i,c=l)=>{let s=ut(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:wn(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=pt(S,c,{userRequested:s.userRequested});if(!T.allowed){if(T.reason==="not_requested"){let y=kn(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=vn(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 En=[500,1e3,2e3,5e3],vt=(e,n={})=>{let t=n.WebSocketImpl??WebSocket,o=n.backoffMs??En,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 kt=(e,n,t={})=>{let o=null,r=()=>{let g=Ae(e);g&&(o=g,n.send({type:"snapshot",snapshot:g}))},l=()=>{let g=Ae(e);if(!g)return;let d=nt(o,g);d.added.length+d.removed.length+d.changed.length===0&&d.route===o?.route&&d.scrollY===o?.scrollY||(ot(d)<=20480?n.send({type:"delta",delta:d}):n.send({type:"snapshot",snapshot:g}),o=g)};r();let m=rt(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 _n=2e4,Sn=1200,Tn=6e3,An=e=>{let n=e.fetchImpl??fetch,t=Se({appId:e.appId,user:{id:e.user.id},...e.debug?{debug:!0}:{},...e.presence??{}}),o=Pe({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()},Tn),x();return}case"goal_done":{t.setState("celebrating"),i!==void 0&&clearTimeout(i),i=setTimeout(x,Sn),l({type:"goal_done",goalKey:u.goalKey});return}case"open_docs":{let A=t.addCaption("docent","");if(!Cn(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=vt(N.wsUrl,e.WebSocketImpl?{WebSocketImpl:e.WebSocketImpl}:{}),f.onFrame(E),g=kt(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")))},_n);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},X=t.onMuteChange(u=>d?.setMuted(u)),re=t.onDismiss(()=>{H().catch(()=>{})}),J={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=Pn(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),X(),re(),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=J),J},Cn=e=>{try{return/^https?:$/.test(new URL(e).protocol)}catch{return!1}},Mn=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,oe=e=>typeof e=="string"&&e.length>0&&e.length<=128,Pn=(e,n)=>{if(typeof e!="object"||e===null)return null;let t=e;return!oe(t.sessionId)||!Mn.test(t.sessionId)||t.sessionId!==n?null:t.vendor==="openai"?{vendor:"openai",sessionId:t.sessionId,...oe(t.greeting)?{greeting:t.greeting}:{}}:t.vendor!=="telnyx"||!oe(t.agentId)?null:{vendor:"telnyx",agentId:t.agentId,sessionId:t.sessionId,...oe(t.versionId)?{versionId:t.versionId}:{},...oe(t.region)?{region:t.region}:{},...oe(t.greeting)?{greeting:t.greeting}:{}}};export{q as CONFIDENCE,he as DEFAULT_PLACEMENT,dt as DEFAULT_THRESHOLD,tt as DELTA_BUDGET_BYTES,mn as DESTRUCTIVE_PATTERN,ft as EDGE_DARK,ne as EDGE_LIGHT,Mt as FIRST_RUN_CAPTION,Rn as INSET,U as MASK,Vt as NAME_FROM_CONTENT,Ue as STATE_ANNOUNCEMENTS,z as accessibleName,Ae as captureSnapshot,ee as containsMask,be as cornerOrder,Ge as createCaptionPanel,An as createDocent,Ve as createLiveRegion,yt as createOverlay,Se as createPresence,Be as createStorage,Pe as createTools,vt as createTransport,ot as deltaBytes,te as describeElement,nt as diffSnapshots,Me as edgeForAccent,Xn as elementFor,pt as evaluateAction,G as implicitRole,ie as isInteractiveRole,zt as isMasked,Qe as labelElements,Te as labelledByTargets,mt as locationAdapter,Oe as nearestCorner,tn as nodeKey,ke as overlayStyles,Z as placementToPoint,ye as rectNear,Fe as rectsOverlap,Y as redactPII,gt as relativeLuminance,ut as resolveAnchor,He as resolveKeepOut,et as safeMask,$e as snapPlacement,kt as startSync,rt as watchDOM};
352
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@usedocent/sdk-core",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "!dist/**/*.map"
18
+ ],
19
+ "sideEffects": false,
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "typecheck": "tsc --noEmit -p tsconfig.json",
23
+ "test": "vitest run",
24
+ "lint": "eslint src"
25
+ },
26
+ "dependencies": {},
27
+ "devDependencies": {
28
+ "@usedocent/mascot": "workspace:*",
29
+ "@usedocent/shared": "workspace:*",
30
+ "jsdom": "^26.0.0",
31
+ "tsup": "^8.3.5",
32
+ "typescript": "^5.7.3",
33
+ "vitest": "^3.0.4"
34
+ },
35
+ "description": "Voice-first, screen-aware in-app guide. Framework-agnostic core: perception, overlay, action guard and transport. Zero runtime dependencies.",
36
+ "license": "UNLICENSED",
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/usedocent/docent.git",
43
+ "directory": "packages/sdk-core"
44
+ },
45
+ "homepage": "https://usedocent.com"
46
+ }