-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathwidget.js
More file actions
227 lines (227 loc) · 52.2 KB
/
Copy pathwidget.js
File metadata and controls
227 lines (227 loc) · 52.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
"use strict";(()=>{(function(){"use strict";function w(n){let i=document.createElement("div");return i.textContent=n,i.innerHTML.replace(/"/g,""")}let be={"":["<em>","</em>"],_:["<strong>","</strong>"],"*":["<strong>","</strong>"],"~":["<s>","</s>"],"\n":["<br />"]," ":["<br />"],"-":["<hr />"]};function jt(n){return n.replace(RegExp("^"+(n.match(/^(\t| )+/)||[""])[0],"gm"),"")}function lt(n){return(n+"").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function kt(n,i){let s=/((?:^|\n+)(?:\n---+|\* \*(?: \*)+)\n)|(?:^``` *(\w*)\n([\s\S]*?)\n```$)|((?:(?:^|\n+)(?:\t| {2,}).+)+\n*)|((?:(?:^|\n)([>*+-]|\d+\.)\s+.*)+)|(?:!\[([^\]]*?)\]\(([^)]+?)\))|(\[)|(\](?:\(([^)]+?)\))?)|(?:(?:^|\n+)([^\s].*)\n(-{3,}|={3,})(?:\n+|$))|(?:(?:^|\n+)(#{1,6})\s*(.+)(?:\n+|$))|(?:`([^`].*?)`)|( \n\n*|\n{2,}|__|\*\*|[_*]|~~)/gm,c=[],l="",b=i||{},$=0,k,d,a,E,h;function P(g){let A=be[g[1]||""],dt=c[c.length-1]==g;return A?A[1]?(dt?c.pop():c.push(g),A[dt?1:0]):A[0]:g}function D(){let g="";for(;c.length;)g+=P(c[c.length-1]);return g}for(n=n.replace(/^\[(.+?)\]:\s*(.+)$/gm,(g,A,dt)=>(b[A.toLowerCase()]=dt,"")).replace(/^\n+|\n+$/g,"");a=s.exec(n);)d=n.substring($,a.index),$=s.lastIndex,k=a[0],d.match(/[^\\](\\\\)*\\$/)||((h=a[3]||a[4])?k='<pre class="code '+(a[4]?"poetry":a[2].toLowerCase())+'"><code'+(a[2]?' class="language-'+a[2].toLowerCase()+'"':"")+">"+jt(lt(h).replace(/^\n+|\n+$/g,""))+"</code></pre>":(h=a[6])?(h.match(/\./)&&(a[5]=a[5].replace(/^\d+/gm,"")),E=kt(jt(a[5].replace(/^\s*[>*+.-]/gm,""))),h==">"?h="blockquote":(h=h.match(/\./)?"ol":"ul",E=E.replace(/^(.*)(\n|$)/gm,"<li>$1</li>")),k="<"+h+">"+E+"</"+h+">"):a[8]?k='<img src="'+lt(a[8])+'" alt="'+lt(a[7])+'">':a[10]?(l=l.replace("<a>",'<a href="'+lt(a[11]||b[d.toLowerCase()]||"")+'">'),k=D()+"</a>"):a[9]?k="<a>":a[12]||a[14]?(h="h"+(a[14]?a[14].length:a[13]>"="?1:2),k="<"+h+">"+kt(a[12]||a[15],b)+"</"+h+">"):a[16]?k="<code>"+lt(a[16])+"</code>":(a[17]||a[1])&&(k=P(a[17]||"--"))),l+=d,l+=k;return(l+n.substring($)+D()).replace(/^\n+|\n+$/g,"")}function we(n,i){let s=kt(w(n));return s=s.replace(/<a href=/g,`<a target="_blank" rel="noopener noreferrer" style="${i}word-break:break-all;" href=`),s=s.replace(/(^|\s)(https?:\/\/[^\s<]+)/g,(c,l,b)=>`${l}<a target="_blank" rel="noopener noreferrer" style="${i}word-break:break-all;" href="${b}">${b}</a>`),s}let ve=new Set(["jpg","jpeg","png","webp","gif"]);function $e(n,i,s,c){let l=n.split(".").pop()?.toLowerCase()||"",b=ve.has(l),$=w(n),k=s?"margin-bottom:6px;":"";if(b)return`<a href="${$}" target="_blank" rel="noopener noreferrer" style="display:block;${k}"><img src="${$}" style="max-width:100%;max-height:200px;border-radius:8px;display:block;cursor:pointer;" loading="lazy" alt="Image"></a>`;let d=i?w(i):`attachment.${w(l)}`;return`<a href="${$}" target="_blank" rel="noopener noreferrer" download="${d}" style="display:flex;align-items:center;gap:8px;padding:8px 10px;background:${c};border-radius:8px;text-decoration:none;color:inherit;${k}">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0;opacity:0.85;"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
<span style="font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;">${d}</span>
</a>`}function ke(n){return/^#[0-9A-Fa-f]{6}$/.test(n)}let Ie={bgMain:"#111827",bgShell:"#0f172a",bgInput:"#1e293b",bgHover:"#334155",txtMain:"#e2e8f0",txtInput:"#f1f5f9",txtDim:"#64748b",txtFaint:"#475569",txtBright:"#94a3b8",border:"rgba(255,255,255,0.08)",borderSolid:"#334155",linkColor:"#67e8f9"},Te={bgMain:"#ffffff",bgShell:"#f3f4f6",bgInput:"#e5e7eb",bgHover:"#d1d5db",txtMain:"#1f2937",txtInput:"#1f2937",txtDim:"#6b7280",txtFaint:"#9ca3af",txtBright:"#374151",border:"rgba(0,0,0,0.08)",borderSolid:"#d1d5db",linkColor:"#0369a1"};function Se(n){return/^(top|bottom)-(left|right)$/.test(n)}function Ee(n){return typeof n=="string"&&(n.startsWith("http://")||n.startsWith("https://"))}function Me(){let n=document.currentScript;if(n?.src)try{let i=new URL(n.src);return`${i.protocol}//${i.host}`}catch{}return"https://api.ghostchat.dev"}function Ce(n){return n.replace("http://","ws://").replace("https://","wss://")+"/ws"}let z=Me(),Le=Ce(z),It={};function He(n,i){typeof n=="string"&&typeof i=="function"&&(It[n]=It[n]||[]).push(i)}function mt(n,i){let s=It[n];if(s)for(let c of s)try{c(i)}catch{}}window.GhostChat=window.GhostChat||{},typeof window.GhostChat.on!="function"&&(window.GhostChat.on=He);function Be(){try{let n=new(window.AudioContext||window.webkitAudioContext),i=n.createOscillator(),s=n.createGain();i.connect(s),s.connect(n.destination),i.frequency.value=800,i.type="sine",s.gain.setValueAtTime(.3,n.currentTime),s.gain.exponentialRampToValueAtTime(.01,n.currentTime+.3),i.start(n.currentTime),i.stop(n.currentTime+.3)}catch{}}class ze{constructor(i,s){this.ws=null;this.reconnectAttempts=0;this.maxReconnectAttempts=10;this.reconnectTimeout=null;this.isDisconnecting=!1;this.channel=i,this.siteId=s}connect(){this.isDisconnecting=!1,this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null);try{this.ws&&(this.ws.readyState===WebSocket.CONNECTING||this.ws.readyState===WebSocket.OPEN)&&this.ws.close(),this.ws=new WebSocket(Le),this.ws.onopen=()=>{this.reconnectAttempts=0,this.ws&&this.ws.readyState===WebSocket.OPEN&&(this.ws.send(JSON.stringify({type:"subscribe",channel:this.channel,siteId:this.siteId,isVisitor:!0,sessionSecret:W()||void 0})),this.onConnectCallback&&this.onConnectCallback())},this.ws.onmessage=i=>{try{let s=JSON.parse(i.data);s.type==="new_message"&&s.message&&this.onMessageCallback?s.message.sender==="OWNER"&&this.onMessageCallback(s.message):s.type==="typing"&&this.onTypingCallback?this.onTypingCallback(s.typing):s.type==="translation_update"&&this.onTranslationCallback&&this.onTranslationCallback({messageId:s.messageId,translatedContent:s.translatedContent})}catch{}},this.ws.onerror=()=>{},this.ws.onclose=()=>{this.isDisconnecting||this.reconnect()}}catch{this.isDisconnecting||this.reconnect()}}reconnect(){if(!this.isDisconnecting&&this.reconnectAttempts<this.maxReconnectAttempts){this.reconnectAttempts++;let i=Math.min(1e3*Math.pow(2,this.reconnectAttempts),3e4);this.reconnectTimeout=setTimeout(()=>{this.isDisconnecting||this.connect()},i)}}onMessage(i){this.onMessageCallback=i}onTyping(i){this.onTypingCallback=i}onConnect(i){this.onConnectCallback=i}onTranslation(i){this.onTranslationCallback=i}updateChannel(i){this.channel=i,this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify({type:"subscribe",channel:this.channel,siteId:this.siteId,isVisitor:!0,sessionSecret:W()||void 0}))}send(i){this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(i))}disconnect(){this.isDisconnecting=!0,this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null),this.ws&&((this.ws.readyState===WebSocket.CONNECTING||this.ws.readyState===WebSocket.OPEN)&&this.ws.close(),this.ws=null)}}function Ft(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{let i=Math.random()*16|0;return(n==="x"?i:i&3|8).toString(16)})}let Tt={};function ct(n){try{return localStorage.getItem(n)}catch{return Tt[n]||null}}function U(n,i){try{localStorage.setItem(n,i)}catch{}Tt[n]=i}function St(n){try{localStorage.removeItem(n)}catch{}delete Tt[n]}function De(){let n="ghostchat_session_id",i=ct(n);return i||(i=Ft(),U(n,i)),i}function W(){return ct("ghostchat_session_secret")}function Ut(n){U("ghostchat_session_secret",n)}function R(){return ct("ghostchat_email")}function Et(n){U("ghostchat_email",n)}function Z(){return ct("ghostchat_name")}function Mt(n){U("ghostchat_name",n)}function Ae(){let n=document.currentScript;if(n?.getAttribute("data-site"))return n.getAttribute("data-site");let i=document.querySelectorAll("script[data-site]");return i.length>0?i[i.length-1].getAttribute("data-site"):null}async function Oe(n,i){try{let s=await fetch(`${z}/session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({siteId:n,sessionId:i,pageUrl:window.location.href,referrer:document.referrer||void 0})});return s.ok?s.json():null}catch{return null}}async function Re(n){try{let i=await fetch(`${z}/session/config?siteId=${encodeURIComponent(n)}`);return i.ok?i.json():null}catch{return null}}async function Wt(n,i){try{let s=`${z}/messages/visitor/${n}?siteId=${encodeURIComponent(i)}`,c=W();c&&(s+=`&sessionSecret=${encodeURIComponent(c)}`);let l=await fetch(s);return l.ok?l.json():[]}catch{return[]}}async function _e(n,i,s,c){let l={sessionId:n,content:i,pageUrl:window.location.href};s&&(l.imageUrl=s),c&&(l.attachmentName=c);let b=W();b&&(l.sessionSecret=b);let $=await fetch(`${z}/messages/visitor`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(!$.ok)throw new Error("Failed to send");return $.json()}async function Ne(n,i){let s=new FormData;s.append("file",i),s.append("sessionId",n);let c=W();c&&s.append("sessionSecret",c);let l=await fetch(`${z}/attachments/visitor`,{method:"POST",body:s});if(!l.ok){let $=await l.json().catch(()=>({error:"Upload failed"}));throw new Error($.error||"Upload failed")}let b=await l.json();return{url:b.url,name:b.name}}async function Ct(n,i,s){if(!i&&!s)return!1;try{let c={sessionId:n};i&&(c.email=i),s&&(c.name=s);let l=W();return l&&(c.sessionSecret=l),(await fetch(`${z}/session/email`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(c)})).ok}catch{return!1}}async function je(n){let i=W();if(i)try{await fetch(`${z}/session/end`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:n,sessionSecret:i})})}catch{}}function Fe(n){let i=n;return i&&!/[zZ]$|[+-]\d{2}:?\d{2}$/.test(i)&&(i=i.replace(" ","T")+"Z"),new Date(i).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}async function Ue(){if(document.getElementById("ghostchat-bubble")||document.getElementById("ghostchat-window"))return;let n=Ae();if(!n)return;let i=De(),s=await Re(n);if(!s)return;let{widgetSettings:c,ownerAvailable:l,hideBranding:b,nextAvailable:$}=s,k={chatWithUs:"Chat with us",sendMessage:"Send a message...",sendMessageAway:"Add email above to send",emptyTitle:"Hey! Drop us a message.",emptySubtitle:"We'll get back to you fast.",awayEmptySubtitle:"We'll reply as soon as we're back.",loading:"Loading...",online:"Online",leaveMessage:$?`Back ${$}`:"Away \u2014 leave a message",yourEmail:"Your email (optional)",yourEmailRequired:"Your email (required)",yourName:"Your name (optional)",save:"Save",editInfo:"Edit your info",noResponsePrompt:"Want to make sure we don't miss you? Leave your email as a backup.",addLaterHint:"Add your name or email anytime via the \u2022\u2022\u2022 menu",teaser:"\u{1F44B} Got a question? We're here to help"},d=t=>k[t],a=null,E=null,h=!1,P=!1;async function D(){return a||E||(E=(async()=>{try{let t=await Oe(n,i);if(!t)return null;a=t.id,t.aiHandedOff&&(h=!0),t.assignedTo==="human"&&(P=!0),t.sessionSecret&&Ut(t.sessionSecret),L.updateChannel(`session:${a}`);let o=R(),r=Z();return(o||r)&&a&&Ct(a,o||void 0,r||void 0),t.visitorEmail&&!R()&&(Et(t.visitorEmail),T=!0),t.visitorName&&!Z()&&(Mt(t.visitorName),q=!0),Y&&$t(),a}catch{return null}finally{E=null}})(),E)}let g=ke(c?.color)?c.color:"#2563eb",A=c?.widgetTheme,e=(A==="auto"?window.matchMedia("(prefers-color-scheme: light)").matches?"light":"dark":A==="light"?"light":"dark")==="light"?Te:Ie,X=Se(c?.position)?c.position:"bottom-right",Vt=c?.icon||"chat",We=c?.awayMessage||"We're currently away but will get back to you soon.",Pe=c?.welcomeMessage||"Hi! How can we help you today?",ln=!!(c?.welcomeMessage&&c.welcomeMessage.trim()),qt=Array.isArray(c?.quickLinks)?c.quickLinks:[],Ve=c?.siteName||"Chat",pt=c?.disableFileUploads===!0,V=c?.aiEnabled===!0,Gt=(c?.teaserMessage||"").trim(),yt=l||V?Pe:We,qe=!b,ut="M12 2C7.58 2 4 5.58 4 10V20L5.5 18.5L7 20L8.5 18.5L10 20L11.5 18.5L13 20L14.5 18.5L16 20L17.5 18.5L19 20L20 10C20 5.58 16.42 2 12 2Z",Jt=document.getElementById("ghostchat-embed"),M=!!Jt,Kt={chat:'<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 2H4C2.9 2 2 2.9 2 4V22L6 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2Z"/></svg>',"message-circle":'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"/></svg>',headset:'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18v-6a9 9 0 0118 0v6"/><path d="M21 19a2 2 0 01-2 2h-1a2 2 0 01-2-2v-3a2 2 0 012-2h3zM3 19a2 2 0 002 2h1a2 2 0 002-2v-3a2 2 0 00-2-2H3z"/></svg>',"help-circle":'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',ghost:`<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="${ut}"/><circle cx="9" cy="10" r="1.4" fill="${g}"/><circle cx="15" cy="10" r="1.4" fill="${g}"/></svg>`},Ge=Kt[Vt]||Kt.chat,Yt={chat:'<svg width="16" height="16" viewBox="0 0 24 24" fill="white"><path d="M20 2H4C2.9 2 2 2.9 2 4V22L6 18H20C21.1 18 22 17.1 22 16V4C22 2.9 21.1 2 20 2Z"/></svg>',"message-circle":'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 01-.9 3.8 8.5 8.5 0 01-7.6 4.7 8.38 8.38 0 01-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 01-.9-3.8 8.5 8.5 0 014.7-7.6 8.38 8.38 0 013.8-.9h.5a8.48 8.48 0 018 8v.5z"/></svg>',headset:'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 18v-6a9 9 0 0118 0v6"/><path d="M21 19a2 2 0 01-2 2h-1a2 2 0 01-2-2v-3a2 2 0 012-2h3zM3 19a2 2 0 002 2h1a2 2 0 002-2v-3a2 2 0 00-2-2H3z"/></svg>',"help-circle":'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',ghost:`<svg width="16" height="16" viewBox="0 0 24 24" fill="white"><path d="${ut}"/><circle cx="9" cy="10" r="1.2" fill="${e.bgShell}"/><circle cx="15" cy="10" r="1.2" fill="${e.bgShell}"/></svg>`},Je=Yt[Vt]||Yt.chat,C=!1,T=!!R(),q=!!Z(),y=[],G=!1,Q=!1,xt=!1,_=null,tt=!1,Lt=0,Zt=5,Ke=2*60*1e3,L=new ze("",n),et=!1,N=null,Ye=2*60*1e3,nt=null,Ht=null;L.onMessage(t=>{if(!y.some(r=>r.id===t.id)){y.push(t);let r=!!t.aiHandedOff&&!h;if(r&&(h=!0),mt("message",{sender:t.sender==="VISITOR"?"visitor":"agent",content:t.content,createdAt:t.createdAt}),t.sender==="OWNER"&&(h&&!r&&(P=!0),_=null,G=!1,J()),ot(),r&&B(),Be(),Ot(),!C){let u=document.getElementById("ghostchat-unread");u&&(u.style.display="flex")}}}),L.onTranslation(t=>{let o=y.find(r=>r.id===t.messageId);o&&(o.translatedContent=t.translatedContent,ot())}),L.onTyping(t=>{nt&&(clearTimeout(nt),nt=null),t?(nn(),nt=setTimeout(Ot,4e3)):Ot()}),L.onConnect(()=>{Y&&$t()});function Xt(){et||(L.connect(),et=!0),N&&(clearTimeout(N),N=null)}function Ze(){N&&clearTimeout(N),N=setTimeout(()=>{L.disconnect(),et=!1},Ye)}let Qt=()=>{y.length===0||!_||y[y.length-1].sender!=="VISITOR"||Date.now()-_>=Ke&&(G=!0,J(),B())},Xe=setInterval(Qt,3e4),te=()=>{!document.hidden&&C&&Xt()};document.addEventListener("visibilitychange",te);let ee=t=>{t.key==="Escape"&&C&&!M&&K()},ne=t=>{t.target.closest("#ghostchat-form-actions")||(ht.style.display="none")},ie=()=>{L.disconnect(),et=!1,nt&&clearTimeout(nt),N&&clearTimeout(N),j&&clearTimeout(j),ft&&clearTimeout(ft),Ht&&clearTimeout(Ht),clearInterval(Xe),Rt(),document.removeEventListener("visibilitychange",te),document.removeEventListener("keydown",ee),document.removeEventListener("click",ne),window.removeEventListener("popstate",rt),window.removeEventListener("hashchange",rt),history.pushState=fe,history.replaceState=me};window.addEventListener("beforeunload",ie),window.addEventListener("pagehide",ie);let p=null;if(!M){if(p=document.createElement("div"),p.id="ghostchat-bubble",p.setAttribute("role","button"),p.setAttribute("tabindex","0"),p.setAttribute("aria-label","Open chat"),p.innerHTML=`
${Ge}
<div id="ghostchat-unread" style="display:none;position:absolute;top:-2px;right:-2px;width:16px;height:16px;background:#ef4444;border-radius:50%;font-size:10px;font-weight:700;color:white;align-items:center;justify-content:center;border:2px solid ${g};">!</div>
`,p.style.cssText=`
position: fixed;
${X.includes("left")?"left: 20px;":"right: 20px;"}
${X.includes("top")?"top: 20px;":"bottom: 20px;"}
width: 52px; height: 52px;
background: ${g}; color: white;
border-radius: 50%;
display: flex; align-items: center; justify-content: center;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
z-index: 9998;
transition: transform 0.15s, box-shadow 0.15s;
border: 1px solid ${e.border};
`,p.onmouseenter=()=>{p.style.transform="scale(1.08)",p.style.boxShadow="0 4px 16px rgba(0,0,0,0.4)"},p.onmouseleave=()=>{p.style.transform="scale(1)",p.style.boxShadow="0 2px 8px rgba(0,0,0,0.3)"},p.onfocus=()=>{p.style.outline=`3px solid ${g}`,p.style.outlineOffset="3px"},p.onblur=()=>{p.style.outline="none"},"ontouchstart"in window){let u=null;window.addEventListener("scroll",()=>{C||!p||(p.style.opacity="0",p.style.pointerEvents="none",u&&clearTimeout(u),u=setTimeout(()=>{p&&(p.style.opacity="1",p.style.pointerEvents="auto")},600))},{passive:!0}),p.style.transition="transform 0.15s, box-shadow 0.15s, opacity 0.3s"}let t=document.createElement("style");t.textContent="@keyframes gcPulse{0%{transform:scale(1);box-shadow:0 2px 8px rgba(0,0,0,0.3)}50%{transform:scale(1.12);box-shadow:0 0 20px rgba(255,255,255,0.1),0 4px 16px rgba(0,0,0,0.4)}100%{transform:scale(1);box-shadow:0 2px 8px rgba(0,0,0,0.3)}}",document.head.appendChild(t),p.style.animation="gcPulse 1.5s ease-in-out 3s 2";let o=7*24*60*60*1e3,r=parseInt(ct("ghostchat_tooltip_shown")||"0",10);!("ontouchstart"in window)&&Date.now()-r>o&&(Ht=setTimeout(()=>{if(C||!p||!document.body.contains(p)||getComputedStyle(p).display==="none")return;let u=X.includes("left"),I=X.includes("top"),f=document.createElement("div");f.id="ghostchat-tooltip",f.setAttribute("role","button"),f.setAttribute("aria-label","Open chat"),f.style.cssText=`
position:fixed;
${u?"left:80px;":"right:80px;"}
${I?"top:28px;":"bottom:28px;"}
display:flex;align-items:center;gap:8px;
background:${e.bgInput};color:${e.txtMain};
font-size:13px;font-family:system-ui,sans-serif;font-weight:500;
padding:9px 12px;border-radius:10px;
box-shadow:0 2px 12px rgba(0,0,0,0.3);
border:1px solid ${e.border};
z-index:9998;max-width:240px;
opacity:0;transition:opacity 0.4s ease;
cursor:pointer;
`,f.innerHTML=`<span style="line-height:1.4;">${Gt?w(Gt):d("teaser")}</span><button type="button" id="ghostchat-tooltip-x" aria-label="Dismiss" style="background:none;border:none;color:${e.txtFaint};cursor:pointer;padding:0 0 0 2px;font-size:15px;line-height:1;flex-shrink:0;">×</button>`,document.body.appendChild(f),requestAnimationFrame(()=>{f.style.opacity="1"}),U("ghostchat_tooltip_shown",String(Date.now()));let x=()=>{f.style.opacity="0",setTimeout(()=>f.remove(),400)};f.onclick=O=>{if(O.target?.id==="ghostchat-tooltip-x"){x();return}x(),st()},setTimeout(x,14e3)},5e3))}let H=document.createElement("div");H.id="ghostchat-window",H.setAttribute("role","dialog"),H.setAttribute("aria-label","Chat with us"),H.innerHTML=`
<style>
#ghostchat-window form { margin: 0 !important; }
#ghostchat-window input,
#ghostchat-window textarea,
#ghostchat-window select {
min-width: 0 !important;
max-width: none !important;
width: auto !important;
font-family: inherit !important;
line-height: 1.4 !important;
}
#ghostchat-window textarea { margin: 0 !important; }
#ghostchat-window input:focus,
#ghostchat-window textarea:focus,
#ghostchat-window select:focus { box-shadow: none !important; }
#ghostchat-window button {
font-family: inherit !important;
text-transform: none !important;
letter-spacing: normal !important;
line-height: 1 !important;
margin: 0 !important;
box-shadow: none !important;
}
</style>
<div id="ghostchat-header" style="background:${e.bgShell};color:${e.txtMain};padding:14px 16px;border-radius:12px 12px 0 0;cursor:pointer;border-bottom:1px solid ${e.border};">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div style="display:flex;align-items:center;gap:10px;">
<div style="width:28px;height:28px;background:${g};border-radius:8px;display:flex;align-items:center;justify-content:center;">
${Je}
</div>
<div>
<div style="font-weight:600;font-size:14px;color:${e.txtInput};letter-spacing:-0.01em;">${w(Ve)}</div>
<div style="font-size:11px;color:${e.txtDim};display:flex;align-items:center;gap:5px;"><span style="width:7px;height:7px;border-radius:50%;background:${l?"#22c55e":"#f59e0b"};display:inline-block;flex-shrink:0;"></span>${d(l?"online":"leaveMessage")}</div>
</div>
</div>
<div style="display:flex;align-items:center;gap:2px;">
<div id="ghostchat-form-actions" style="position:relative;">
<button type="button" id="ghostchat-menu-btn" style="background:transparent;border:none;color:${e.txtDim};cursor:pointer;padding:4px;border-radius:6px;display:flex;align-items:center;justify-content:center;width:28px;height:28px;transition:color 0.15s;" title="More options" aria-label="More options" onmouseover="this.style.color='${e.txtMain}'" onmouseout="this.style.color='${e.txtDim}'"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="6" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="18" r="1.5"/></svg></button>
<div id="ghostchat-menu-dropdown" style="display:none;position:absolute;top:100%;right:0;margin-top:4px;background:${e.bgInput};border:1px solid ${e.bgHover};border-radius:8px;padding:4px;min-width:200px;box-shadow:0 4px 12px rgba(0,0,0,0.3);z-index:10;">
<button type="button" id="ghostchat-menu-email" style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:8px 10px;border:none;background:transparent;color:${e.txtMain};font-size:13px;cursor:pointer;border-radius:6px;" onmouseover="this.style.background='${e.bgHover}'" onmouseout="this.style.background='transparent'">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 4L12 13 2 4"/></svg>
<span id="ghostchat-menu-email-label">${d("editInfo")}</span>
</button>
<div style="height:1px;background:${e.bgHover};margin:4px 0;"></div>
<button type="button" id="ghostchat-menu-end" style="display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:8px 10px;border:none;background:transparent;color:${e.txtDim};font-size:13px;cursor:pointer;border-radius:6px;" onmouseover="this.style.background='${e.bgHover}'" onmouseout="this.style.background='transparent'">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>
End conversation
</button>
</div>
</div>
<button id="ghostchat-close" aria-label="Close chat" style="background:transparent;border:none;color:${e.txtDim};cursor:pointer;padding:4px;border-radius:6px;${M?"display:none;":"display:flex;"}align-items:center;justify-content:center;width:28px;height:28px;transition:color 0.15s;" onmouseover="this.style.color='${e.txtMain}'" onmouseout="this.style.color='${e.txtDim}'"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4l8 8M12 4l-8 8"/></svg></button>
</div>
</div>
</div>
<div id="ghostchat-messages" role="log" aria-live="polite" style="flex:1;min-height:0;overflow-y:auto;padding:16px;background:${e.bgMain};"></div>
<div id="ghostchat-helper" style="display:none;padding:8px 12px;background:${e.bgShell};border-top:1px solid ${e.border};"></div>
<div id="ghostchat-info-section" style="display:none;padding:8px 12px;background:${e.bgShell};border-top:1px solid ${e.border};">
<form id="ghostchat-info-form" style="display:flex;flex-direction:column;gap:6px;">
<div style="display:flex;justify-content:flex-end;">
<button type="button" id="ghostchat-dismiss-info" style="background:none;border:none;color:${e.txtFaint};cursor:pointer;font-size:18px;padding:0;line-height:1;" title="Dismiss">×</button>
</div>
<input id="ghostchat-name" type="text" placeholder="${d("yourName")}" autocomplete="name"
style="margin:0 8px;padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};transition:border-color 0.15s;" onfocus="this.style.borderColor='${g}'" onblur="this.style.borderColor='${e.bgInput}'">
<input id="ghostchat-email" type="email" placeholder="${d(l?"yourEmail":"yourEmailRequired")}" autocomplete="email" ${l?"":"required"}
style="margin:0 8px;padding:7px 10px;border:1px solid ${l?"${theme.bgInput}":"#f59e0b"};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};transition:border-color 0.15s;" onfocus="this.style.borderColor='${g}'" onblur="this.style.borderColor='${l?"${theme.bgInput}":"#f59e0b"}'">
<div style="display:flex;justify-content:flex-end;margin:0 8px;">
<button type="submit" style="background:${g};color:white;border:none;padding:7px 14px;border-radius:8px;cursor:pointer;font-weight:500;font-size:12px;transition:opacity 0.15s;" onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">${d("save")}</button>
</div>
</form>
</div>
<div id="ghostchat-image-preview" style="display:none;padding:8px 12px;background:${e.bgShell};border-top:1px solid ${e.border};"></div>
<form id="ghostchat-form" style="display:block;padding:12px;background:${e.bgShell};border-top:1px solid ${e.border};">
${pt?"":'<input type="file" id="ghostchat-file-input" accept="image/jpeg,image/png,image/webp,image/gif,application/pdf,text/plain,.md,.log,.json,.csv" style="display:none;">'}
<div style="display:flex;gap:8px;align-items:center;">
${pt?"":`<button type="button" id="ghostchat-attach" title="Attach file" aria-label="Attach file" style="background:transparent;border:none;color:${e.txtDim};cursor:pointer;padding:6px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:color 0.15s;flex-shrink:0;" onmouseover="this.style.color='${e.txtMain}'" onmouseout="this.style.color='${e.txtDim}'">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>
</button>`}
<textarea id="ghostchat-input" placeholder="${d("sendMessage")}" rows="1" maxlength="5000"
style="flex:1;padding:10px 14px;border:1px solid ${e.bgInput};border-radius:10px;font-size:14px;outline:none;background:${e.bgInput};color:${e.txtInput};transition:border-color 0.15s;resize:none;overflow-y:hidden;height:auto;min-height:0;max-height:72px;line-height:1.4;font-family:inherit;box-sizing:border-box;" onfocus="this.style.borderColor='${g}'" onblur="this.style.borderColor='${e.bgInput}'"></textarea>
<button type="submit" id="ghostchat-send" aria-label="Send message" style="background:${g};color:white;border:none;padding:10px 14px;border-radius:10px;cursor:pointer;font-weight:500;font-size:14px;display:flex;align-items:center;justify-content:center;transition:opacity 0.15s;" onmouseover="this.style.opacity='0.85'" onmouseout="this.style.opacity='1'">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>
</button>
</div>
</form>
${qe?`
<div style="text-align:center;padding:6px;background:${e.bgShell};border-top:1px solid ${e.border};border-radius:0 0 12px 12px;">
<a href="https://ghostchat.dev" target="_blank" rel="noopener" style="color:${e.txtFaint};text-decoration:none;font-size:10px;letter-spacing:0.02em;transition:color 0.15s;" onmouseover="this.style.color='${e.txtBright}'" onmouseout="this.style.color='${e.txtFaint}'">
\u26A1 <span style="font-weight:500;">GhostChat</span>
</a>
</div>
`:""}
`,M?(H.style.cssText=`
position: relative;
width: 100%; height: 100%;
background: ${e.bgMain};
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
display: flex; flex-direction: column;
border: 1px solid ${e.border};
font-family: system-ui, sans-serif;
overflow: hidden;
`,Jt.appendChild(H)):(H.style.cssText=`
position: fixed;
${X.includes("left")?"left: 20px;":"right: 20px;"}
${X.includes("top")?"top: 84px;":"bottom: 84px;"}
width: 350px; max-width: calc(100vw - 40px);
background: ${e.bgMain};
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
z-index: 9999;
display: none;
height: 580px; max-height: calc(100vh - 120px);
flex-direction: column;
border: 1px solid ${e.border};
font-family: system-ui, sans-serif;
`,document.body.appendChild(p),document.body.appendChild(H));let v=document.getElementById("ghostchat-messages"),S=document.getElementById("ghostchat-helper"),gt=document.getElementById("ghostchat-info-section"),oe=document.getElementById("ghostchat-info-form"),Bt=document.getElementById("ghostchat-name"),zt=document.getElementById("ghostchat-email"),Dt=document.getElementById("ghostchat-form"),m=document.getElementById("ghostchat-input"),Qe=document.getElementById("ghostchat-close"),tn=document.getElementById("ghostchat-menu-btn"),ht=document.getElementById("ghostchat-menu-dropdown"),At=document.getElementById("ghostchat-menu-email"),se=document.getElementById("ghostchat-menu-email-label"),en=document.getElementById("ghostchat-menu-end"),it=pt?null:document.getElementById("ghostchat-file-input"),re=pt?null:document.getElementById("ghostchat-attach"),bt=document.getElementById("ghostchat-image-preview"),wt=null;function nn(){let t=document.getElementById("ghostchat-typing");if(!t&&(t=document.createElement("div"),t.id="ghostchat-typing",t.style.cssText="padding:4px 0 8px;display:flex;align-items:center;gap:6px;",t.innerHTML=`
<div style="background:${e.bgInput};border-radius:12px;padding:8px 14px;display:flex;align-items:center;gap:4px;">
<span style="width:6px;height:6px;border-radius:50%;background:${e.txtDim};animation:gcDot 1.2s infinite;"></span>
<span style="width:6px;height:6px;border-radius:50%;background:${e.txtDim};animation:gcDot 1.2s infinite 0.2s;"></span>
<span style="width:6px;height:6px;border-radius:50%;background:${e.txtDim};animation:gcDot 1.2s infinite 0.4s;"></span>
</div>`,!document.getElementById("ghostchat-typing-style"))){let r=document.createElement("style");r.id="ghostchat-typing-style",r.textContent="@keyframes gcDot{0%,60%,100%{opacity:.3;transform:scale(1)}30%{opacity:1;transform:scale(1.2)}}",document.head.appendChild(r)}let o=v;o&&!o.contains(t)&&(o.appendChild(t),o.scrollTop=o.scrollHeight)}function Ot(){let t=document.getElementById("ghostchat-typing");t&&t.remove()}function ae(){let t=document.getElementById("ghostchat-dismiss-helper");t&&(t.onclick=()=>{Q=!0,G=!1,J(),B()})}function vt(){let t=document.getElementById("ghostchat-helper-email-form"),o=document.getElementById("ghostchat-helper-email"),r=document.getElementById("ghostchat-helper-name");t&&(t.onsubmit=async u=>{u.preventDefault();let I=o?.value.trim()||"",f=r?.value.trim()||"";if(!l&&!I||!I&&!f)return;let x=t.querySelector('button[type="submit"]');x&&(x.textContent="...",x.disabled=!0);let O=await D();O&&await Ct(O,I||void 0,f||void 0),I&&(Et(I),T=!0),f&&(Mt(f),q=!0),G=!1,xt=!1,J(),B(),m.focus(),x&&(x.textContent=d("save"),x.disabled=!1)})}function J(){if(h&&!P&&T){if(S.style.display="block",xt){S.innerHTML=`
<form id="ghostchat-helper-email-form" style="display:flex;gap:6px;align-items:center;">
<input id="ghostchat-helper-email" type="email" value="${w(R()||"")}" placeholder="${d("yourEmailRequired")}" autocomplete="email" required
style="flex:1;padding:7px 10px;border:1px solid ${g};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<button type="submit" style="background:${g};color:white;border:none;padding:7px 14px;border-radius:8px;cursor:pointer;font-weight:500;font-size:12px;flex-shrink:0;">${d("save")}</button>
<button type="button" id="ghostchat-cancel-email" title="Cancel" aria-label="Cancel" style="background:none;border:none;color:${e.txtFaint};cursor:pointer;font-size:18px;line-height:1;padding:0 2px;flex-shrink:0;">×</button>
</form>
`,vt();let t=document.getElementById("ghostchat-cancel-email");t&&(t.onclick=()=>{xt=!1,J()})}else{S.innerHTML=`<div style="font-size:12px;color:${e.txtBright};display:flex;align-items:center;gap:6px;flex-wrap:wrap;line-height:1.6;">We'll follow up at <strong style="color:${e.txtMain};">${w(R()||"")}</strong><button type="button" id="ghostchat-change-email" style="background:none;border:none;color:${g};cursor:pointer;font-size:12px;padding:0;text-decoration:underline;">Change</button></div>`;let t=document.getElementById("ghostchat-change-email");t&&(t.onclick=()=>{xt=!0,J()})}return}if(l&&h&&!T&&!Q){S.style.display="block",S.innerHTML=`
<form id="ghostchat-helper-email-form" style="display:flex;flex-direction:column;gap:6px;">
<div style="display:flex;justify-content:space-between;align-items:start;">
<p style="margin:0;font-size:12px;color:${e.txtBright};flex:1;">Add your email and the team will follow up if you step away.</p>
<button type="button" id="ghostchat-dismiss-helper" style="background:none;border:none;color:${e.txtFaint};cursor:pointer;padding:0 0 0 8px;font-size:16px;line-height:1;" title="Dismiss">×</button>
</div>
<input id="ghostchat-helper-name" type="text" placeholder="${d("yourName")}" autocomplete="name"
style="margin:0 8px;padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<input id="ghostchat-helper-email" type="email" placeholder="${d("yourEmail")}" autocomplete="email"
style="margin:0 8px;padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<div style="display:flex;justify-content:flex-end;margin:0 8px;">
<button type="submit" style="background:${g};color:white;border:none;padding:7px 14px;border-radius:8px;cursor:pointer;font-weight:500;font-size:12px;">${d("save")}</button>
</div>
</form>
`,vt(),ae();return}if(l&&G&&!(T||q)&&!Q&&!tt){S.style.display="block",S.innerHTML=`
<form id="ghostchat-helper-email-form" style="display:flex;flex-direction:column;gap:6px;">
<div style="display:flex;justify-content:space-between;align-items:start;">
<p style="margin:0;font-size:12px;color:${e.txtBright};flex:1;">${d("noResponsePrompt")}</p>
<button type="button" id="ghostchat-dismiss-helper" style="background:none;border:none;color:${e.txtFaint};cursor:pointer;padding:0 0 0 8px;font-size:16px;line-height:1;" title="Dismiss">×</button>
</div>
<input id="ghostchat-helper-name" type="text" placeholder="${d("yourName")}" autocomplete="name"
style="margin:0 8px;padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<input id="ghostchat-helper-email" type="email" placeholder="${d("yourEmail")}" autocomplete="email"
style="margin:0 8px;padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<div style="display:flex;justify-content:flex-end;margin:0 8px;">
<button type="submit" style="background:${g};color:white;border:none;padding:7px 14px;border-radius:8px;cursor:pointer;font-weight:500;font-size:12px;">${d("save")}</button>
</div>
</form>
`,vt(),ae();return}if(!l&&!T&&(!V||h)){S.style.display="block",S.innerHTML=`
<form id="ghostchat-helper-email-form" style="display:flex;flex-direction:column;gap:6px;">
<input id="ghostchat-helper-name" type="text" placeholder="${d("yourName")}" autocomplete="name"
style="padding:7px 10px;border:1px solid ${e.bgInput};border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<input id="ghostchat-helper-email" type="email" placeholder="${d("yourEmailRequired")}" autocomplete="email" required
style="padding:7px 10px;border:1px solid #f59e0b;border-radius:8px;font-size:12px;outline:none;background:${e.bgInput};color:${e.txtMain};box-sizing:border-box;">
<div style="display:flex;justify-content:flex-end;">
<button type="submit" style="background:${g};color:white;border:none;padding:7px 14px;border-radius:8px;cursor:pointer;font-weight:500;font-size:12px;">${d("save")}</button>
</div>
</form>
<style>#ghostchat-helper-email::placeholder{color:#fbbf24;opacity:1;}</style>
`,vt();return}if(!G&&qt.length>0&&(l||T||V)){S.style.display="block";let t=qt.filter(o=>o.label&&o.url).map(o=>{let r=Ee(o.url),u=w(o.label);return r?`<a href="${w(o.url)}" target="_blank" rel="noopener noreferrer" style="display:inline-block;margin-right:8px;margin-bottom:6px;padding:6px 10px;background:${e.bgInput};border-radius:8px;color:${e.txtBright};font-size:12px;text-decoration:none;transition:color 0.15s,background 0.15s;" onmouseover="this.style.color='${e.txtMain}';this.style.background='${e.bgHover}';" onmouseout="this.style.color='${e.txtBright}';this.style.background='${e.bgInput}';">${u}</a>`:`<span style="display:inline-block;margin-right:8px;margin-bottom:6px;padding:6px 10px;background:${e.bgInput};border-radius:8px;color:${e.txtDim};font-size:12px;">${u}</span>`}).join("");S.innerHTML=`<div style="display:flex;flex-wrap:wrap;gap:4px;">${t}</div>`;return}S.style.display="none",S.innerHTML=""}function le(t){return new Date(t).toDateString()}function on(t){let o=new Date(t),r={month:"long",day:"numeric"};return o.getFullYear()!==new Date().getFullYear()&&(r.year="numeric"),o.toLocaleDateString(void 0,r)}function ot(){if(y.length===0){if(v.style.display="block",!l&&!T&&!V){M||(v.style.height="185px"),yt?v.innerHTML=`<div style="padding:16px 12px 0;"><div style="max-width:80%;background:${e.bgInput};border-radius:16px 16px 16px 4px;padding:10px 14px;font-size:14px;line-height:1.5;white-space:pre-line;color:${e.txtMain};">${w(yt)}</div></div>`:v.innerHTML=`<div style="text-align:center;color:${e.txtDim};padding:36px 20px;"><svg width="32" height="32" viewBox="0 0 24 24" fill="none" style="margin:0 auto;display:block;opacity:0.5;"><path d="${ut}" fill="${e.txtFaint}"/><circle cx="9" cy="10" r="1.4" fill="${e.bgMain}"/><circle cx="15" cy="10" r="1.4" fill="${e.bgMain}"/></svg></div>`;return}if(M||(v.style.height="280px"),yt){v.innerHTML=`<div style="padding:16px 12px 0;"><div style="max-width:80%;background:${e.bgInput};border-radius:16px 16px 16px 4px;padding:10px 14px;font-size:14px;line-height:1.5;white-space:pre-line;color:${e.txtMain};">${w(yt)}</div></div>`;return}if(!l){v.innerHTML=`
<div style="text-align:center;color:${e.txtDim};padding:36px 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" style="margin:0 auto 12px;display:block;opacity:0.5;"><path d="${ut}" fill="${e.txtFaint}"/><circle cx="9" cy="10" r="1.4" fill="${e.bgMain}"/><circle cx="15" cy="10" r="1.4" fill="${e.bgMain}"/></svg>
<p style="margin:0;font-size:13px;line-height:1.5;">${d("emptyTitle")}<br><span style="color:${e.txtFaint};font-size:12px;">${d("awayEmptySubtitle")}</span></p>
</div>
`;return}v.innerHTML=`
<div style="text-align:center;color:${e.txtDim};padding:36px 20px;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" style="margin:0 auto 12px;display:block;opacity:0.5;"><path d="${ut}" fill="${e.txtFaint}"/><circle cx="9" cy="10" r="1.4" fill="${e.bgMain}"/><circle cx="15" cy="10" r="1.4" fill="${e.bgMain}"/></svg>
<p style="margin:0;font-size:13px;line-height:1.5;">${d("emptyTitle")}<br><span style="color:${e.txtFaint};font-size:12px;">${d("emptySubtitle")}</span></p>
</div>
`;return}v.style.display="block",M||(v.style.height="280px"),v.innerHTML=y.map((t,o)=>{let r=o>0&&le(t.createdAt)!==le(y[o-1].createdAt)?`<div style="text-align:center;margin:14px 0 8px;"><span style="display:inline-block;font-size:10px;color:${e.txtFaint};background:${e.bgInput};padding:2px 10px;border-radius:8px;">${w(on(t.createdAt))}</span></div>`:"",u=t.imageUrl?$e(t.imageUrl,t.attachmentName,t.content,e.border):"",I=t.sender==="VISITOR"?"color:white;text-decoration:underline;":`color:${e.linkColor};text-decoration:underline;`,f=t.content?we(t.content,I):"",x=t.sender==="OWNER"&&t.translatedContent?`<div style="margin-top:6px;padding-top:6px;border-top:1px solid rgba(255,255,255,0.15);font-size:12px;opacity:0.85;">${w(t.translatedContent).replace(/\n/g,"<br>")}</div>`:"",O=t.sender==="OWNER"&&t.senderName?`<div style="font-size:11px;color:${e.txtDim};margin-bottom:2px;padding:0 2px;">${w(t.senderName)}</div>`:"";return r+`
<div style="margin-bottom:10px;display:flex;flex-direction:column;align-items:${t.sender==="VISITOR"?"flex-end":"flex-start"};">
${O}
<div style="max-width:80%;padding:9px 13px;border-radius:12px;font-size:13px;line-height:1.45;
${t.sender==="VISITOR"?`background:${g};color:white;`:`background:${e.bgInput};color:${e.txtMain};`}">
${u}${f}${x}
</div>
<div style="font-size:10px;color:${e.txtFaint};margin-top:3px;padding:0 2px;">${Fe(t.createdAt)}</div>
</div>
`}).join("")+(h&&!P?`<div style="text-align:center;padding:8px 16px 4px;"><span style="display:inline-block;background:${e.bgInput};color:${e.txtDim};font-size:11px;line-height:1.5;padding:7px 12px;border-radius:10px;max-width:90%;">\u2713 Sent to the team \u2014 they'll follow up with you by email.</span></div>`:""),v.scrollTop=v.scrollHeight}function B(){Dt.style.display="block";let t=!l&&!T&&(!V||h),o=document.getElementById("ghostchat-send");o&&(o.disabled=t,o.style.opacity=t?"0.4":"1",o.style.cursor=t?"not-allowed":"pointer"),m.disabled=t,m.placeholder=d(t?"sendMessageAway":"sendMessage"),m.style.opacity=t?"0.5":"1";let r=T||q,u=l&&!r&&!G&&!Q&&!tt&&!V;if(gt.style.display=u?"block":"none",J(),ot(),r){let I=Z()||R()||"",f=I.length>22?I.slice(0,22)+"...":I;se.textContent=f?`\u2713 ${f} (edit)`:"\u2713 Info saved",At.style.color=e.txtBright}else se.textContent=d("editInfo"),At.style.color=e.txtMain}async function st(){H.style.display="flex",C=!0,mt("open"),p&&p.setAttribute("aria-label","Close chat");let t=document.getElementById("ghostchat-unread");if(t&&(t.style.display="none"),v.innerHTML=`
<div style="text-align:center;color:${e.txtFaint};padding:40px 20px;">
<div style="font-size:13px;">${d("loading")}</div>
</div>
`,await D(),Xt(),a){y=await Wt(i,n),y.length>0&&(tt=!0);let o=y.filter(r=>r.sender==="VISITOR").pop();o&&o.createdAt?_=new Date(o.createdAt).getTime():y.length===0&&(_=null)}B(),Qt(),"ontouchstart"in window||m.focus()}function K(){M||(H.style.display="none",C=!1,mt("close"),p&&(p.setAttribute("aria-label","Open chat"),p.focus()),Ze())}p&&(p.onclick=()=>C?K():st(),p.onkeydown=t=>{(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),C?K():st())}),M||(Qe.onclick=K),document.addEventListener("keydown",ee),tn.onclick=t=>{t.stopPropagation();let o=ht.style.display==="block";ht.style.display=o?"none":"block"},At.onclick=()=>{ht.style.display="none",Q=!1,S.style.display="none",gt.style.display="block",Bt.value=Z()||"",zt.value=R()||"",Bt.focus()},en.onclick=async()=>{ht.style.display="none";let t=a||await D();t&&await je(t),v.innerHTML=`<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:10px;padding:24px;text-align:center;">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="${e.txtDim}" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M8 12h8"/></svg>
<p style="margin:0;color:${e.txtMain};font-size:14px;font-weight:500;">Conversation ended</p>
<p style="margin:0;color:${e.txtDim};font-size:12px;">Type a message below to continue.</p>
</div>`},document.addEventListener("click",ne);let ce=document.getElementById("ghostchat-header");M||(ce.onclick=t=>{t.target.closest("#ghostchat-close")||t.target.closest("#ghostchat-form-actions")||K()}),M&&(ce.style.cursor="default"),oe.onsubmit=async t=>{t.preventDefault();let o=zt.value.trim(),r=Bt.value.trim();if(!l&&!o){zt.focus();return}if(!o&&!r)return;let u=oe.querySelector('button[type="submit"]');u&&(u.textContent="...",u.disabled=!0),a&&await Ct(a,o||void 0,r||void 0),o&&(Et(o),T=!0),r&&(Mt(r),q=!0),B(),m.focus(),u&&(u.textContent=d("save"),u.disabled=!1)};let de=document.getElementById("ghostchat-dismiss-info");de&&(de.onclick=()=>{Q=!0,gt.style.display="none";let t=document.createElement("div");t.style.cssText=`padding:6px 12px;background:${e.bgShell};border-top:1px solid ${e.border};font-size:11px;color:${e.txtFaint};text-align:center;transition:opacity 0.4s;`,t.textContent=d("addLaterHint"),gt.parentNode?.insertBefore(t,gt.nextSibling),setTimeout(()=>{t.style.opacity="0",setTimeout(()=>t.remove(),400)},3e3),B()}),m.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),Dt.requestSubmit())}),m.addEventListener("input",()=>{m.style.height="auto",m.style.height=Math.min(m.scrollHeight,72)+"px",m.style.overflowY=m.scrollHeight>72?"auto":"hidden"});let j=null;m.addEventListener("input",()=>{et&&a&&(L.send({type:"typing",channel:`session:${a}`,typing:!0}),j&&clearTimeout(j),j=setTimeout(()=>{a&&L.send({type:"typing",channel:`session:${a}`,typing:!1})},2e3))});let F=null;function sn(t){F&&(URL.revokeObjectURL(F),F=null),wt=t;let o=t.type.startsWith("image/"),r;o?(F=URL.createObjectURL(t),r=`<img src="${F}" style="max-height:48px;border-radius:6px;" alt="Preview">`):r=`<div style="width:48px;height:48px;background:${e.bgInput};border-radius:6px;display:flex;align-items:center;justify-content:center;color:${e.txtBright};flex-shrink:0;"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg></div>`,bt.innerHTML=`<div style="display:flex;align-items:center;gap:8px;">${r}<span style="flex:1;font-size:12px;color:${e.txtBright};overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${w(t.name)}</span><button type="button" id="ghostchat-remove-image" style="background:none;border:none;color:#ef4444;cursor:pointer;padding:2px;font-size:16px;line-height:1;">×</button></div>`,bt.style.display="block";let u=document.getElementById("ghostchat-remove-image");u&&(u.onclick=Rt)}function Rt(){F&&(URL.revokeObjectURL(F),F=null),wt=null,bt.style.display="none",bt.innerHTML="",it&&(it.value="")}async function pe(t){if(t.size>5*1024*1024){console.error("[GhostChat] Image too large (max 5MB)");return}if(Lt>=Zt){console.error("[GhostChat] Image limit reached for this conversation");return}sn(t)}re&&it&&(re.onclick=()=>{Lt>=Zt||it.click()},it.onchange=()=>{let t=it.files?.[0];t&&pe(t)}),pt||m.addEventListener("paste",t=>{let o=t.clipboardData?.items;if(o){for(let r=0;r<o.length;r++)if(o[r].type.startsWith("image/")){t.preventDefault();let u=o[r].getAsFile();u&&pe(u);return}}}),Dt.onsubmit=async t=>{if(t.preventDefault(),!l&&!T&&(!V||h))return;let o=m.value.trim();if(!o&&!!!wt)return;j&&(clearTimeout(j),j=null),et&&a&&L.send({type:"typing",channel:`session:${a}`,typing:!1});let u=document.getElementById("ghostchat-send"),I='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>';u.innerHTML='<span style="font-size:12px;">...</span>',u.disabled=!0,m.disabled=!0;let f=wt;try{let x=await D();if(!x)throw new Error("Failed to create session");let O,ye;if(f){let xe=await Ne(x,f);O=xe.url,ye=xe.name,Lt++}let at=await _e(x,o,O,ye);at?.aiHandedOff&&(h=!0),Rt(),y.push(at.message),mt("message",{sender:"visitor",content:at.message?.content,createdAt:at.message?.createdAt}),_=at.message?.createdAt?new Date(at.message.createdAt).getTime():Date.now(),tt=!0,m.value="",m.style.height="auto",ot(),B()}catch(x){console.error("Failed to send:",x)}u.innerHTML=I,u.disabled=!1,m.disabled=!1,m.focus()},R()&&(T=!0),Z()&&(q=!0);let Y=null,ft=null,_t=!1,Nt=null;async function ue(t){if(!(!t||typeof t.sessionId!="string"||!t.sessionId)&&!(typeof t.dbSessionId!="string"||!t.dbSessionId)&&!(typeof t.sessionSecret!="string"||!t.sessionSecret)&&t.sessionId!==i){if(E)try{await E}catch{}if(t.sessionId!==i)if(i=t.sessionId,U("ghostchat_session_id",t.sessionId),Ut(t.sessionSecret),a=null,await D(),C)try{y=await Wt(i,n),y.length>0&&(tt=!0);let o=y.filter(r=>r.sender==="VISITOR").pop();_=o?.createdAt?new Date(o.createdAt).getTime():null,ot(),B()}catch{}else y=[]}}function rn(){St("ghostchat_email"),St("ghostchat_name"),T=!1,q=!1}async function an(){if(i=Ft(),U("ghostchat_session_id",i),St("ghostchat_session_secret"),a=null,y=[],tt=!1,_=null,C)try{await D(),ot(),B()}catch{}}function $t(){if(!Y)return;let t={sessionId:i,siteId:n,metadata:Y};Nt&&(t.userHash=Nt),fetch(`${z}/session/context`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}).then(async o=>{if(!o.ok)return;let r=await o.json().catch(()=>null);r&&(r.identitySwitch?(rn(),r.canonicalSession?await ue(r.canonicalSession):await an()):r.canonicalSession&&await ue(r.canonicalSession))}).catch(()=>{})}function ge(t){if(!t||typeof t!="object"||Array.isArray(t))return;t.userHash&&typeof t.userHash=="string"&&(Nt=t.userHash,t={...t},delete t.userHash);let o=Y?{...Y,...t}:t;try{if(JSON.stringify(o).length>4096)return}catch{return}if(Y=o,ft){_t=!0;return}$t(),ft=setTimeout(()=>{ft=null,_t&&(_t=!1,$t())},5e3)}let he=window.location.href;function rt(){let t=window.location.href;t!==he&&(he=t,ge({_url:t}))}window.addEventListener("popstate",rt),window.addEventListener("hashchange",rt);let fe=history.pushState,me=history.replaceState;history.pushState=function(...t){fe.apply(this,t),rt()},history.replaceState=function(...t){me.apply(this,t),rt()},M&&st(),Object.assign(window.GhostChat,{open:st,close:K,toggle:()=>C?K():st(),setContext:ge})}async function Pt(){try{await Ue()}catch(n){console.error("[GhostChat] Widget failed to initialize:",n)}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Pt):Pt()})();})();