@characterxyz/widget 0.0.0-stage → 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.
@@ -0,0 +1,102 @@
1
+ import { InitOptions, CharacterXYZ } from '@characterxyz/web';
2
+ export { CharacterXYZ, CxError } from '@characterxyz/web';
3
+
4
+ /**
5
+ * Everything a brand can set, from three places, later wins:
6
+ * 1. the key's `appearance` (the Embed designer in Character XYZ),
7
+ * 2. the element's attributes / `data-*` on the script tag,
8
+ * 3. options passed to `mount()`.
9
+ */
10
+ type Position = 'bottom-right' | 'bottom-left';
11
+ type ColorMode = 'light' | 'dark' | 'auto';
12
+ /** `bubble`: just her portrait (opens the chat; calls are inside). `actions`: chat and call buttons beside it. */
13
+ type LauncherStyle = 'bubble' | 'actions';
14
+ /** How she is shown while closed: a round `bubble`, a `half` body cut-out, or her `full` body standing in the corner. */
15
+ type Display = 'bubble' | 'half' | 'full';
16
+ interface WidgetConfig {
17
+ position: Position;
18
+ mode: ColorMode;
19
+ launcher: LauncherStyle;
20
+ display: Display;
21
+ /** Any CSS colour. */
22
+ accent: string;
23
+ /** Corner radius of the panel, px. */
24
+ radius: number;
25
+ /** A CSS font-family; defaults to the system UI font. */
26
+ font: string;
27
+ /** The line under her name; defaults to the agent's tagline. */
28
+ subtitle: string | null;
29
+ /** Shown once per visitor above the launcher. Empty = none. */
30
+ greeting: string;
31
+ /** Seconds before the greeting appears. */
32
+ greetingDelay: number;
33
+ /** Suggested first messages in an empty chat. */
34
+ suggestions: string[];
35
+ /** Placeholder in the message box. */
36
+ placeholder: string;
37
+ showChat: boolean;
38
+ showCall: boolean;
39
+ /** The "Powered by Character XYZ" line. */
40
+ branding: boolean;
41
+ /** px from the corner. */
42
+ offsetX: number;
43
+ offsetY: number;
44
+ zIndex: number;
45
+ /** Open the panel on load. */
46
+ open: boolean;
47
+ /**
48
+ * Draw the agent's face in calls with Character XYZ's own renderer (lip
49
+ * sync, her own teeth and eyes), framed from `faceUrl`. Off = the portrait clips.
50
+ */
51
+ face: boolean;
52
+ faceUrl: string;
53
+ }
54
+ declare const DEFAULTS: WidgetConfig;
55
+ /** Merge one layer of untrusted settings onto a config. Unknown or invalid values are dropped. */
56
+ declare function applyLayer(base: WidgetConfig, raw: Record<string, unknown> | null | undefined): WidgetConfig;
57
+
58
+ declare const TAG = "character-xyz";
59
+ interface MountOptions extends InitOptions, Partial<WidgetConfig> {
60
+ /** Where the element goes. Default `document.body`. */
61
+ container?: HTMLElement;
62
+ }
63
+ /** Ink that reads on the accent: white on dark accents, near-black on light ones. */
64
+ declare function inkFor(color: string): string;
65
+ /**
66
+ * `<character-xyz publishable-key="cxyz_pk_live_…"></character-xyz>`
67
+ *
68
+ * Events (bubbling, composed): `cx-ready` {agent}, `cx-open` {view},
69
+ * `cx-close`, `cx-call` {phase}, `cx-error` {code, message}.
70
+ * Methods: `open('chat' | 'call')`, `close()`; property `client` once ready.
71
+ */
72
+ declare class CharacterXYZElement extends HTMLElement {
73
+ static get observedAttributes(): string[];
74
+ /** Set before the element connects (what `mount()` does). */
75
+ options: MountOptions | null;
76
+ client: CharacterXYZ | null;
77
+ private api;
78
+ private pendingOpen;
79
+ private booted;
80
+ private mq;
81
+ private stage;
82
+ connectedCallback(): void;
83
+ disconnectedCallback(): void;
84
+ open(view?: 'chat' | 'call'): void;
85
+ close(): void;
86
+ private fire;
87
+ private onSchemeChange;
88
+ private onScheme;
89
+ private boot;
90
+ private applyTokens;
91
+ }
92
+ declare function define(): void;
93
+ interface WidgetHandle {
94
+ element: CharacterXYZElement;
95
+ open(view?: 'chat' | 'call'): void;
96
+ close(): void;
97
+ destroy(): void;
98
+ }
99
+ /** Put the widget on the page. One per page is the norm; a second replaces nothing. */
100
+ declare function mount(options: MountOptions): WidgetHandle;
101
+
102
+ export { CharacterXYZElement, type ColorMode, DEFAULTS, type Display, type LauncherStyle, type MountOptions, type Position, TAG, type WidgetConfig, type WidgetHandle, applyLayer, define, inkFor, mount };
package/dist/index.js ADDED
@@ -0,0 +1,356 @@
1
+ var _n=Object.defineProperty;var bn=(t,e,n)=>e in t?_n(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var Y=(t,e,n)=>bn(t,typeof e!="symbol"?e+"":e,n);var xn=Object.defineProperty,vn=(t,e,n)=>e in t?xn(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,b=(t,e,n)=>vn(t,typeof e!="symbol"?e+"":e,n),J=null;function st(){return(!J||J.state==="closed")&&(J=new AudioContext({latencyHint:"interactive"})),J.state==="suspended"&&J.resume().catch(()=>{}),J}var yn=class{constructor(t={}){b(this,"opts",t),b(this,"ctx"),b(this,"gain"),b(this,"analyser"),b(this,"data"),b(this,"nextAt",0),b(this,"started",!1),b(this,"ended",!1),b(this,"finishing",!1),b(this,"sources",new Set),b(this,"startedAt",0),b(this,"sampleRate"),this.ctx=st(),this.sampleRate=t.sampleRate??16e3,this.gain=this.ctx.createGain(),this.gain.gain.value=t.volume??1,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=512,this.data=new Uint8Array(new ArrayBuffer(this.analyser.fftSize)),this.gain.connect(this.analyser).connect(this.ctx.destination)}enqueue(t){if(this.ended||t.byteLength<2)return;let e=Math.floor(t.byteLength/2),n=new DataView(t.buffer,t.byteOffset,e*2),i=this.ctx.createBuffer(1,e,this.sampleRate),a=i.getChannelData(0);for(let l=0;l<e;l++)a[l]=n.getInt16(l*2,!0)/32768;let r=this.ctx.createBufferSource();r.buffer=i,r.connect(this.gain);let o=this.ctx.currentTime;if(this.nextAt<o&&(this.nextAt=o+(this.started?.02:.12)),r.start(this.nextAt),!this.started){this.started=!0;let l=Math.max(0,(this.nextAt-o)*1e3);this.startedAt=performance.now()+l,setTimeout(()=>this.opts.onStart?.(),l)}this.nextAt+=i.duration,this.sources.add(r),r.onended=()=>{this.sources.delete(r),this.finishing&&this.sources.size===0&&this.finish()}}end(){this.finishing=!0,this.sources.size===0&&this.finish()}stop(){this.ended=!0;for(let t of this.sources)try{t.stop()}catch{}this.sources.clear(),this.gain.disconnect()}playedMs(){return this.started?Math.max(0,performance.now()-this.startedAt):0}level(){this.analyser.getByteTimeDomainData(this.data);let t=0;for(let e=0;e<this.data.length;e++){let n=(this.data[e]-128)/128;t+=n*n}return Math.min(1,Math.sqrt(t/this.data.length)*3)}finish(){this.ended||(this.ended=!0,this.gain.disconnect(),this.opts.onEnd?.())}},kn=`
2
+ class CxyzMic extends AudioWorkletProcessor {
3
+ constructor(o) {
4
+ super();
5
+ this.ratio = sampleRate / 16000;
6
+ this.pos = 0;
7
+ this.lp = 0;
8
+ this.alpha = Math.min(1, 2 * Math.PI * 7000 / sampleRate / (1 + 2 * Math.PI * 7000 / sampleRate));
9
+ this.out = new Int16Array(480);
10
+ this.n = 0;
11
+ }
12
+ process(inputs) {
13
+ const ch = inputs[0] && inputs[0][0];
14
+ if (!ch) return true;
15
+ for (let i = 0; i < ch.length; i++) {
16
+ this.lp += this.alpha * (ch[i] - this.lp);
17
+ this.pos += 1;
18
+ if (this.pos >= this.ratio) {
19
+ this.pos -= this.ratio;
20
+ const s = Math.max(-1, Math.min(1, this.lp));
21
+ this.out[this.n++] = s < 0 ? s * 0x8000 : s * 0x7fff;
22
+ if (this.n === 480) {
23
+ this.port.postMessage(this.out.buffer, [this.out.buffer]);
24
+ this.out = new Int16Array(480);
25
+ this.n = 0;
26
+ }
27
+ }
28
+ }
29
+ return true;
30
+ }
31
+ }
32
+ registerProcessor('cxyz-mic', CxyzMic);
33
+ `;function wn(t){let e=new Int16Array(t);if(!e.length)return 0;let n=0;for(let i=0;i<e.length;i++){let a=e[i]/32768;n+=a*a}return Math.sqrt(n/e.length)}async function Cn(t){if(!navigator.mediaDevices?.getUserMedia)throw new Error("This browser cannot use a microphone here.");let e=await navigator.mediaDevices.getUserMedia({audio:{deviceId:t.deviceId?{exact:t.deviceId}:void 0,channelCount:1,echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}}),n=new AudioContext({latencyHint:"interactive"}),i=n.createMediaStreamSource(e),a=!1,r=d=>{if(a){t.onFrame(new ArrayBuffer(d.byteLength),0);return}t.onFrame(d,wn(d))},o,l;try{let d=URL.createObjectURL(new Blob([kn],{type:"application/javascript"}));try{await n.audioWorklet.addModule(d)}finally{URL.revokeObjectURL(d)}let u=new AudioWorkletNode(n,"cxyz-mic");u.port.onmessage=m=>r(m.data),o=u,l=()=>{u.port.onmessage=null}}catch{let d=n.createScriptProcessor(4096,1,1),u=n.sampleRate/16e3,m=0,c=new Int16Array(480),h=0;d.onaudioprocess=_=>{let v=_.inputBuffer.getChannelData(0);for(let g=0;g<v.length;g++)if(m+=1,m>=u){m-=u;let x=Math.max(-1,Math.min(1,v[g]));c[h++]=x<0?x*32768:x*32767,h===480&&(r(c.buffer),c=new Int16Array(480),h=0)}},o=d,l=()=>{d.onaudioprocess=null}}i.connect(o);let p=n.createGain();return p.gain.value=0,o.connect(p).connect(n.destination),n.state==="suspended"&&await n.resume().catch(()=>{}),{get muted(){return a},setMuted(d){a=d;for(let u of e.getAudioTracks())u.enabled=!d},stop(){l();try{i.disconnect(),o.disconnect()}catch{}for(let d of e.getTracks())d.stop();n.close().catch(()=>{})}}}var Oe=class{constructor(){b(this,"handlers",{})}on(t,e){var n;return((n=this.handlers)[t]??(n[t]=new Set)).add(e),()=>this.handlers[t]?.delete(e)}emit(t,e){for(let n of this.handlers[t]??[])try{n(e)}catch(i){console.error("[characterxyz] listener threw",i)}}clear(){this.handlers={}}},z=class extends Error{constructor(t,e,n=0){super(e),b(this,"code"),b(this,"status"),this.name="CxError",this.code=t,this.status=n}};function Sn(t){switch(t){case 401:return"unauthorized";case 403:return"forbidden";case 404:return"not_found";case 402:return"payment_required";case 422:return"invalid";case 429:return"rate_limited";case 503:return"unavailable";default:return"unknown"}}async function An(t){let e="";try{let n=await t.json();typeof n?.message=="string"&&(e=n.message)}catch{}return new z(Sn(t.status),e||`Request failed (${t.status})`,t.status)}async function he(t,e,n={}){let i={};n.body!==void 0&&(i["Content-Type"]="application/json"),n.token&&(i.Authorization=`Bearer ${n.token}`);let a;try{a=await fetch(t+e,{method:n.method??(n.body===void 0?"GET":"POST"),headers:i,body:n.body===void 0?void 0:JSON.stringify(n.body),signal:n.signal,credentials:"omit",cache:"no-store"})}catch(r){throw r?.name==="AbortError"?r:new z("network","Could not reach Character XYZ. Check your connection.")}if(!a.ok)throw await An(a);return a}async function te(t,e,n={}){return(await(await he(t,e,n)).json()).data}async function ot(t,e,n){let i=t.body;if(!i)return;let a=i.getReader(),r=new TextDecoder,o="",l=()=>{a.cancel().catch(()=>{})};n?.addEventListener("abort",l);try{for(;;){let{value:p,done:d}=await a.read();if(d)break;o+=r.decode(p,{stream:!0}),o=at(o,e)}o+=r.decode(),at(o+`
34
+
35
+ `,e)}finally{n?.removeEventListener("abort",l)}}function at(t,e){let n=t.replace(/\r\n/g,`
36
+ `),i;for(;(i=n.indexOf(`
37
+
38
+ `))!==-1;){let a=n.slice(0,i);n=n.slice(i+2);let r="message",o=[];for(let d of a.split(`
39
+ `)){if(!d||d.startsWith(":"))continue;let u=d.indexOf(":"),m=u===-1?d:d.slice(0,u),c=u===-1?"":d.slice(u+1).replace(/^ /,"");m==="event"?r=c:m==="data"&&o.push(c)}if(!o.length)continue;let l=o.join(`
40
+ `),p=l;try{p=JSON.parse(l)}catch{}e({event:r,data:p})}return n}function Mn(t){if(t.byteLength<25)return null;let e=new DataView(t);if(e.getUint8(0)!==67||e.getUint8(1)!==88||e.getUint8(2)!==89||e.getUint8(3)!==90||e.getUint8(4)!==1)return null;let n=e.getUint8(5),i=(e.getUint8(6)&1)!==0,a=7,r=e.getUint16(a,!0);if(a+=2,a+r+20>t.byteLength)return null;let o=new TextDecoder().decode(new Uint8Array(t,a,r));a+=r+4+8+4;let l=e.getUint32(a,!0);return a+=4,a+l>t.byteLength?null:{kind:n,final:i,corr:o,payload:new Uint8Array(t,a,l)}}var Tn=.09,In=350,En=25e3,zn=()=>({phase:"idle",callId:null,position:null,etaSeconds:null,holdSeconds:null,maxSeconds:null,startedAt:null,endReason:null,muted:!1,speaking:!1,agentState:"idle",error:null}),$n=class extends Oe{constructor(t,e,n,i={}){super(),b(this,"apiUrl",t),b(this,"session",e),b(this,"agentId",n),b(this,"opts",i),b(this,"s",zn()),b(this,"ticket",null),b(this,"eventsAbort",null),b(this,"ws",null),b(this,"mic",null),b(this,"players",new Map),b(this,"sampleRates",new Map),b(this,"cancelled",new Set),b(this,"speakingCorr",null),b(this,"heartbeat",null),b(this,"loudSince",null)}get state(){return this.s}audible(){let t=this.speakingCorr,e=t?this.players.get(t):void 0;return t&&e?{corr:t,ms:e.playedMs()}:null}voiceLevel(){let t=this.speakingCorr?this.players.get(this.speakingCorr):void 0;return t?t.level():0}set(t){this.s={...this.s,...t},this.emit("state",this.s)}async start(){if(this.s.phase==="idle"){this.set({phase:"joining"}),st();try{this.mic=await Cn({deviceId:this.opts.deviceId,onFrame:(t,e)=>this.onMicFrame(t,e)})}catch{this.finish("mic-denied","Allow the microphone to talk, or chat instead.");return}try{let t=await this.session.token(),e=await te(this.apiUrl,"/sdk/v1/calls",{method:"POST",body:{},token:t});this.set({callId:e.callId,phase:e.state==="ready"?"joining":"queued",position:e.position??null,etaSeconds:e.etaSeconds??null}),this.follow()}catch(t){let e=t instanceof z?t:new z("unknown","Could not start the call."),n=e.code==="rate_limited"?"busy":"unavailable";this.finish(n,e.message),this.emit("error",e)}}}async follow(){let t=0;for(;this.s.callId&&this.s.phase!=="ended"&&this.s.phase!=="idle";){this.eventsAbort=new AbortController;try{let e=await this.session.token(),n=await he(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(this.s.callId)}/events`,{token:e,signal:this.eventsAbort.signal});t=0,await ot(n,i=>this.onServerEvent(i.event,i.data),this.eventsAbort.signal)}catch(e){if(e?.name==="AbortError")return;if(e instanceof z&&e.code==="not_found"){this.finish("failed","The call ended.");return}if(t+=1,t>5){this.finish("failed","Lost the connection to the call.");return}}if(this.ended())return;await new Promise(e=>setTimeout(e,Math.min(4e3,500*2**t)))}}onServerEvent(t,e){switch(t){case"queued":(this.s.phase==="joining"||this.s.phase==="queued")&&this.set({phase:"queued",position:Number(e.position)||1,etaSeconds:Number(e.etaSeconds)||null});break;case"ready":{typeof e.ticket=="string"&&e.ticket&&(this.ticket=e.ticket);let n=Number(e.holdSeconds)||0;this.s.phase!=="ready"&&this.s.phase!=="connecting"&&this.s.phase!=="live"?(this.set({phase:"ready",holdSeconds:n,position:null,etaSeconds:null}),this.emit("ready",{holdSeconds:n}),this.opts.autoAccept!==!1&&this.accept()):this.s.phase==="ready"&&this.set({holdSeconds:n});break}case"live":this.set({phase:"live",maxSeconds:Number(e.maxSeconds)||null,startedAt:this.s.startedAt??Date.now()-(Number(e.elapsedSeconds)||0)*1e3});break;case"ended":this.finish(String(e.reason||"hangup")||"hangup",null);break}}ended(){return this.s.phase==="ended"}accept(){if(this.s.phase!=="ready"||!this.ticket||this.ws)return;this.set({phase:"connecting"});let t=this.apiUrl.replace(/^http/,"ws")+"/sdk/v1/calls/socket",e=new WebSocket(t,[`cxyz-ticket.${this.ticket}`]);this.ticket=null,e.binaryType="arraybuffer",this.ws=e,e.onopen=()=>{let n=this.opts.face,i=n?.emotion?.()??null;e.send(JSON.stringify({type:"agent_identity",agent_id:this.agentId,skin_index:0,blendshapes:!!n,...n?{blendshape_stream:!0}:{},...n&&i?{face_emotion:i}:{}})),e.send(JSON.stringify({type:"mic_state",silero:"off",denoise:!1})),this.heartbeat=setInterval(()=>this.sendJson({type:"heartbeat"}),En),this.set({phase:"live",startedAt:this.s.startedAt??Date.now()})},e.onmessage=n=>this.onSocket(n.data),e.onclose=()=>{this.ws=null,setTimeout(()=>{(this.s.phase==="live"||this.s.phase==="connecting")&&this.finish("hangup",null)},1500)}}sendJson(t){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(t))}onMicFrame(t,e){let n=this.ws;if(!(!n||n.readyState!==WebSocket.OPEN)){if(this.speakingCorr){let i=performance.now();if(e>Tn){if(this.loudSince??(this.loudSince=i),i-this.loudSince>=In){this.loudSince=null,this.interrupt(),n.send(t);return}}else this.loudSince=null;n.send(new ArrayBuffer(t.byteLength));return}n.send(t)}}onSocket(t){if(t instanceof ArrayBuffer){let n=Mn(t);if(!n||this.cancelled.has(n.corr))return;if(n.kind===3){this.opts.face&&this.emit("face",{corr:n.corr,payload:n.payload.slice()});return}if(n.kind!==1)return;let i=this.players.get(n.corr);if(!i){for(let[r,o]of this.players)o.stop(),this.players.delete(r);let a=n.corr;i=new yn({sampleRate:this.sampleRates.get(a)??16e3,onStart:()=>{this.speakingCorr=a,this.set({speaking:!0}),this.emit("line",{corr:a,event:"audible"}),this.sendJson({type:"playback_started",correlationId:a,timestampMs:Date.now()})},onEnd:()=>{this.players.delete(a),this.speakingCorr===a&&(this.speakingCorr=null),this.set({speaking:!1}),this.emit("line",{corr:a,event:"end"}),this.sendJson({type:"playback_ended",correlationId:a,timestampMs:Date.now(),reason:"natural"}),this.sendJson({type:"speech_ended"})}}),this.players.set(a,i)}i.enqueue(n.payload),n.final&&i.end();return}if(typeof t!="string")return;let e;try{e=JSON.parse(t)}catch{return}if("AgentSpeechMeta"in e){let n=e.AgentSpeechMeta;n?.correlation_id&&n.sample_rate&&this.sampleRates.set(n.correlation_id,n.sample_rate);return}if("InteractorTranscript"in e){let n=e.InteractorTranscript;n?.text&&this.emit("caption",{id:`v:${n.correlation_id}`,role:"visitor",text:n.text});return}if("AgentReplyTranscript"in e){let n=e.AgentReplyTranscript;n?.text&&!this.cancelled.has(n.correlation_id)&&this.emit("caption",{id:`a:${n.correlation_id}`,role:"agent",text:n.text});return}if(e.type==="turn_cancelled"&&typeof e.correlationId=="string"){let n=e.correlationId;this.cancelled.add(n),this.players.get(n)?.stop(),this.players.delete(n),this.emit("line",{corr:n,event:"end"}),this.speakingCorr===n&&(this.speakingCorr=null,this.set({speaking:!1})),this.emit("captionRemoved",`a:${n}`);return}e.kind==="agent_status"&&typeof e.state=="string"&&this.set({agentState:e.state.toLowerCase()})}interrupt(){let t=this.speakingCorr;if(!t)return;let e=this.players.get(t),n=Math.round(e?.playedMs()??0);e?.stop(),this.players.delete(t),this.cancelled.add(t),this.speakingCorr=null,this.set({speaking:!1}),this.emit("line",{corr:t,event:"end"}),this.sendJson({type:"playback_ended",correlationId:t,timestampMs:Date.now(),reason:"interrupted"}),this.sendJson({type:"interrupt",correlationId:t,heardMs:n,timestampMs:Date.now()})}setMuted(t){this.mic?.setMuted(t),this.set({muted:t})}async hangUp(){let t=this.s.callId,e=this.s.phase;if(this.finish(e==="live"?"hangup":"left",null),!!t)try{let n=await this.session.token();await he(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(t)}`,{method:"DELETE",token:n})}catch{}}finish(t,e){if(this.s.phase==="ended")return;this.eventsAbort?.abort(),this.eventsAbort=null,this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null;for(let i of this.players.values())i.stop();this.players.clear(),this.speakingCorr=null,this.mic?.stop(),this.mic=null;let n=this.ws;this.ws=null,n&&n.readyState<=WebSocket.OPEN&&n.close(1e3),this.ticket=null,this.set({phase:"ended",endReason:t,speaking:!1,holdSeconds:null,error:e})}},Un=0,rt=t=>`${t}_${Date.now().toString(36)}_${(Un++).toString(36)}`,Ln=class extends Oe{constructor(t,e){super(),b(this,"apiUrl",t),b(this,"session",e),b(this,"list",[]),b(this,"loaded",!1),b(this,"busy",!1),b(this,"abort",null)}get messages(){return this.list}get isBusy(){return this.busy}publish(){this.list=[...this.list],this.emit("messages",this.list)}async load(){if(this.loaded)return this.list;let t=await this.session.token(),e=await te(this.apiUrl,"/sdk/v1/chat/messages?limit=50",{token:t}),n=this.list;return this.list=[...e?.messages??[],...n],this.loaded=!0,this.publish(),this.list}async send(t){let e=t.trim();if(!e)throw new z("invalid","Say something first.");if(this.busy)throw new z("rate_limited","Wait for the reply first.");this.setBusy(!0);let n={id:rt("local"),role:"visitor",text:e,createdAt:new Date().toISOString()},i={id:rt("reply"),role:"agent",text:"",createdAt:new Date().toISOString(),streaming:!0};this.list.push(n,i),this.publish(),this.abort=new AbortController;try{let a=await this.session.token(),r=await he(this.apiUrl,"/sdk/v1/chat/messages",{method:"POST",body:{text:e},token:a,signal:this.abort.signal}),o=null,l=null;if(await ot(r,({event:d,data:u})=>{let m=u;d==="delta"&&typeof m?.text=="string"?(i.text+=m.text,this.publish()):d==="done"?o={id:String(m.id),role:"agent",text:String(m.text??i.text),createdAt:String(m.createdAt??i.createdAt)}:d==="error"&&(l=typeof m?.message=="string"?m.message:"Something went wrong.")},this.abort.signal),l||!o)throw new z("unknown",l??"The reply was cut off. Try again.");let p=o;return this.replace(i.id,p),p}catch(a){let r=a instanceof z?a:new z("network","The reply was cut off. Try again.");this.list=this.list.filter(l=>l.id!==i.id);let o=this.list.findIndex(l=>l.id===n.id);throw o!==-1&&(this.list[o]={...n,failed:!0}),this.publish(),a?.name!=="AbortError"&&this.emit("error",r),r}finally{this.abort=null,this.setBusy(!1)}}retry(t){let e=this.list.find(n=>n.id===t&&n.failed);if(!e)throw new z("not_found","Nothing to retry.");return this.list=this.list.filter(n=>n.id!==t),this.publish(),this.send(e.text)}stop(){this.abort?.abort()}replace(t,e){let n=this.list.findIndex(i=>i.id===t);n!==-1&&(this.list[n]=e),this.publish()}setBusy(t){this.busy=t,this.emit("busy",t)}},Pn=()=>{let t=new Map;return{get:e=>t.get(e)??null,set:(e,n)=>{t.set(e,n)}}},Rn=()=>({get(t){try{return globalThis.localStorage?.getItem(t)??null}catch{return null}},set(t,e){try{globalThis.localStorage?.setItem(t,e)}catch{}}}),Fn=60,Dn=class{constructor(t){if(b(this,"src",t),b(this,"current",null),b(this,"inflight",null),!t.publishableKey&&!t.getSessionToken)throw new z("invalid","Pass a publishableKey, or getSessionToken for sessions your server mints.")}visitorKey(){return`cxyz:visitor:${(this.src.publishableKey??"server").slice(-12)}`}get info(){return this.current}async token(){let t=Date.now()/1e3;return this.current&&this.current.expiresAt-Fn>t?this.current.token:(await this.refresh()).token}refresh(){return this.inflight??(this.inflight=this.mint().finally(()=>{this.inflight=null})),this.inflight}async mint(){let t;if(this.src.getSessionToken){let e=await this.src.getSessionToken();typeof e=="string"?t=await this.describe(e):t=e}else{let e=this.src.store.get(this.visitorKey())??void 0;t=await te(this.src.apiUrl,"/sdk/v1/sessions",{method:"POST",body:{publishableKey:this.src.publishableKey,agentId:this.src.agentId,visitorId:e}}),this.src.store.set(this.visitorKey(),t.visitorId)}return this.current=t,t}async describe(t){return{...await te(this.src.apiUrl,"/sdk/v1/session",{token:t}),token:t}}},On="https://api.character.xyz",He=class lt extends Oe{constructor(e,n,i){super(),b(this,"apiUrl",e),b(this,"session",n),b(this,"info",i),b(this,"chat"),b(this,"currentCall",null),b(this,"destroyed",!1),this.chat=new Ln(e,n)}static async init(e){let n=(e.apiUrl??On).replace(/\/+$/,"");if(e.publishableKey&&/^cxyz_sk_/.test(e.publishableKey))throw new z("invalid","That is a SECRET key. Never put it in a web page: use a publishable key (cxyz_pk_\u2026). Revoke the secret key now.");let i=e.storage==="memory"?Pn():e.storage&&typeof e.storage=="object"?e.storage:Rn(),a=new Dn({apiUrl:n,agentId:e.agentId,publishableKey:e.publishableKey,getSessionToken:e.getSessionToken,store:i}),r=await a.refresh();return new lt(n,a,r)}get agent(){return(this.session.info??this.info).agent}get features(){return(this.session.info??this.info).features}get appearance(){return(this.session.info??this.info).appearance??{}}get visitorId(){return(this.session.info??this.info).visitorId}get mode(){return(this.session.info??this.info).mode}get call(){return this.currentCall&&this.currentCall.state.phase!=="ended"?this.currentCall:null}async videoAvatar(){let e=await this.session.token();return te(this.apiUrl,"/sdk/v1/agent/video-avatar",{token:e})}async startCall(e={}){if(this.destroyed)throw new z("invalid","This client was destroyed.");if(!this.features.call)throw new z("forbidden","Calls are not available on this site.");if(this.call)return this.call;let n=new $n(this.apiUrl,this.session,this.agent.id,e);return this.currentCall=n,n.on("state",i=>{i.phase==="ended"&&this.currentCall===n&&this.emit("call",null)}),n.on("error",i=>this.emit("error",i)),this.emit("call",n),await n.start(),n}destroy(){this.destroyed=!0,this.currentCall?.hangUp(),this.chat.stop(),this.chat.clear(),this.clear()}};var ye,C,ht,Hn,V,ct,ft,gt,We,ge,ne,mt,qe,Ye,Ne,Wn,be={},xe=[],Yn=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,ke=Array.isArray;function B(t,e){for(var n in e)t[n]=e[n];return t}function Be(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function Nn(t,e,n){var i,a,r,o={};for(r in e)r=="key"?i=e[r]:r=="ref"?a=e[r]:o[r]=e[r];if(arguments.length>2&&(o.children=arguments.length>3?ye.call(arguments,2):n),typeof t=="function"&&t.defaultProps!=null)for(r in t.defaultProps)o[r]===void 0&&(o[r]=t.defaultProps[r]);return me(t,o,i,a,null)}function me(t,e,n,i,a){var r={type:t,props:e,key:n,ref:i,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:a??++ht,__i:-1,__u:0};return a==null&&C.vnode!=null&&C.vnode(r),r}function M(t){return t.children}function _e(t,e){this.props=t,this.context=e}function K(t,e){if(e==null)return t.__?K(t.__,t.__i+1):null;for(var n;e<t.__k.length;e++)if((n=t.__k[e])!=null&&n.__e!=null)return n.__e;return typeof t.type=="function"?K(t):null}function qn(t){if(t.__P&&t.__d){var e=t.__v,n=e.__e,i=[],a=[],r=B({},e);r.__v=e.__v+1,C.vnode&&C.vnode(r),Ve(t.__P,r,e,t.__n,t.__P.namespaceURI,32&e.__u?[n]:null,i,n??K(e),!!(32&e.__u),a),r.__v=e.__v,r.__.__k[r.__i]=r,yt(i,r,a),e.__e=e.__=null,r.__e!=n&&_t(r)}}function _t(t){if((t=t.__)!=null&&t.__c!=null)return t.__e=t.__c.base=null,t.__k.some(function(e){if(e!=null&&e.__e!=null)return t.__e=t.__c.base=e.__e}),_t(t)}function dt(t){(!t.__d&&(t.__d=!0)&&V.push(t)&&!ve.__r++||ct!=C.debounceRendering)&&((ct=C.debounceRendering)||ft)(ve)}function ve(){try{for(var t,e=1;V.length;)V.length>e&&V.sort(gt),t=V.shift(),e=V.length,qn(t)}finally{V.length=ve.__r=0}}function bt(t,e,n,i,a,r,o,l,p,d,u){var m,c,h,_,v,g,x=i&&i.__k||xe,k=e.length;for(p=Bn(n,e,x,p,k),m=0;m<k;m++)(h=n.__k[m])!=null&&(c=h.__i!=-1&&x[h.__i]||be,h.__i=m,g=Ve(t,h,c,a,r,o,l,p,d,u),_=h.__e,h.ref&&c.ref!=h.ref&&(c.ref&&je(c.ref,null,h),u.push(h.ref,h.__c||_,h)),v==null&&_!=null&&(v=_),4&h.__u?(p=xt(h,p,t),c.__e&&(c.__e=null)):typeof h.type=="function"&&g!==void 0?p=g:_&&(p=_.nextSibling),h.__u&=-7);return n.__e=v,p}function Bn(t,e,n,i,a){var r,o,l,p,d,u=n.length,m=u,c=0;for(t.__k=new Array(a),r=0;r<a;r++)(o=e[r])!=null&&typeof o!="boolean"&&typeof o!="function"?(typeof o=="string"||typeof o=="number"||typeof o=="bigint"||o.constructor==String?o=t.__k[r]=me(null,o,null,null,null):ke(o)?o=t.__k[r]=me(M,{children:o},null,null,null):o.constructor===void 0&&o.__b>0?o=t.__k[r]=me(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):t.__k[r]=o,p=r+c,o.__=t,o.__b=t.__b+1,l=null,(d=o.__i=Vn(o,n,p,m))!=-1&&(m--,(l=n[d])&&(l.__u|=2)),l==null||l.__v==null?(d==-1&&(a>u?c--:a<u&&c++),typeof o.type!="function"&&(o.__u|=4)):d!=p&&(d==p-1?c--:d==p+1?c++:(d>p?c--:c++,o.__u|=4))):t.__k[r]=null;if(m)for(r=0;r<u;r++)(l=n[r])!=null&&(2&l.__u)==0&&(l.__e==i&&(i=K(l)),wt(l,l));return i}function xt(t,e,n){var i,a;if(typeof t.type=="function"){for(i=t.__k,a=0;i&&a<i.length;a++)i[a]&&(i[a].__=t,e=xt(i[a],e,n));return e}t.__e!=e&&(e&&t.type&&!e.parentNode&&(e=K(t)),e=n.insertBefore(t.__e,e||null));do e=e&&e.nextSibling;while(e!=null&&e.nodeType==8);return e}function Vn(t,e,n,i){var a,r,o,l=t.key,p=t.type,d=e[n],u=d!=null&&(2&d.__u)==0;if(d===null&&l==null||u&&l==d.key&&p==d.type)return n;if(i>(u?1:0)){for(a=n-1,r=n+1;a>=0||r<e.length;)if((d=e[o=a>=0?a--:r++])!=null&&(2&d.__u)==0&&l==d.key&&p==d.type)return o}return-1}function pt(t,e,n){e[0]=="-"?t.setProperty(e,n??""):t[e]=n==null?"":typeof n!="number"||Yn.test(e)?n:n+"px"}function fe(t,e,n,i,a){var r,o;e:if(e=="style")if(typeof n=="string")t.style.cssText=n;else{if(typeof i=="string"&&(t.style.cssText=i=""),i)for(e in i)n&&e in n||pt(t.style,e,"");if(n)for(e in n)i&&n[e]==i[e]||pt(t.style,e,n[e])}else if(e[0]=="o"&&e[1]=="n")r=e!=(e=e.replace(mt,"$1")),o=e.toLowerCase(),e=o in t||e=="onFocusOut"||e=="onFocusIn"?o.slice(2):e.slice(2),t.l||(t.l={}),t.l[e+r]=n,n?i?n[ne]=i[ne]:(n[ne]=qe,t.addEventListener(e,r?Ne:Ye,r)):t.removeEventListener(e,r?Ne:Ye,r);else{if(a=="http://www.w3.org/2000/svg")e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!="width"&&e!="height"&&e!="href"&&e!="list"&&e!="form"&&e!="tabIndex"&&e!="download"&&e!="rowSpan"&&e!="colSpan"&&e!="role"&&e!="popover"&&e in t)try{t[e]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&e[4]!="-"?t.removeAttribute(e):t.setAttribute(e,e=="popover"&&n==1?"":n))}}function ut(t){return function(e){if(this.l){var n=this.l[e.type+t];if(e[ge]==null)e[ge]=qe++;else if(e[ge]<n[ne])return;return n(C.event?C.event(e):e)}}}function Ve(t,e,n,i,a,r,o,l,p,d){var u,m,c,h,_,v,g,x,k,E,R,F,O,U,D,W,y=e.type;if(e.constructor!==void 0)return null;128&n.__u&&(p=!!(32&n.__u),r=[l=e.__e=n.__e]),(u=C.__b)&&u(e);e:if(typeof y=="function"){m=o.length;try{if(k=e.props,E=y.prototype&&y.prototype.render,R=(u=y.contextType)&&i[u.__c],F=u?R?R.props.value:u.__:i,n.__c?x=(c=e.__c=n.__c).__=c.__E:(E?e.__c=c=new y(k,F):(e.__c=c=new _e(k,F),c.constructor=y,c.render=Kn),R&&R.sub(c),c.state||(c.state={}),c.__n=i,h=c.__d=!0,c.__h=[],c._sb=[]),E&&c.__s==null&&(c.__s=c.state),E&&y.getDerivedStateFromProps!=null&&(c.__s==c.state&&(c.__s=B({},c.__s)),B(c.__s,y.getDerivedStateFromProps(k,c.__s))),_=c.props,v=c.state,c.__v=e,h)E&&y.getDerivedStateFromProps==null&&c.componentWillMount!=null&&c.componentWillMount(),E&&c.componentDidMount!=null&&c.__h.push(c.componentDidMount);else{if(E&&y.getDerivedStateFromProps==null&&k!==_&&c.componentWillReceiveProps!=null&&c.componentWillReceiveProps(k,F),e.__v==n.__v||!c.__e&&c.shouldComponentUpdate!=null&&c.shouldComponentUpdate(k,c.__s,F)===!1){e.__v!=n.__v&&(c.props=k,c.state=c.__s,c.__d=!1),e.__e=n.__e,e.__k=n.__k,e.__k.some(function(P){P&&(P.__=e)}),xe.push.apply(c.__h,c._sb),c._sb=[],c.__h.length&&o.push(c),l=K(n);break e}c.componentWillUpdate!=null&&c.componentWillUpdate(k,c.__s,F),E&&c.componentDidUpdate!=null&&c.__h.push(function(){c.componentDidUpdate(_,v,g)})}if(c.context=F,c.props=k,c.__P=t,c.__e=!1,O=C.__r,U=0,E)c.state=c.__s,c.__d=!1,O&&O(e),u=c.render(c.props,c.state,c.context),xe.push.apply(c.__h,c._sb),c._sb=[];else do c.__d=!1,O&&O(e),u=c.render(c.props,c.state,c.context),c.state=c.__s;while(c.__d&&++U<25);c.state=c.__s,c.getChildContext!=null&&(i=B(B({},i),c.getChildContext())),E&&!h&&c.getSnapshotBeforeUpdate!=null&&(g=c.getSnapshotBeforeUpdate(_,v)),D=u!=null&&u.type===M&&u.key==null?kt(u.props.children):u,l=bt(t,ke(D)?D:[D],e,n,i,a,r,o,l,p,d),c.base=e.__e,e.__u&=-161,c.__h.length&&o.push(c),x&&(c.__E=c.__=null)}catch(P){if(o.length=m,e.__v=null,p||r!=null){if(P.then){for(e.__u|=p?160:128;l&&l.nodeType==8&&l.nextSibling;)l=l.nextSibling;r!=null&&(r[r.indexOf(l)]=null),e.__e=l}else if(r!=null)for(W=r.length;W--;)Be(r[W])}else e.__e=n.__e;e.__k==null&&(e.__k=n.__k||[]),P.then||vt(e),C.__e(P,e,n)}}else r==null&&e.__v==n.__v?(e.__k=n.__k,e.__e=n.__e):l=e.__e=jn(n.__e,e,n,i,a,r,o,p,d);return(u=C.diffed)&&u(e),128&e.__u?void 0:l}function vt(t){t&&(t.__c&&(t.__c.__e=!0),t.__k&&t.__k.some(vt))}function yt(t,e,n){for(var i=0;i<n.length;i++)je(n[i],n[++i],n[++i]);C.__c&&C.__c(e,t),t.some(function(a){try{t=a.__h,a.__h=[],t.some(function(r){r.call(a)})}catch(r){C.__e(r,a.__v)}})}function kt(t){return typeof t!="object"||t==null||t.__b>0?t:ke(t)?t.map(kt):t.constructor!==void 0?null:B({},t)}function jn(t,e,n,i,a,r,o,l,p){var d,u,m,c,h,_,v,g=n.props||be,x=e.props,k=e.type;if(k=="svg"?a="http://www.w3.org/2000/svg":k=="math"?a="http://www.w3.org/1998/Math/MathML":a||(a="http://www.w3.org/1999/xhtml"),r!=null){for(d=0;d<r.length;d++)if((h=r[d])&&"setAttribute"in h==!!k&&(k?h.localName==k:h.nodeType==3)){t=h,r[d]=null;break}}if(t==null){if(k==null)return document.createTextNode(x);t=document.createElementNS(a,k,x.is&&x),l&&(C.__m&&C.__m(e,r),l=!1),r=null}if(k==null)g===x||l&&t.data==x||(t.data=x);else{if(r=k=="textarea"&&x.defaultValue!=null?null:r&&ye.call(t.childNodes),!l&&r!=null)for(g={},d=0;d<t.attributes.length;d++)g[(h=t.attributes[d]).name]=h.value;for(d in g)h=g[d],d=="dangerouslySetInnerHTML"?m=h:d=="children"||d in x||d=="value"&&"defaultValue"in x||d=="checked"&&"defaultChecked"in x||fe(t,d,null,h,a);for(d in x)h=x[d],d=="children"?c=h:d=="dangerouslySetInnerHTML"?u=h:d=="value"?_=h:d=="checked"?v=h:l&&typeof h!="function"||g[d]===h||fe(t,d,h,g[d],a);if(u)l||m&&(u.__html==m.__html||u.__html==t.innerHTML)||(t.innerHTML=u.__html),e.__k=[];else if(m&&(t.innerHTML=""),bt(e.type=="template"?t.content:t,ke(c)?c:[c],e,n,i,k=="foreignObject"?"http://www.w3.org/1999/xhtml":a,r,o,r?r[0]:n.__k&&K(n,0),l,p),r!=null)for(d=r.length;d--;)Be(r[d]);l&&k!="textarea"||(d="value",k=="progress"&&_==null?t.removeAttribute("value"):_!=null&&(_!==t[d]||k=="progress"&&!_||k=="option"&&_!=g[d])&&fe(t,d,_,g[d],a),d="checked",v!=null&&v!=t[d]&&fe(t,d,v,g[d],a))}return t}function je(t,e,n){try{if(typeof t=="function"){var i=typeof t.__u=="function";i&&t.__u(),i&&e==null||(t.__u=t(e))}else t.current=e}catch(a){C.__e(a,n)}}function wt(t,e,n){var i,a;if(C.unmount&&C.unmount(t),(i=t.ref)&&(i.current&&i.current!=t.__e||je(i,null,e)),(i=t.__c)!=null){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(r){C.__e(r,e)}i.base=i.__P=i.__n=null}if(i=t.__k)for(a=0;a<i.length;a++)i[a]&&wt(i[a],e,n||typeof t.type!="function");n||Be(t.__e),t.__c=t.__=t.__e=void 0}function Kn(t,e,n){return this.constructor(t,n)}function Ke(t,e,n){var i,a,r,o;e==document&&(e=document.documentElement),C.__&&C.__(t,e),a=(i=typeof n=="function")?null:n&&n.__k||e.__k,r=[],o=[],Ve(e,t=(!i&&n||e).__k=Nn(M,null,[t]),a||be,be,e.namespaceURI,!i&&n?[n]:a?null:e.firstChild?ye.call(e.childNodes):null,r,!i&&n?n:a?a.__e:e.firstChild,i,o),yt(r,t,o),t.props.children=null}ye=xe.slice,C={__e:function(t,e,n,i){for(var a,r,o;e=e.__;)if((a=e.__c)&&!a.__)try{if((r=a.constructor)&&r.getDerivedStateFromError!=null&&(a.setState(r.getDerivedStateFromError(t)),o=a.__d),a.componentDidCatch!=null&&(a.componentDidCatch(t,i||{}),o=a.__d),o)return a.__E=a}catch(l){t=l}throw t}},ht=0,Hn=function(t){return t!=null&&t.constructor===void 0},_e.prototype.setState=function(t,e){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=B({},this.state),typeof t=="function"&&(t=t(B({},n),this.props)),t&&B(n,t),t!=null&&this.__v&&(e&&this._sb.push(e),dt(this))},_e.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),dt(this))},_e.prototype.render=M,V=[],ft=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,gt=function(t,e){return t.__v.__b-e.__v.__b},ve.__r=0,We=Math.random().toString(8),ge="__d"+We,ne="__a"+We,mt=/(PointerCapture)$|Capture$/i,qe=0,Ye=ut(!1),Ne=ut(!0),Wn=0;var Z,A,Xe,Ct,ie=0,$t=[],T=C,St=T.__b,At=T.__r,Mt=T.diffed,Tt=T.__c,It=T.unmount,Et=T.__;function Ce(t,e){T.__h&&T.__h(A,t,ie||e),ie=0;var n=A.__H||(A.__H={__:[],__h:[]});return t>=n.__.length&&n.__.push({}),n.__[t]}function $(t){return ie=1,Xn(Pt,t)}function Xn(t,e,n){var i=Ce(Z++,2);if(i.t=t,!i.__c&&(i.__=[n?n(e):Pt(void 0,e),function(l){var p=i.__N?i.__N[0]:i.__[0],d=i.t(p,l);p!==d&&(i.__N=[d,i.__[1]],i.__c.setState({}))}],i.__c=A,!A.__f)){var a=function(l,p,d){if(!i.__c.__H)return!0;var u=!1,m=i.__c.props!==l;if(i.__c.__H.__.some(function(h){if(h.__N){u=!0;var _=h.__[0];h.__=h.__N,h.__N=void 0,_!==h.__[0]&&(m=!0)}}),r){var c=r.call(this,l,p,d);return u?c||m:c}return!u||m};A.__f=!0;var r=A.shouldComponentUpdate,o=A.componentWillUpdate;A.componentWillUpdate=function(l,p,d){if(this.__e){var u=r;r=void 0,a(l,p,d),r=u}o&&o.call(this,l,p,d)},A.shouldComponentUpdate=a}return i.__N||i.__}function I(t,e){var n=Ce(Z++,3);!T.__s&&Ze(n.__H,e)&&(n.__=t,n.u=e,A.__H.__h.push(n))}function Ut(t,e){var n=Ce(Z++,4);!T.__s&&Ze(n.__H,e)&&(n.__=t,n.u=e,A.__h.push(n))}function H(t){return ie=5,Lt(function(){return{current:t}},[])}function Lt(t,e){var n=Ce(Z++,7);return Ze(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function Se(t,e){return ie=8,Lt(function(){return t},e)}function Jn(){for(var t;t=$t.shift();){var e=t.__H;if(t.__P&&e)try{e.__h.some(we),e.__h.some(Je),e.__h=[]}catch(n){e.__h=[],T.__e(n,t.__v)}}}T.__b=function(t){A=null,St&&St(t)},T.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),Et&&Et(t,e)},T.__r=function(t){At&&At(t),Z=0;var e=(A=t.__c).__H;e&&(Xe===A?(e.__h=[],A.__h=[],e.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(e.__h.some(we),e.__h.some(Je),e.__h=[],Z=0)),Xe=A},T.diffed=function(t){Mt&&Mt(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&($t.push(e)!==1&&Ct===T.requestAnimationFrame||((Ct=T.requestAnimationFrame)||Zn)(Jn)),e.__H.__.some(function(n){n.u&&(n.__H=n.u,n.u=void 0)})),Xe=A=null},T.__c=function(t,e){e.some(function(n){try{n.__h.some(we),n.__h=n.__h.filter(function(i){return!i.__||Je(i)})}catch(i){e.some(function(a){a.__h&&(a.__h=[])}),e=[],T.__e(i,n.__v)}}),Tt&&Tt(t,e)},T.unmount=function(t){It&&It(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.some(function(i){try{we(i)}catch(a){e=a}}),n.__H=void 0,e&&T.__e(e,n.__v))};var zt=typeof requestAnimationFrame=="function";function Zn(t){var e,n=function(){clearTimeout(i),zt&&cancelAnimationFrame(e),setTimeout(t)},i=setTimeout(n,35);zt&&(e=requestAnimationFrame(n))}function we(t){var e=A,n=t.__c;typeof n=="function"&&(t.__c=void 0,n()),A=e}function Je(t){var e=A;t.__c=t.__(),A=e}function Ze(t,e){return!t||t.length!==e.length||e.some(function(n,i){return n!==t[i]})}function Pt(t,e){return typeof e=="function"?e(t):e}function j(t){let e=t%100;if(e>=11&&e<=13)return`${t}th`;switch(t%10){case 1:return`${t}st`;case 2:return`${t}nd`;case 3:return`${t}rd`;default:return`${t}th`}}function Ae(t){if(t==null)return"";if(t<60)return"less than a minute";let e=Math.round(t/60);return e<60?`about ${e} min`:`about ${Math.round(e/60)} hr`}function Me(t){let e=Math.max(0,Math.floor(t)),n=Math.floor(e/3600),i=Math.floor(e%3600/60),a=String(e%60).padStart(2,"0");return n?`${n}:${String(i).padStart(2,"0")}:${a}`:`${i}:${a}`}function Ft(t,e){switch(t){case"hangup":return{title:"Call ended",body:`Thanks for talking with ${e}.`};case"left":return{title:"You left the line",body:"You can call again whenever you like."};case"missed":return{title:"You missed your turn",body:`${e} was ready, but the call wasn't joined in time.`};case"timeout":return{title:"Still busy",body:`Sorry for the wait. ${e} is still on other calls. Chat is open meanwhile.`};case"limit":return{title:"Time is up",body:"This call reached its time limit."};case"busy":return{title:"All lines are busy",body:"Try again in a few minutes, or keep chatting."};case"mic-denied":return{title:"Microphone needed",body:"Allow the microphone in your browser to talk, or keep chatting."};case"credits":case"unavailable":return{title:"Calls are unavailable",body:"Calls are not available right now. Chat is open."};default:return{title:"The call dropped",body:"Something interrupted the call. Try again."}}}function Rt(t){let e=[],n=/(\*\*[^*]+\*\*|`[^`]+`|\[[^\]]+\]\((https?:\/\/[^)\s]+)\)|https?:\/\/[^\s<>()]+[^\s<>().,;:!?'"]|\*[^*\s][^*]*\*)/g,i=0,a;for(;a=n.exec(t);){a.index>i&&e.push({t:"text",v:t.slice(i,a.index)});let r=a[0];r.startsWith("**")?e.push({t:"b",v:r.slice(2,-2)}):r.startsWith("`")?e.push({t:"code",v:r.slice(1,-1)}):r.startsWith("[")?e.push({t:"link",v:r.slice(1,r.indexOf("]")),href:a[2]}):r.startsWith("http")?e.push({t:"link",v:r,href:r}):e.push({t:"i",v:r.slice(1,-1)}),i=a.index+r.length}return i<t.length&&e.push({t:"text",v:t.slice(i)}),e}function Dt(t){let e=[];for(let n of t.split(/\n{2,}/)){let i=n.split(`
41
+ `);i.length&&i.every(a=>/^\s*[-*•]\s+/.test(a))?e.push({t:"ul",items:i.map(a=>Rt(a.replace(/^\s*[-*•]\s+/,"")))}):e.push({t:"p",parts:Rt(n)})}return e}var Ot={cx:.5,cy:.12,span:.06};function Ht(t,e,n){let i=t?.face?.eyes,a=t?.face?.chin;if(!i||!a||!e||!n)return Ot;let r=(i.left.x+i.right.x)/2,o=(i.left.y+i.right.y)/2,l=(a.y-o)/n;return l>.005&&l<.5?{cx:r/e,cy:(o+a.y)/2/n,span:l}:Ot}var Te={faceFraction:.26,at:{x:.5,y:.5}},Wt={faceFraction:.14,at:{x:.5,y:.34}},Yt={faceFraction:.16,at:{x:.5,y:.22}},Nt={fit:"height"};function qt(t,e,n,i,a){if("fit"in a){let l=i*e;return{width:l,height:i,left:n/2-t.cx*l,top:0}}let r=i*a.faceFraction/t.span,o=r*e;return{width:o,height:r,left:n*a.at.x-t.cx*o,top:i*a.at.y-t.cy*r}}var Gn=0;function s(t,e,n,i,a,r){e||(e={});var o,l,p=e;if("ref"in p)for(l in p={},e)l=="ref"?o=e[l]:p[l]=e[l];var d={type:t,props:p,key:n,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Gn,__i:-1,__u:0,__source:a,__self:r};if(typeof t=="function"&&(o=t.defaultProps))for(l in o)p[l]===void 0&&(p[l]=o[l]);return C.vnode&&C.vnode(d),d}var N=(t,e)=>s("svg",{width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.9","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true",focusable:"false",children:e}),ae=({size:t=20})=>N(t,s("path",{d:"M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.6a.5.5 0 0 1-.8-.4V16h0A2.5 2.5 0 0 1 4 13.5z"})),G=({size:t=20})=>N(t,s("path",{d:"M5.2 3.5h3l1.6 4.2-2 1.4a12 12 0 0 0 7.1 7.1l1.4-2 4.2 1.6v3a1.7 1.7 0 0 1-1.8 1.7A16.6 16.6 0 0 1 3.5 5.3 1.7 1.7 0 0 1 5.2 3.5z"})),Bt=({size:t=22})=>N(t,s("path",{d:"M3 13.6c5-4.4 13-4.4 18 0l-1.7 2.6-3.6-1.3v-2.6a11 11 0 0 0-7.4 0v2.6l-3.6 1.3z"})),Vt=({size:t=20})=>N(t,s(M,{children:[s("rect",{x:"9",y:"3",width:"6",height:"11",rx:"3"}),s("path",{d:"M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21"})]})),jt=({size:t=20})=>N(t,s(M,{children:[s("path",{d:"M9 9v2a3 3 0 0 0 5.1 2.1M15 9.4V6a3 3 0 0 0-5.7-1.3"}),s("path",{d:"M5.5 11a6.5 6.5 0 0 0 10.6 5M18.4 12.5a6.5 6.5 0 0 0 .1-1.5M12 17.5V21M3 3l18 18"})]})),Ie=({size:t=18})=>N(t,s("path",{d:"M6 6l12 12M18 6L6 18"})),Kt=({size:t=18})=>N(t,s("path",{d:"M12 19V5M5.5 11.5L12 5l6.5 6.5"})),Xt=({size:t=18})=>N(t,s("path",{d:"M15 5l-7 7 7 7"})),Jt=({size:t=14})=>N(t,s("path",{d:"M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z"})),Zt=({size:t=14})=>N(t,s("path",{d:"M4 12a8 8 0 1 0 2.3-5.6M4 4v4h4"}));var Ge={current:null};function Qn(t){return t?t.speaking?"speaking":t.agentState==="thinking"?"reasoning":t.agentState==="listening"||t.phase==="live"?"listening":"idle":"idle"}function Gt({client:t,call:e,state:n,src:i,onStatus:a}){let r=H(null),[o,l]=$(!1),p=H(!1),d=(()=>{try{return new URL(i).origin}catch{return null}})(),u=(c,h)=>{let _=r.current?.contentWindow;_&&d&&_.postMessage({cx:"face",...c},d,h??[])};I(()=>{if(!d){a("unavailable");return}let c=!1,h=v=>{if(v.source!==r.current?.contentWindow||v.origin!==d)return;let g=v.data;g?.cx==="face"&&(g.type==="loaded"?(p.current=!0,l(!0),t.videoAvatar().then(x=>{c||(x?u({type:"init",avatar:x}):a("unavailable"))}).catch(()=>!c&&a("unavailable"))):g.type==="ready"?(Ge.current=typeof g.faceEmotion=="string"?g.faceEmotion:null,a("ready")):g.type==="unavailable"&&a("unavailable"))};window.addEventListener("message",h);let _=setTimeout(()=>!c&&!p.current&&a("unavailable"),15e3);return()=>{c=!0,clearTimeout(_),window.removeEventListener("message",h)}},[t,d]);let m=Qn(n);return I(()=>{o&&u({type:"state",state:m})},[m,o]),I(()=>{if(!e||!o)return;let c=[e.on("face",({corr:v,payload:g})=>u({type:"batch",corr:v,payload:g},[g.buffer])),e.on("line",({corr:v,event:g})=>{u(g==="audible"?{type:"audible",corr:v,ms:e.audible()?.ms??0}:{type:"end",corr:v})})],h=0,_=()=>{let v=e.audible();v&&u({type:"clock",corr:v.corr,ms:v.ms}),h=requestAnimationFrame(_)};return h=requestAnimationFrame(_),()=>{c.forEach(v=>v()),cancelAnimationFrame(h)}},[e,o]),d?s("iframe",{ref:r,class:"face-frame",src:i,title:"","aria-hidden":"true",tabIndex:-1,allow:"autoplay",sandbox:"allow-scripts allow-same-origin",referrerpolicy:"strict-origin"}):null}function ei(){if(typeof document>"u")return!1;let t=navigator.userAgent;return/Safari\//.test(t)&&!/(Chrome|Chromium|Edg|OPR|Firefox)\//.test(t)?!1:document.createElement("video").canPlayType('video/webm; codecs="vp9"')!==""}var ti=()=>typeof matchMedia<"u"&&matchMedia("(prefers-reduced-motion: reduce)").matches;function re({agent:t,shot:e,talking:n=!1,still:i=!1,class:a}){let r=H(null),[o,l]=$({w:0,h:0}),[p,d]=$(null),[u,m]=$({}),c=t.video,h=c?.anchor?.alphaUrl??c?.anchor?.url??null,_=!i&&!ti()&&ei(),v=c?.clips.idle?.alphaUrl??null,g=c?.clips.talking?.alphaUrl??v;if(Ut(()=>{let U=r.current;if(!U)return;let D=()=>l({w:U.clientWidth,h:U.clientHeight});if(D(),typeof ResizeObserver>"u")return;let W=new ResizeObserver(D);return W.observe(U),()=>W.disconnect()},[]),!c||!h)return s("div",{ref:r,class:`portrait portrait--initial ${a??""}`,"aria-hidden":"true",children:s("span",{children:(t.name||"?").slice(0,1).toUpperCase()})});let x=p?p.w/p.h:.75,k=Ht(c,p?.w??0,p?.h??0),E=o.w&&o.h?qt(k,x,o.w,o.h,e):null,R=E?{width:`${E.width}px`,height:`${E.height}px`,left:`${E.left}px`,top:`${E.top}px`}:{opacity:0},F=_&&!!v&&!!u.idle,O=_&&!!g&&g!==v&&!!u.talk&&n;return s("div",{ref:r,class:`portrait ${a??""}`,"aria-hidden":"true",children:[s("img",{class:"portrait__media",src:h,alt:"",draggable:!1,style:{...R,opacity:E?F?0:1:0},onLoad:U=>{let D=U.currentTarget;d({w:D.naturalWidth,h:D.naturalHeight})}}),_&&v?s(Qt,{src:v,style:R,visible:F&&!O,onReady:()=>m(U=>({...U,idle:!0}))}):null,_&&g&&g!==v?s(Qt,{src:g,style:R,visible:O,onReady:()=>m(U=>({...U,talk:!0}))}):null]})}function Qt({src:t,style:e,visible:n,onReady:i}){let a=H(null);return I(()=>{let r=a.current;r&&(n?r.play().catch(()=>{}):r.pause())},[n]),s("video",{ref:a,class:"portrait__media portrait__clip",src:t,muted:!0,loop:!0,playsInline:!0,preload:"auto",style:{...e,opacity:n?1:0},onLoadedData:i})}var Qe="cxyz:greeted",en="cxyz:introduced";function se(t,e){try{return e!==void 0&&localStorage.setItem(t,e),localStorage.getItem(t)}catch{return null}}function ni(){try{let t=window.AudioContext??window.webkitAudioContext,e=new t,n=e.currentTime;[660,880].forEach((i,a)=>{let r=e.createOscillator(),o=e.createGain();r.type="sine",r.frequency.value=i,o.gain.setValueAtTime(0,n+a*.16),o.gain.linearRampToValueAtTime(.18,n+a*.16+.02),o.gain.exponentialRampToValueAtTime(1e-4,n+a*.16+.5),r.connect(o).connect(e.destination),r.start(n+a*.16),r.stop(n+a*.16+.55)}),setTimeout(()=>{e.close()},1200)}catch{}}function ii(t){let[e,n]=$(t.chat.messages),[i,a]=$(t.chat.isBusy);return I(()=>{let r=t.chat.on("messages",n),o=t.chat.on("busy",a);return()=>{r(),o()}},[t]),{messages:e,busy:i}}function ai(t){let[e,n]=$(t.call),[i,a]=$(t.call?.state??null),[r,o]=$([]);return I(()=>t.on("call",l=>l&&n(l)),[t]),I(()=>{if(!e)return;a(e.state),o([]);let l=[e.on("state",a),e.on("caption",p=>o(d=>[...d.filter(u=>u.id!==p.id),p].slice(-4))),e.on("captionRemoved",p=>o(d=>d.filter(u=>u.id!==p)))];return()=>l.forEach(p=>p())},[e]),{call:e,state:i,captions:r,reset:()=>n(null)}}function ri(t,e){let[n,i]=$(Date.now());return I(()=>{if(!e)return;let a=setInterval(()=>i(Date.now()),1e3);return()=>clearInterval(a)},[e]),t?Math.max(0,(n-t)/1e3):0}function si(t,e,n){I(()=>{if(!t||!n)return;let i=0,a=0,r=()=>{let o=t.voiceLevel();a=a*.7+o*.3,e.current?.style.setProperty("--cx-lvl",a.toFixed(3)),i=requestAnimationFrame(r)};return i=requestAnimationFrame(r),()=>cancelAnimationFrame(i)},[t,n,e])}function tn({parts:t}){return s(M,{children:t.map((e,n)=>e.t==="b"?s("strong",{children:e.v},n):e.t==="i"?s("em",{children:e.v},n):e.t==="code"?s("code",{children:e.v},n):e.t==="link"?s("a",{href:e.href,target:"_blank",rel:"noopener noreferrer nofollow",children:e.v},n):e.v.split(`
42
+ `).map((i,a,r)=>s(M,{children:[i,a<r.length-1?s("br",{}):null]},`${n}.${a}`)))})}function oi({text:t}){return s(M,{children:Dt(t).map((e,n)=>e.t==="ul"?s("ul",{children:e.items.map((i,a)=>s("li",{children:s(tn,{parts:i})},a))},n):s("p",{children:s(tn,{parts:e.parts})},n))})}function nn({client:t,config:e,bind:n,onView:i}){let a=t.agent,r=t.features,o=e.showChat&&r.chat,l=e.showCall&&r.call,[p,d]=$(e.open?o?"chat":"call":"closed"),[u,m]=$(!1),[c,h]=$(!1),{messages:_,busy:v}=ii(t),{call:g,state:x,captions:k,reset:E}=ai(t),[R,F]=$(""),O=H(null),U=H(null),D=H(null),W=e.subtitle??a.tagline,y=a.name||"Assistant",P=Se(f=>{d(f),i(f)},[i]),X=Se(()=>{m(!0),setTimeout(()=>{m(!1),P("closed")},200)},[P]),q=Se((f=o?"chat":"call")=>{h(!1),se(Qe,"1"),P(f),f==="chat"&&t.chat.load().catch(()=>{})},[o,t,P]);I(()=>n({open:q,close:X}),[n,q,X]),I(()=>{e.open&&o&&t.chat.load().catch(()=>{})},[t,e.open,o]),I(()=>{if(!e.greeting||se(Qe))return;let f=setTimeout(()=>h(!0),e.greetingDelay*1e3);return()=>clearTimeout(f)},[e.greeting,e.greetingDelay]);let[Ue,ln]=$(()=>!se(en));I(()=>{if(!Ue)return;let f=setTimeout(()=>{ln(!1),se(en,"1")},5e3);return()=>clearTimeout(f)},[Ue]),I(()=>{if(p==="closed")return;let f=L=>{L.key==="Escape"&&X()};return window.addEventListener("keydown",f),()=>window.removeEventListener("keydown",f)},[p,X]),I(()=>{let f=O.current;f&&(f.scrollTop=f.scrollHeight)},[_,p,x?.phase]),I(()=>{p==="chat"&&setTimeout(()=>U.current?.focus({preventScroll:!0}),60)},[p]);let Q=e.face&&!!a.video,[de,cn]=$("loading"),w=x?.phase??"idle";I(()=>{if(!(w!=="ready"||!g)){if(ni(),p==="call"){if(!Q||de!=="loading"){g.accept();return}let f=setTimeout(()=>g.accept(),3e3);return()=>clearTimeout(f)}if(typeof document<"u"&&document.hidden){let f=document.title;document.title=`\u25CF ${y} is ready for you`;let L=()=>{document.title=f,document.removeEventListener("visibilitychange",L)};document.addEventListener("visibilitychange",L)}}},[w,g,p,y,Q,de]);let nt=w==="live"||w==="connecting";si(g,D,nt&&p==="call");let pe=ri(x?.startedAt??null,w==="live"),Le=li(g,x?.position??1),ue=async()=>{P("call");try{await t.startCall({autoAccept:!1,...Q?{face:{emotion:()=>Ge.current}}:{}})}catch{}},Pe=async f=>{let L=f.trim();if(!(!L||v)){F(""),U.current&&(U.current.style.height="");try{await t.chat.send(L)}catch{}}},dn=_.length>0&&_[_.length-1].role==="agent"&&_[_.length-1].streaming;if(p==="closed"){let f=w==="queued"||w==="ready"||w==="live"||w==="connecting";return s("div",{class:`dock dock--${e.display}`,part:"launcher",children:[c?s("div",{class:"greeting",part:"greeting",role:"status",onClick:()=>q(),children:[e.greeting,s("button",{class:"greeting__close","aria-label":"Dismiss",onClick:L=>{L.stopPropagation(),h(!1),se(Qe,"1")},children:s(Ie,{size:14})})]}):null,s("button",{class:`presence presence--${e.display} ${f?"presence--live":""}`,part:"presence","aria-label":f?w==="queued"?`You are ${j(x?.position??1)} in line to call ${y}. Open`:`Back to your call with ${y}`:o?`Chat with ${y}`:`Call ${y}`,onClick:()=>q(f||!o?"call":"chat"),children:[e.display==="bubble"?s("span",{class:"presence__ring"}):null,s("span",{class:"presence__face",children:s(re,{agent:a,shot:e.display==="full"?Nt:e.display==="half"?Yt:Te})}),s("span",{class:"presence__dot"}),t.mode==="test"?s("span",{class:"testmode",title:"Test mode: this key only works on development sites",children:"TEST"}):null,w==="queued"?s("span",{class:"presence__badge","aria-hidden":"true",children:x?.position??1}):null,e.launcher==="bubble"&&!c?s("span",{class:"presence__label","aria-hidden":"true",children:f?w==="queued"?`${j(x?.position??1)} in line`:"Back to your call":o?`Chat with ${y}`:`Call ${y}`}):null]}),e.launcher==="bubble"?null:s("div",{class:`acts ${Ue?"acts--labelled":""}`,part:"actions",children:[o?s("button",{class:"act","aria-label":`Chat with ${y}`,onClick:()=>q("chat"),children:[s(ae,{size:20}),s("span",{class:"act__label","aria-hidden":"true",children:"Chat"})]}):null,l?s("button",{class:`act act--call ${f?"act--live":""}`,"aria-label":f?w==="queued"?`You are ${j(x?.position??1)} in line. Open your call`:"Back to your call":`Call ${y}`,onClick:()=>f?q("call"):void ue(),children:[s(G,{size:20}),s("span",{class:"act__label","aria-hidden":"true",children:f?w==="queued"?`${j(x?.position??1)} in line`:"On call":"Call"}),w==="queued"?s("span",{class:"act__badge","aria-hidden":"true",children:x?.position??1}):null]}):null]})]})}let pn=s("div",{class:"head",part:"header",children:[s("div",{class:"head__face",children:s(re,{agent:a,shot:Te,talking:!!dn})}),s("div",{class:"head__who",children:[s("div",{class:"head__name",children:y}),s("div",{class:"head__sub",children:[s("i",{}),v?"Typing\u2026":W||"Online"]})]}),l&&p==="chat"?s("button",{class:"icon-btn icon-btn--accent","aria-label":`Call ${y}`,title:`Call ${y}`,onClick:()=>g&&w!=="ended"?P("call"):void ue(),children:s(G,{size:18})}):null,s("button",{class:"icon-btn","aria-label":"Close",onClick:X,children:s(Ie,{})})]});if(p==="chat")return s("div",{class:`panel ${u?"is-closing":""}`,part:"panel",role:"dialog","aria-label":`Chat with ${y}`,children:[pn,g&&(w==="queued"||w==="ready")?s("div",{class:"banner",part:"banner",role:"status",children:[s("div",{class:"banner__text",children:w==="queued"?s(M,{children:["You're ",s("b",{children:j(x?.position??1)})," in line for a call \xB7 ",Ae(x?.etaSeconds??null)]}):s(M,{children:[s("b",{children:[y," is ready for you"]})," \xB7 ",x?.holdSeconds??30,"s to join"]})}),w==="ready"?s("button",{class:"btn btn--accent btn--glow",onClick:()=>{g.accept(),P("call")},children:"Join"}):s("button",{class:"btn",onClick:()=>P("call"),children:"View"})]}):null,s("div",{class:"log",ref:O,role:"log","aria-live":"polite","aria-relevant":"additions",children:[_.length===0?s("div",{class:"empty",children:[s("div",{class:"empty__face",children:s(re,{agent:a,shot:Te})}),s("div",{class:"empty__title",children:["Hi, I'm ",y]}),s("div",{class:"empty__body",children:[W?`${W}. `:"","Ask me anything",l?", or call me to talk":"","."]}),l?s("button",{class:"btn btn--accent empty__call",onClick:()=>g&&w!=="ended"?P("call"):void ue(),children:[s(G,{size:17})," Call ",y]}):null,e.suggestions.length?s("div",{class:"chips",children:e.suggestions.map(f=>s("button",{class:"chip",onClick:()=>{Pe(f)},children:[s(Jt,{}),f]},f))}):null]}):null,_.map(f=>f.role==="agent"&&f.streaming&&!f.text?s("div",{class:"msg msg--agent typing","aria-label":`${y} is typing`,children:[s("i",{}),s("i",{}),s("i",{})]},f.id):s(M,{children:[s("div",{class:`msg msg--${f.role} ${f.failed?"msg--failed":""} ${f.streaming?"caret":""}`,part:`message message-${f.role}`,children:f.role==="agent"?s(oi,{text:f.text}):f.text}),f.failed?s("button",{class:"msg__retry",onClick:()=>{t.chat.retry(f.id).catch(()=>{})},children:[s(Zt,{})," Not sent \xB7 Retry"]}):null]},f.id))]}),s("form",{class:"compose",part:"composer",onSubmit:f=>{f.preventDefault(),Pe(R)},children:s("div",{class:"compose__box",children:[s("textarea",{ref:U,rows:1,value:R,maxLength:2e3,placeholder:e.placeholder,"aria-label":"Message",onInput:f=>{let L=f.currentTarget;F(L.value),L.style.height="auto",L.style.height=`${Math.min(120,L.scrollHeight)}px`},onKeyDown:f=>{f.key==="Enter"&&!f.shiftKey&&!f.isComposing&&(f.preventDefault(),Pe(R))}}),s("button",{class:"send",type:"submit","aria-label":"Send",disabled:!R.trim()||v,children:s(Kt,{})})]})}),e.branding?s("div",{class:"foot",children:["Powered by"," ",s("a",{href:"https://character.xyz",target:"_blank",rel:"noopener noreferrer",children:"Character XYZ"})]}):null]});let S=x,Re=S?.position??1,un=Le>1?(Le-Re)/(Le-1):0,Fe=74,it=2*Math.PI*Fe,ee=S?.maxSeconds?S.maxSeconds-pe:null,hn=S?.agentState??"idle",fn=S?.speaking?"Speaking":hn==="thinking"?"Thinking\u2026":"Listening",gn=!S||w==="ended"||w==="idle",De=Ft(S?.endReason??null,y);return s("div",{class:`panel ${u?"is-closing":""}`,part:"panel",role:"dialog","aria-label":`Call with ${y}`,children:s("div",{class:`stage ${Q&&de==="ready"?"stage--face":""}`,ref:D,children:[s("div",{class:"stage__figure",style:{opacity:w==="queued"?.35:1,transition:"opacity .6s"},children:[s(re,{agent:a,shot:Wt,talking:!!S?.speaking}),Q?s("div",{class:`stage__face ${de==="ready"?"is-ready":""}`,children:s(Gt,{client:t,call:g,state:S,src:e.faceUrl,onStatus:cn})}):null]}),nt?s("div",{class:"voice"}):null,s("div",{class:"stage__veil"}),s("div",{class:"stage__top",children:[w==="live"?s("span",{class:`badge ${ee!=null&&ee<=60?"badge--warn":""}`,role:"timer","aria-label":"Call time",children:[s("i",{}),ee!=null&&ee<=60?`${Me(ee)} left`:Me(pe)]}):s("span",{}),s("div",{style:{display:"flex",gap:"6px"},children:[o?s("button",{class:"icon-btn","aria-label":"Chat",title:"Chat",onClick:()=>q("chat"),children:s(ae,{size:18})}):null,s("button",{class:"icon-btn","aria-label":"Minimise",onClick:X,children:s(Ie,{})})]})]}),s("div",{class:"stage__bottom","aria-live":"polite",children:[w==="joining"||w==="connecting"?s(M,{children:[s("div",{class:"stage__name",children:y}),s("div",{class:"stage__status",children:[s("span",{class:"spinner"})," ",w==="joining"?"Connecting\u2026":"Joining\u2026"]})]}):null,w==="queued"?s(M,{children:[s("div",{class:"line",role:"status","aria-label":`You are ${j(Re)} in line, ${Ae(S?.etaSeconds??null)}`,children:[s("svg",{width:"168",height:"168",viewBox:"0 0 168 168",children:[s("circle",{class:"line__track",cx:"84",cy:"84",r:Fe,fill:"none","stroke-width":"7"}),s("circle",{class:"line__fill",cx:"84",cy:"84",r:Fe,fill:"none","stroke-width":"7","stroke-linecap":"round","stroke-dasharray":it,"stroke-dashoffset":it*(1-Math.max(.06,un))})]}),s("div",{children:[s("div",{class:"line__num",children:j(Re)}),s("div",{class:"line__lbl",children:"in line"})]})]}),s("div",{class:"title",children:[y," is on other calls"]}),s("div",{class:"note",children:["Your turn in ",Ae(S?.etaSeconds??null),". We'll chime when it's time",o?", so feel free to keep chatting.":"."]}),s("div",{class:"btn-row",children:[o?s("button",{class:"btn btn--accent",onClick:()=>q("chat"),children:[s(ae,{size:18})," Keep chatting"]}):null,s("button",{class:"btn",onClick:()=>{g?.hangUp()},children:"Leave line"})]})]}):null,w==="ready"?s(M,{children:[s("div",{class:"title",children:[y," is ready for you"]}),s("div",{class:"note",children:["Join within ",S?.holdSeconds??30," seconds."]}),s("button",{class:"btn btn--accent btn--glow",onClick:()=>g?.accept(),children:[s(G,{size:18})," Join call"]})]}):null,w==="live"?s(M,{children:[s("div",{class:"stage__name",children:y}),s("div",{class:"stage__status",children:[S?.speaking?s("span",{class:"wave","aria-hidden":"true",children:[.6,1,.75,1,.55].map((f,L)=>s("i",{style:{"--k":f}},L))}):null,S?.muted?"You are muted":fn]}),s("div",{class:"captions",children:k.slice(-2).map((f,L,mn)=>s("div",{class:`captions__line ${L===mn.length-1?"captions__line--now":""}`,children:f.role==="visitor"?`You: ${f.text}`:f.text},f.id))}),s("div",{class:"controls",children:[s("div",{class:"ctl",children:[s("button",{class:`round ${S?.muted?"round--on":""}`,"aria-pressed":S?.muted,"aria-label":S?.muted?"Unmute":"Mute",onClick:()=>g?.setMuted(!S?.muted),children:S?.muted?s(jt,{size:22}):s(Vt,{size:22})}),s("span",{class:"round__label",children:S?.muted?"Unmute":"Mute"})]}),s("div",{class:"ctl",children:[s("button",{class:"round round--end","aria-label":"End call",onClick:()=>{g?.hangUp()},children:s(Bt,{size:26})}),s("span",{class:"round__label",children:"End"})]}),S?.speaking?s("div",{class:"ctl",children:[s("button",{class:"round","aria-label":`Interrupt ${y}`,onClick:()=>g?.interrupt(),children:s(Xt,{size:22})}),s("span",{class:"round__label",children:"Interrupt"})]}):null]})]}):null,gn?s(M,{children:[s("div",{class:"title",children:S?De.title:`Call ${y}`}),s("div",{class:"note",children:S?S.endReason==="hangup"&&pe?`${Me(pe)} \xB7 ${De.body}`:S.error??De.body:`Talk with ${y} in real time.`}),s("div",{class:"btn-row",children:[l&&S?.endReason!=="credits"&&S?.endReason!=="unavailable"?s("button",{class:"btn btn--accent",onClick:()=>{E(),ue()},children:[s(G,{size:18})," ",S?"Call again":"Start call"]}):null,o?s("button",{class:"btn",onClick:()=>q("chat"),children:[s(ae,{size:18})," Chat"]}):null]})]}):null]})]})})}function li(t,e){let n=H({call:null,start:e});return n.current.call!==t&&(n.current={call:t,start:e}),e>n.current.start&&(n.current.start=e),n.current.start}var tt={position:"bottom-right",mode:"auto",launcher:"bubble",display:"bubble",accent:"#7c5cff",radius:24,font:"",subtitle:null,greeting:"",greetingDelay:3,suggestions:[],placeholder:"Message",showChat:!0,showCall:!0,branding:!0,offsetX:20,offsetY:20,zIndex:2147483e3,open:!1,face:!0,faceUrl:"https://www.character.xyz/embed/face"},oe=(t,e,n)=>{let i=typeof t=="number"?t:typeof t=="string"&&t.trim()!==""?Number(t):NaN;return Number.isFinite(i)?Math.min(n,Math.max(e,i)):void 0},le=t=>{if(typeof t=="boolean")return t;if(t==="true"||t===""||t==="1")return!0;if(t==="false"||t==="0")return!1},et=(t,e=200)=>typeof t=="string"?t.slice(0,e):void 0;function ci(t){if(typeof t!="string")return;let e=t.trim();if(/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(e)||/^(rgb|rgba|hsl|hsla|oklch|oklab)\([0-9.,%\s/+-]+\)$/i.test(e)||/^[a-z]{3,20}$/i.test(e))return e}function di(t){if(typeof t!="string")return;let e=t.trim();return/^[\w\s,"'-]{1,120}$/.test(e)?e:void 0}function ce(t,e){if(!e||typeof e!="object")return t;let n={...t};return(e.position==="bottom-left"||e.position==="bottom-right")&&(n.position=e.position),(e.mode==="light"||e.mode==="dark"||e.mode==="auto")&&(n.mode=e.mode),(e.launcher==="bubble"||e.launcher==="actions")&&(n.launcher=e.launcher),(e.display==="bubble"||e.display==="half"||e.display==="full")&&(n.display=e.display),n.accent=ci(e.accent)??n.accent,n.radius=oe(e.radius,0,40)??n.radius,n.font=di(e.font)??n.font,e.subtitle===null?n.subtitle=null:n.subtitle=et(e.subtitle,80)??n.subtitle,n.greeting=et(e.greeting,160)??n.greeting,n.greetingDelay=oe(e.greetingDelay,0,120)??n.greetingDelay,Array.isArray(e.suggestions)?n.suggestions=e.suggestions.filter(i=>typeof i=="string"&&i.trim()!=="").map(i=>i.slice(0,80)).slice(0,4):typeof e.suggestions=="string"&&(n.suggestions=e.suggestions.split("|").map(i=>i.trim()).filter(Boolean).slice(0,4)),n.placeholder=et(e.placeholder,60)??n.placeholder,n.showChat=le(e.showChat)??n.showChat,n.showCall=le(e.showCall)??n.showCall,n.branding=le(e.branding)??n.branding,n.offsetX=oe(e.offsetX,0,200)??n.offsetX,n.offsetY=oe(e.offsetY,0,200)??n.offsetY,n.zIndex=oe(e.zIndex,0,2147483647)??n.zIndex,n.open=le(e.open)??n.open,n.face=le(e.face)??n.face,typeof e.faceUrl=="string"&&/^https?:\/\/[^\s"'<>]+$/.test(e.faceUrl.trim())&&(n.faceUrl=e.faceUrl.trim()),n}function an(t){let e={};for(let{name:n,value:i}of t){let a=n.replace(/^data-/,"").replace(/-([a-z])/g,(r,o)=>o.toUpperCase());e[a]=i}return e}var rn=`
43
+ :host {
44
+ --cx-accent: #7c5cff;
45
+ --cx-accent-ink: #fff;
46
+ --cx-radius: 24px;
47
+ --cx-font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
48
+ --cx-bg: rgba(255, 255, 255, 0.82);
49
+ --cx-solid: #ffffff;
50
+ --cx-ink: #14121a;
51
+ --cx-ink-2: #5b5866;
52
+ --cx-ink-3: #8d8a98;
53
+ --cx-line: rgba(20, 18, 26, 0.08);
54
+ --cx-bubble: rgba(20, 18, 26, 0.05);
55
+ --cx-shadow: 0 24px 64px -12px rgba(23, 16, 52, 0.28), 0 4px 16px -4px rgba(23, 16, 52, 0.12);
56
+ --cx-danger: #ef4444;
57
+ --cx-ok: #22c55e;
58
+ --cx-ease: cubic-bezier(0.22, 1, 0.36, 1);
59
+ --cx-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
60
+ all: initial;
61
+ position: fixed;
62
+ z-index: var(--cx-z, 2147483000);
63
+ bottom: var(--cx-oy, 20px);
64
+ font-family: var(--cx-font);
65
+ color: var(--cx-ink);
66
+ -webkit-font-smoothing: antialiased;
67
+ line-height: 1.45;
68
+ }
69
+ :host([data-side="right"]) { right: var(--cx-ox, 20px); }
70
+ :host([data-side="left"]) { left: var(--cx-ox, 20px); }
71
+ :host([data-theme="dark"]) {
72
+ --cx-bg: rgba(22, 20, 30, 0.78);
73
+ --cx-solid: #16141e;
74
+ --cx-ink: #f4f2fa;
75
+ --cx-ink-2: #b7b3c6;
76
+ --cx-ink-3: #85819a;
77
+ --cx-line: rgba(255, 255, 255, 0.09);
78
+ --cx-bubble: rgba(255, 255, 255, 0.07);
79
+ --cx-shadow: 0 24px 64px -12px rgba(0, 0, 0, 0.6), 0 4px 16px -4px rgba(0, 0, 0, 0.4);
80
+ }
81
+ *, *::before, *::after { box-sizing: border-box; }
82
+ button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
83
+ button:focus-visible, textarea:focus-visible, a:focus-visible { outline: 2px solid var(--cx-accent); outline-offset: 2px; }
84
+ .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
85
+
86
+ /* ------------------------------------------------------------ launcher */
87
+ .dock { display: flex; align-items: flex-end; gap: 10px; }
88
+ /* She sits in the corner and never moves; the buttons grow away from her. */
89
+ :host([data-side="right"]) .dock { flex-direction: row-reverse; }
90
+ .presence {
91
+ position: relative; width: 60px; height: 60px; border-radius: 50%; flex: none;
92
+ transition: transform .5s var(--cx-spring);
93
+ }
94
+ .presence:hover { transform: translateY(-2px) scale(1.05); }
95
+ /* ---- display: half body \u2014 her cut-out from the waist up, no frame, fading out at the waist */
96
+ .presence--half { width: 128px; height: 170px; border-radius: 0; filter: drop-shadow(0 10px 18px rgba(15, 10, 30, 0.28)); }
97
+ .presence--half .presence__face { border-radius: 0; background: none; box-shadow: none;
98
+ -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 98%); mask-image: linear-gradient(to bottom, #000 70%, transparent 98%); }
99
+ /* ---- display: full body \u2014 she stands in the corner, feet on the edge, a soft shadow under her */
100
+ .presence--full { width: 132px; height: 300px; border-radius: 0; filter: drop-shadow(0 6px 14px rgba(15, 10, 30, 0.22)); }
101
+ .presence--full .presence__face { border-radius: 0; background: none; box-shadow: none; }
102
+ .presence--full::before { content: ""; position: absolute; left: 22%; right: 22%; bottom: -4px; height: 10px; border-radius: 50%;
103
+ background: radial-gradient(closest-side, rgba(15, 10, 30, 0.35), transparent); }
104
+ .presence--half:hover, .presence--full:hover { transform: translateY(-3px); }
105
+ .presence--half .presence__dot { top: 10px; bottom: auto; right: 26px; }
106
+ .presence--full .presence__dot { top: 6px; bottom: auto; right: 34px; }
107
+ .presence--half .testmode, .presence--full .testmode { top: -6px; bottom: auto; }
108
+ .presence--full .presence__label { top: 22%; }
109
+ .presence--half .presence__badge, .presence--full .presence__badge { top: 0; right: 4px; }
110
+ .presence--half.presence--live::after, .presence--full.presence--live::after { display: none; }
111
+ .presence--half.presence--live, .presence--full.presence--live { animation: cx-figure-glow 1.8s ease-in-out infinite; }
112
+ .dock--half .greeting { bottom: 186px; }
113
+ .dock--full .greeting { bottom: 316px; }
114
+
115
+ /* What a tap does, on hover and keyboard focus. */
116
+ .presence__label {
117
+ position: absolute; top: 50%; transform: translate(6px, -50%); opacity: 0; pointer-events: none; white-space: nowrap;
118
+ padding: 7px 12px; border-radius: 999px; font-size: 13px; font-weight: 600; letter-spacing: -0.005em;
119
+ color: var(--cx-ink); background: var(--cx-solid); border: 1px solid var(--cx-line); box-shadow: var(--cx-shadow);
120
+ transition: opacity .2s, transform .3s var(--cx-ease);
121
+ }
122
+ :host([data-side="right"]) .presence__label { right: calc(100% + 10px); }
123
+ :host([data-side="left"]) .presence__label { left: calc(100% + 10px); transform: translate(-6px, -50%); }
124
+ .presence:hover .presence__label, .presence:focus-visible .presence__label { opacity: 1; transform: translate(0, -50%); }
125
+ /* Waiting in line: the place, on her. */
126
+ .presence__badge {
127
+ position: absolute; top: -4px; right: -4px; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
128
+ display: grid; place-items: center; font-size: 12px; font-weight: 800; font-variant-numeric: tabular-nums;
129
+ background: var(--cx-accent); color: var(--cx-accent-ink); box-shadow: 0 0 0 2px var(--cx-solid);
130
+ }
131
+ /* A call is open (or waiting): she breathes, so the way back is obvious. */
132
+ .presence--live::after { content: ""; position: absolute; inset: -5px; border-radius: 50%; border: 2px solid var(--cx-accent); animation: cx-glow-ring 1.8s ease-out infinite; }
133
+ .empty__call { margin-top: 4px; height: 40px; }
134
+ .presence__ring {
135
+ position: absolute; inset: -3px; border-radius: 50%;
136
+ background: conic-gradient(from var(--cx-angle, 0deg), var(--cx-accent), color-mix(in oklab, var(--cx-accent) 30%, #fff), var(--cx-accent));
137
+ animation: cx-spin 6s linear infinite;
138
+ }
139
+ .presence__face {
140
+ position: absolute; inset: 0; border-radius: 50%; overflow: hidden;
141
+ background: radial-gradient(120% 90% at 50% 10%, color-mix(in oklab, var(--cx-accent) 22%, var(--cx-solid)), var(--cx-solid));
142
+ box-shadow: inset 0 0 0 3px var(--cx-solid);
143
+ }
144
+ .presence__dot {
145
+ position: absolute; right: 3px; bottom: 3px; width: 14px; height: 14px; border-radius: 50%;
146
+ background: var(--cx-ok); box-shadow: 0 0 0 3px var(--cx-solid);
147
+ }
148
+ .acts { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
149
+ /* Call, the primary action, sits next to her on either side. */
150
+ :host([data-side="left"]) .acts { flex-direction: row-reverse; }
151
+ .act {
152
+ position: relative; display: inline-flex; align-items: center; justify-content: center;
153
+ height: 44px; min-width: 44px; padding: 0 12px; border-radius: 999px;
154
+ color: var(--cx-ink); background: var(--cx-bg);
155
+ backdrop-filter: blur(18px) saturate(1.6); -webkit-backdrop-filter: blur(18px) saturate(1.6);
156
+ border: 1px solid var(--cx-line); box-shadow: var(--cx-shadow);
157
+ animation: cx-rise .6s var(--cx-ease) both;
158
+ transition: transform .35s var(--cx-spring), background .2s, box-shadow .2s;
159
+ }
160
+ .act + .act { animation-delay: .06s; }
161
+ .act:hover { transform: translateY(-2px); }
162
+ .act:active { transform: scale(.94); }
163
+ .act--call { background: var(--cx-accent); color: var(--cx-accent-ink); border-color: transparent; }
164
+ .act--call:hover { background: color-mix(in oklab, var(--cx-accent) 88%, #000); }
165
+ /* The word folds away to an icon; hover, keyboard focus and a first visit unfold it. */
166
+ .act__label {
167
+ max-width: 0; opacity: 0; overflow: hidden; white-space: nowrap;
168
+ font-size: 14px; font-weight: 600; letter-spacing: -0.005em;
169
+ transition: max-width .35s var(--cx-ease), opacity .2s, margin .35s var(--cx-ease);
170
+ }
171
+ .act:hover .act__label, .act:focus-visible .act__label, .acts--labelled .act__label { max-width: 120px; opacity: 1; margin-left: 7px; }
172
+ /* Waiting in line: the place, on the button. */
173
+ .act__badge {
174
+ position: absolute; top: -5px; right: -5px; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px;
175
+ display: grid; place-items: center; font-size: 11px; font-weight: 800; font-variant-numeric: tabular-nums;
176
+ background: var(--cx-solid); color: var(--cx-ink); box-shadow: 0 0 0 2px var(--cx-accent);
177
+ }
178
+ /* On a call (or ready): the button breathes so the way back is obvious. */
179
+ .act--live::after { content: ""; position: absolute; inset: -4px; border-radius: inherit; border: 2px solid var(--cx-accent); opacity: .5; animation: cx-glow-ring 1.8s ease-out infinite; }
180
+ .greeting {
181
+ position: absolute; bottom: 76px; max-width: 260px; padding: 12px 34px 12px 14px; border-radius: 18px;
182
+ background: var(--cx-solid); box-shadow: var(--cx-shadow); border: 1px solid var(--cx-line);
183
+ font-size: 14px; color: var(--cx-ink); animation: cx-pop .55s var(--cx-spring) both; cursor: pointer;
184
+ }
185
+ :host([data-side="right"]) .greeting { right: 0; border-bottom-right-radius: 6px; }
186
+ :host([data-side="left"]) .greeting { left: 0; border-bottom-left-radius: 6px; }
187
+ .greeting__close { position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; color: var(--cx-ink-3); }
188
+ .greeting__close:hover { background: var(--cx-bubble); color: var(--cx-ink); }
189
+
190
+ /* ------------------------------------------------------------ panel */
191
+ .panel {
192
+ position: absolute; bottom: 0; width: 392px; height: min(640px, calc(100vh - 40px));
193
+ display: flex; flex-direction: column; overflow: hidden;
194
+ border-radius: var(--cx-radius); background: var(--cx-bg); border: 1px solid var(--cx-line);
195
+ backdrop-filter: blur(24px) saturate(1.7); -webkit-backdrop-filter: blur(24px) saturate(1.7);
196
+ box-shadow: var(--cx-shadow);
197
+ transform-origin: bottom right;
198
+ animation: cx-open .5s var(--cx-ease) both;
199
+ }
200
+ :host([data-side="right"]) .panel { right: 0; }
201
+ :host([data-side="left"]) .panel { left: 0; transform-origin: bottom left; }
202
+ .panel.is-closing { animation: cx-close .22s ease-in both; }
203
+
204
+ .head { display: flex; align-items: center; gap: 12px; padding: 14px 14px 12px 16px; border-bottom: 1px solid var(--cx-line); }
205
+ .head__face { position: relative; width: 42px; height: 42px; border-radius: 50%; overflow: hidden; flex: none;
206
+ background: radial-gradient(120% 90% at 50% 10%, color-mix(in oklab, var(--cx-accent) 22%, var(--cx-solid)), var(--cx-solid)); }
207
+ .head__who { flex: 1; min-width: 0; }
208
+ .head__name { font-size: 15px; font-weight: 650; letter-spacing: -0.01em; }
209
+ .head__sub { font-size: 12.5px; color: var(--cx-ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }
210
+ .head__sub i { width: 7px; height: 7px; border-radius: 50%; background: var(--cx-ok); flex: none; }
211
+ .icon-btn { width: 38px; height: 38px; border-radius: 12px; display: grid; place-items: center; color: var(--cx-ink-2); transition: background .2s, color .2s; }
212
+ .icon-btn:hover { background: var(--cx-bubble); color: var(--cx-ink); }
213
+ .icon-btn--accent { background: var(--cx-accent); color: var(--cx-accent-ink); }
214
+ .icon-btn--accent:hover { background: color-mix(in oklab, var(--cx-accent) 88%, #000); color: var(--cx-accent-ink); }
215
+
216
+ /* ------------------------------------------------------------ chat */
217
+ .log { flex: 1; overflow-y: auto; padding: 18px 16px 8px; display: flex; flex-direction: column; gap: 6px; scroll-behavior: smooth; overscroll-behavior: contain; }
218
+ .log::-webkit-scrollbar { width: 8px; } .log::-webkit-scrollbar-thumb { background: var(--cx-line); border-radius: 8px; }
219
+ .msg { max-width: 84%; padding: 9px 13px; border-radius: 18px; font-size: 14.5px; word-wrap: break-word; animation: cx-msg .35s var(--cx-ease) both; }
220
+ .msg p { margin: 0; } .msg p + p, .msg p + ul, .msg ul + p { margin-top: 8px; }
221
+ .msg ul { margin: 0; padding-left: 18px; }
222
+ .msg code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .9em; padding: 1px 5px; border-radius: 6px; background: var(--cx-bubble); }
223
+ .msg a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
224
+ .msg--agent { align-self: flex-start; background: var(--cx-bubble); border-bottom-left-radius: 6px; }
225
+ .msg--visitor { align-self: flex-end; background: var(--cx-accent); color: var(--cx-accent-ink); border-bottom-right-radius: 6px; }
226
+ .msg--visitor + .msg--visitor, .msg--agent + .msg--agent { margin-top: -2px; }
227
+ .msg--failed { opacity: .65; }
228
+ .msg__retry { display: inline-flex; align-items: center; gap: 4px; margin-top: 4px; font-size: 12px; color: var(--cx-danger); align-self: flex-end; }
229
+ .caret::after { content: ""; display: inline-block; width: 7px; height: 1.05em; margin-left: 2px; vertical-align: -2px; border-radius: 2px; background: currentColor; opacity: .55; animation: cx-blink 1s steps(2) infinite; }
230
+ .typing { display: inline-flex; gap: 4px; padding: 13px 14px; }
231
+ .typing i { width: 7px; height: 7px; border-radius: 50%; background: var(--cx-ink-3); animation: cx-bounce 1.2s var(--cx-ease) infinite; }
232
+ .typing i:nth-child(2) { animation-delay: .15s; } .typing i:nth-child(3) { animation-delay: .3s; }
233
+ .empty { margin: auto 0 8px; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 10px 8px 4px; }
234
+ .empty__face { width: 96px; height: 96px; border-radius: 50%; overflow: hidden; position: relative; box-shadow: 0 0 0 4px var(--cx-solid), 0 0 0 6px color-mix(in oklab, var(--cx-accent) 45%, transparent);
235
+ background: radial-gradient(120% 90% at 50% 10%, color-mix(in oklab, var(--cx-accent) 22%, var(--cx-solid)), var(--cx-solid)); }
236
+ .empty__title { font-size: 17px; font-weight: 650; letter-spacing: -0.015em; }
237
+ .empty__body { font-size: 13.5px; color: var(--cx-ink-2); max-width: 280px; }
238
+ .chips { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 4px; }
239
+ .chip { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 999px; font-size: 13px; border: 1px solid var(--cx-line); background: var(--cx-solid); transition: border-color .2s, transform .3s var(--cx-spring); }
240
+ .chip:hover { border-color: color-mix(in oklab, var(--cx-accent) 55%, transparent); transform: translateY(-1px); }
241
+ .chip svg { color: var(--cx-accent); }
242
+
243
+ .compose { padding: 10px 12px 12px; }
244
+ .compose__box { display: flex; align-items: flex-end; gap: 8px; padding: 6px 6px 6px 14px; border-radius: 20px; background: var(--cx-solid); border: 1px solid var(--cx-line); transition: border-color .2s, box-shadow .2s; }
245
+ .compose__box:focus-within { border-color: color-mix(in oklab, var(--cx-accent) 60%, transparent); box-shadow: 0 0 0 4px color-mix(in oklab, var(--cx-accent) 14%, transparent); }
246
+ .compose textarea { flex: 1; resize: none; border: 0; outline: 0; background: transparent; font: inherit; font-size: 14.5px; color: var(--cx-ink); max-height: 120px; padding: 7px 0; line-height: 1.4; }
247
+ .compose textarea::placeholder { color: var(--cx-ink-3); }
248
+ .send { width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: var(--cx-accent); color: var(--cx-accent-ink); flex: none; transition: transform .3s var(--cx-spring), opacity .2s; }
249
+ .send:disabled { opacity: .35; cursor: default; }
250
+ .send:not(:disabled):active { transform: scale(.9); }
251
+ .foot { text-align: center; font-size: 11px; color: var(--cx-ink-3); padding: 0 0 10px; }
252
+ .foot a { color: inherit; text-decoration: none; font-weight: 600; }
253
+
254
+ /* ------------------------------------------------------------ banners (queue / ready while chatting) */
255
+ .banner { margin: 10px 12px 0; padding: 10px 10px 10px 14px; border-radius: 16px; display: flex; align-items: center; gap: 10px; font-size: 13px;
256
+ background: color-mix(in oklab, var(--cx-accent) 12%, var(--cx-solid)); border: 1px solid color-mix(in oklab, var(--cx-accent) 25%, transparent); animation: cx-rise .4s var(--cx-ease) both; }
257
+ .banner__text { flex: 1; min-width: 0; } .banner__text b { font-weight: 650; }
258
+ .banner .btn { height: 32px; padding: 0 12px; font-size: 13px; }
259
+
260
+ /* ------------------------------------------------------------ call */
261
+ .stage { flex: 1; position: relative; display: flex; flex-direction: column; overflow: hidden;
262
+ background: radial-gradient(120% 70% at 50% 18%, color-mix(in oklab, var(--cx-accent) 26%, var(--cx-solid)) 0%, var(--cx-solid) 70%); }
263
+ .stage__figure { position: absolute; inset: 0; }
264
+ .stage__figure .portrait { position: absolute; inset: 0; }
265
+ /* The app's own face renderer, faded in over the portrait once it is drawing. */
266
+ .stage__face { position: absolute; inset: 0; opacity: 0; transition: opacity .5s ease; pointer-events: none; }
267
+ .stage__face.is-ready { opacity: 1; }
268
+ /* Over the skin's own (usually dark) backdrop the top controls go light. */
269
+ .stage--face .stage__top .icon-btn { color: rgba(255, 255, 255, 0.85); }
270
+ .stage--face .stage__top .icon-btn:hover { color: #fff; background: rgba(255, 255, 255, 0.14); }
271
+ .stage--face .badge { background: rgba(10, 8, 16, 0.45); color: #fff; border-color: rgba(255, 255, 255, 0.12); }
272
+ .face-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: transparent; color-scheme: normal; }
273
+ .stage__veil { position: absolute; left: 0; right: 0; bottom: 0; height: 58%; background: linear-gradient(to top, var(--cx-solid) 18%, color-mix(in oklab, var(--cx-solid) 0%, transparent)); pointer-events: none; }
274
+ .stage__top { position: relative; display: flex; justify-content: space-between; align-items: center; padding: 14px 14px 0 16px; }
275
+ .badge { display: inline-flex; align-items: center; gap: 7px; height: 28px; padding: 0 11px; border-radius: 999px; font-size: 12.5px; font-weight: 600; background: var(--cx-bg); backdrop-filter: blur(12px); border: 1px solid var(--cx-line); font-variant-numeric: tabular-nums; }
276
+ .badge i { width: 7px; height: 7px; border-radius: 50%; background: var(--cx-danger); animation: cx-pulse 1.6s ease-in-out infinite; }
277
+ .badge--warn { color: var(--cx-danger); }
278
+ .stage__bottom { position: relative; margin-top: auto; padding: 0 18px 18px; display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; }
279
+ .stage__name { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; }
280
+ .stage__status { font-size: 13.5px; color: var(--cx-ink-2); min-height: 20px; display: inline-flex; align-items: center; gap: 8px; }
281
+ .wave { display: inline-flex; align-items: center; gap: 3px; height: 16px; }
282
+ .wave i { width: 3px; border-radius: 3px; background: var(--cx-accent); height: calc(4px + var(--cx-lvl, 0) * 12px * var(--k, 1)); transition: height .08s linear; }
283
+ .captions { width: 100%; min-height: 44px; font-size: 14.5px; color: var(--cx-ink); display: flex; flex-direction: column; gap: 2px; }
284
+ .captions__line { opacity: .55; font-size: 13px; } .captions__line--now { opacity: 1; font-size: 15px; font-weight: 500; }
285
+ .controls { display: flex; gap: 14px; align-items: center; justify-content: center; margin-top: 4px; }
286
+ .round { width: 56px; height: 56px; border-radius: 50%; display: grid; place-items: center; background: var(--cx-bg); border: 1px solid var(--cx-line); backdrop-filter: blur(12px); transition: transform .3s var(--cx-spring), background .2s; }
287
+ .round:hover { transform: translateY(-2px); }
288
+ .round:active { transform: scale(.94); }
289
+ .round--on { background: var(--cx-ink); color: var(--cx-solid); }
290
+ .round--end { background: var(--cx-danger); color: #fff; border-color: transparent; width: 64px; height: 64px; }
291
+ .round__label { font-size: 11.5px; color: var(--cx-ink-2); margin-top: 6px; }
292
+ .ctl { display: flex; flex-direction: column; align-items: center; }
293
+
294
+ .voice { position: absolute; left: 50%; top: 34%; width: 240px; height: 240px; margin: -120px 0 0 -120px; border-radius: 50%; pointer-events: none;
295
+ background: radial-gradient(closest-side, color-mix(in oklab, var(--cx-accent) 30%, transparent), transparent);
296
+ transform: scale(calc(0.85 + var(--cx-lvl, 0) * 0.5)); opacity: calc(0.25 + var(--cx-lvl, 0) * 0.75); transition: transform .1s linear, opacity .1s linear; }
297
+
298
+ /* queue */
299
+ .line { position: relative; width: 168px; height: 168px; display: grid; place-items: center; margin: 4px auto 0; }
300
+ .line svg { position: absolute; inset: 0; transform: rotate(-90deg); }
301
+ .line__track { stroke: var(--cx-line); }
302
+ .line__fill { stroke: var(--cx-accent); transition: stroke-dashoffset .8s var(--cx-ease); }
303
+ .line__num { font-size: 46px; font-weight: 750; letter-spacing: -0.04em; line-height: 1; font-variant-numeric: tabular-nums; }
304
+ .line__lbl { font-size: 12px; color: var(--cx-ink-2); text-transform: uppercase; letter-spacing: .08em; margin-top: 4px; }
305
+ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 44px; padding: 0 18px; border-radius: 999px; font-size: 14.5px; font-weight: 600; background: var(--cx-bubble); transition: transform .3s var(--cx-spring), background .2s; }
306
+ .btn:hover { background: color-mix(in oklab, var(--cx-ink) 10%, transparent); }
307
+ .btn:active { transform: scale(.97); }
308
+ .btn--accent { background: var(--cx-accent); color: var(--cx-accent-ink); }
309
+ .btn--accent:hover { background: color-mix(in oklab, var(--cx-accent) 88%, #000); }
310
+ .btn--glow { box-shadow: 0 0 0 0 color-mix(in oklab, var(--cx-accent) 55%, transparent); animation: cx-glow 1.6s ease-out infinite; }
311
+ .btn-row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
312
+ .note { font-size: 13.5px; color: var(--cx-ink-2); max-width: 300px; }
313
+ .title { font-size: 19px; font-weight: 700; letter-spacing: -0.02em; }
314
+ .spinner { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--cx-line); border-top-color: var(--cx-accent); animation: cx-spin 0.8s linear infinite; }
315
+
316
+ /* ------------------------------------------------------------ portrait */
317
+ .portrait { position: relative; width: 100%; height: 100%; overflow: hidden; }
318
+ .portrait__media { position: absolute; max-width: none; transition: opacity .35s ease; user-select: none; -webkit-user-drag: none; }
319
+ .portrait--initial { display: grid; place-items: center; font-size: 26px; font-weight: 700; color: var(--cx-accent); }
320
+
321
+ /* ------------------------------------------------------------ test-mode ribbon */
322
+ .dock { position: relative; }
323
+ /* A small tag on the portrait's lower edge: present, never in the way. */
324
+ .testmode { position: absolute; left: 50%; bottom: -7px; transform: translateX(-50%); font-size: 8.5px; font-weight: 800; letter-spacing: .08em; line-height: 1; padding: 3px 5px; border-radius: 5px; background: #f59e0b; color: #1c1206; box-shadow: 0 0 0 2px var(--cx-solid); pointer-events: none; }
325
+
326
+ /* ------------------------------------------------------------ phones: a bottom sheet */
327
+ @media (max-width: 520px) {
328
+ :host([data-open]) { left: 0 !important; right: 0 !important; bottom: 0 !important; }
329
+ .panel { position: fixed; left: 0; right: 0; bottom: 0; width: 100%; height: min(92dvh, 760px); border-radius: var(--cx-radius) var(--cx-radius) 0 0; padding-bottom: env(safe-area-inset-bottom); animation-name: cx-sheet; }
330
+ .presence { width: 56px; height: 56px; }
331
+ .presence--half { width: 104px; height: 138px; }
332
+ .presence--full { width: 100px; height: 228px; }
333
+ .dock--half .greeting { bottom: 152px; }
334
+ .dock--full .greeting { bottom: 242px; }
335
+ }
336
+
337
+ @keyframes cx-spin { to { transform: rotate(360deg); } }
338
+ @keyframes cx-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
339
+ @keyframes cx-pop { from { opacity: 0; transform: translateY(8px) scale(.92); } to { opacity: 1; transform: none; } }
340
+ @keyframes cx-open { from { opacity: 0; transform: translateY(14px) scale(.94); filter: blur(4px); } to { opacity: 1; transform: none; filter: none; } }
341
+ @keyframes cx-close { to { opacity: 0; transform: translateY(10px) scale(.96); } }
342
+ @keyframes cx-sheet { from { transform: translateY(100%); } to { transform: none; } }
343
+ @keyframes cx-msg { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
344
+ @keyframes cx-blink { 50% { opacity: 0; } }
345
+ @keyframes cx-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: .45; } 30% { transform: translateY(-4px); opacity: 1; } }
346
+ @keyframes cx-pulse { 50% { opacity: .35; } }
347
+ @keyframes cx-figure-glow { 0%, 100% { filter: drop-shadow(0 0 0 transparent); } 50% { filter: drop-shadow(0 0 12px var(--cx-accent)); } }
348
+ @keyframes cx-glow-ring { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(1.35); opacity: 0; } }
349
+ @keyframes cx-glow { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--cx-accent) 50%, transparent); } 100% { box-shadow: 0 0 0 16px transparent; } }
350
+
351
+ @media (prefers-reduced-motion: reduce) {
352
+ *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
353
+ .presence__ring { animation: none; }
354
+ }
355
+ `;var Ee="character-xyz";function on(t){let e=/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(t.trim());if(!e)return"#ffffff";let n=e[1].length===3?e[1].replace(/./g,l=>l+l):e[1],[i,a,r]=[0,2,4].map(l=>parseInt(n.slice(l,l+2),16)/255).map(l=>l<=.03928?l/12.92:((l+.055)/1.055)**2.4);return .2126*i+.7152*a+.0722*r>.45?"#14121a":"#ffffff"}function pi(t){let e=/rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)(?:[,\s/]+([\d.]+%?))?\s*\)/.exec(t);if(!e||(e[4]===void 0?1:e[4].endsWith("%")?parseFloat(e[4])/100:parseFloat(e[4]))<.5)return null;let[i,a,r]=[e[1],e[2],e[3]].map(o=>Number(o)/255).map(o=>o<=.03928?o/12.92:((o+.055)/1.055)**2.4);return .2126*i+.7152*a+.0722*r}function sn(t){for(let e of[document.body,document.documentElement]){if(!e)continue;let n=pi(getComputedStyle(e).backgroundColor);if(n!==null)return n<.22}return!!t?.matches}var ui=["publishable-key","agent","api-url","position","mode","accent","greeting","open"],ze=class extends HTMLElement{constructor(){super(...arguments);Y(this,"options",null);Y(this,"client",null);Y(this,"api",null);Y(this,"pendingOpen",null);Y(this,"booted",!1);Y(this,"mq",null);Y(this,"stage",null);Y(this,"onSchemeChange",()=>requestAnimationFrame(this.onScheme));Y(this,"onScheme",()=>{this.dataset.mode==="auto"&&(this.dataset.theme=sn(this.mq)?"dark":"light")})}static get observedAttributes(){return ui}connectedCallback(){if(this.booted)return;this.booted=!0;let n=this.shadowRoot??this.attachShadow({mode:"open"}),i=document.createElement("style");i.textContent=rn,this.stage=document.createElement("div"),n.replaceChildren(i,this.stage),this.style.display="none";let a=window.requestIdleCallback;a?a(()=>{this.boot()},{timeout:2e3}):setTimeout(()=>{this.boot()},200)}disconnectedCallback(){this.stage&&Ke(null,this.stage),this.client?.destroy(),this.client=null,this.mq?.removeEventListener("change",this.onSchemeChange),this.booted=!1}open(n="chat"){this.api?this.api.open(n):this.pendingOpen=n}close(){this.api?.close()}fire(n,i){this.dispatchEvent(new CustomEvent(n,{detail:i,bubbles:!0,composed:!0}))}async boot(){let n={...this.options??{}},i=an(Array.from(this.attributes)),a=n.publishableKey??i.publishableKey;try{this.client=await He.init({publishableKey:a,getSessionToken:n.getSessionToken,agentId:n.agentId??i.agent,apiUrl:n.apiUrl??i.apiUrl,storage:n.storage})}catch(l){let p=l instanceof z?l:new z("unknown",String(l?.message??l));console.warn(`[characterxyz] widget not shown: ${p.message}`),this.fire("cx-error",{code:p.code,message:p.message});return}if(!this.isConnected){this.client.destroy();return}let r=this.client,o=ce(tt,r.appearance);if(o=ce(o,i),o=ce(o,n),!(o.showChat&&r.features.chat)&&!(o.showCall&&r.features.call)){console.warn("[characterxyz] widget not shown: neither chat nor calls are enabled for this site");return}this.applyTokens(o),r.on("call",l=>{l&&l.on("state",p=>this.fire("cx-call",{phase:p.phase,position:p.position,endReason:p.endReason}))}),r.on("error",l=>this.fire("cx-error",{code:l.code,message:l.message})),this.style.display="",Ke(s(nn,{client:r,config:o,bind:l=>{this.api=l,this.pendingOpen&&this.pendingOpen!=="closed"&&(l.open(this.pendingOpen),this.pendingOpen=null)},onView:l=>{l==="closed"?(this.removeAttribute("data-open"),this.fire("cx-close")):(this.setAttribute("data-open",""),this.fire("cx-open",{view:l}))}}),this.stage),o.open&&this.setAttribute("data-open",""),this.fire("cx-ready",{agent:{id:r.agent.id,name:r.agent.name},features:r.features})}applyTokens(n){this.dataset.side=n.position==="bottom-left"?"left":"right",this.dataset.mode=n.mode,n.mode==="auto"?(this.mq=matchMedia("(prefers-color-scheme: dark)"),this.mq.addEventListener("change",this.onSchemeChange),this.dataset.theme=sn(this.mq)?"dark":"light"):this.dataset.theme=n.mode;let i=(a,r)=>this.style.setProperty(a,r);i("--cx-accent",n.accent),i("--cx-accent-ink",on(n.accent)),i("--cx-radius",`${n.radius}px`),n.font&&i("--cx-font",n.font),i("--cx-ox",`${n.offsetX}px`),i("--cx-oy",`${n.offsetY}px`),i("--cx-z",String(n.zIndex))}};function $e(){typeof customElements<"u"&&!customElements.get(Ee)&&customElements.define(Ee,ze)}function hi(t){$e();let e=document.createElement(Ee);return e.options=t,(t.container??document.body).appendChild(e),{element:e,open:n=>e.open(n),close:()=>e.close(),destroy:()=>e.remove()}}$e();export{He as CharacterXYZ,ze as CharacterXYZElement,z as CxError,tt as DEFAULTS,Ee as TAG,ce as applyLayer,$e as define,on as inkFor,hi as mount};
356
+ //# sourceMappingURL=index.js.map