@sphoro/bugcatch-web-sdk 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -3
- package/dist/bugcatch-call.es.js +201 -200
- package/dist/bugcatch-call.es.js.map +1 -1
- package/dist/bugcatch-call.umd.js +1 -1
- package/dist/bugcatch-call.umd.js.map +1 -1
- package/dist/bugcatch-core.es.js +1085 -1007
- package/dist/bugcatch-core.es.js.map +1 -1
- package/dist/bugcatch-panel.es.js +1337 -1067
- package/dist/bugcatch-panel.es.js.map +1 -1
- package/dist/bugcatch-panel.umd.js +427 -315
- package/dist/bugcatch-panel.umd.js.map +1 -1
- package/dist/bugcatch.standalone.umd.js +553 -429
- package/dist/bugcatch.standalone.umd.js.map +1 -1
- package/dist/bugcatch.umd.js +132 -120
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/accent.js +38 -0
- package/src/incoming-call.js +17 -15
- package/src/index.d.ts +52 -2
- package/src/index.js +26 -7
- package/src/panel/call.js +3 -2
- package/src/panel/compose.js +7 -3
- package/src/panel/icons.js +2 -0
- package/src/panel/index.js +26 -3
- package/src/panel/messages.js +2 -2
- package/src/panel/picks.js +6 -2
- package/src/panel/rate-due.js +155 -0
- package/src/panel/rating.js +87 -0
- package/src/panel/refs.js +1 -1
- package/src/panel/render.js +11 -3
- package/src/panel/signin.js +1 -1
- package/src/panel/styles.js +270 -186
- package/src/panel/thread.js +48 -7
- package/src/updates.js +77 -27
- package/src/widget.js +160 -141
|
@@ -1,81 +1,106 @@
|
|
|
1
|
-
(function(U,K){typeof exports=="object"&&typeof module<"u"?module.exports=K():typeof define=="function"&&define.amd?define(K):(U=typeof globalThis<"u"?globalThis:U||self,U.BugCatch=K())})(this,function(){"use strict";var xn=U=>{throw TypeError(U)};var wr=(U,K,ae)=>K.has(U)||xn("Cannot "+ae);var kn=(U,K,ae)=>K.has(U)?xn("Cannot add the same private member more than once"):K instanceof WeakSet?K.add(U):K.set(U,ae);var H=(U,K,ae)=>(wr(U,K,"access private method"),ae);var B,De,Sn,oe,$n,st,Ne,Ue,ct,Cn,Tn,En,_e,In;const U="[REDACTED]",K=new Set(["auth","bearer","session","sid","phpsessid","otp","pass","passwd","pwd","sig","codeverifier"]),ae=["token","secret","password","passwd","apikey","signature","credential","sessionid","privatekey","accesskey","authorization"],Ln=new Set(["key","code","state","nonce","salt","hash"]),lt=[/eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,/(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,/AIza[\w-]{35}/g,/gh[pousr]_[A-Za-z0-9]{36,}/g,/github_pat_\w{22,}/g,/[sprk]k_(?:live|test)_[0-9A-Za-z]{10,}/g,/xox[abposr]-[A-Za-z0-9-]{10,}/g,/sk-ant-[\w-]{20,}/g,/sk-[\w-]{20,}/g,/glpat-[\w-]{20,}/g,/shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g],An=/\bBearer\s+[\w.~+/=-]{8,}/gi,Mn=/^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;function dt(t){try{return decodeURIComponent(t.replace(/\+/g," "))}catch{return t}}function Bn(t){return dt(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function Rn(t){return t.length>=20?!0:lt.some(e=>(e.lastIndex=0,e.test(t)))}function jn(t,e){const n=Bn(t);if(!n)return!1;if(K.has(n))return!0;for(const o of ae)if(n.includes(o))return!0;return Ln.has(n)?Rn(dt(e)):!1}function Pe(t){return t.split("&").map(e=>{const n=e.indexOf("=");if(n===-1)return e;const o=e.slice(0,n),a=e.slice(n+1);return a&&jn(o,a)?`${o}=${U}`:e}).join("&")}function ut(t){let e=t;for(const n of lt)n.lastIndex=0,e=e.replace(n,U);return e}function pt(t){if(t==null)return t;let e=String(t);if(!e)return e;e=e.replace(Mn,`$1${U}@`);const n=e.indexOf("#");let o=n===-1?e:e.slice(0,n),a=n===-1?"":e.slice(n);const r=o.indexOf("?");if(r!==-1&&(o=o.slice(0,r+1)+Pe(o.slice(r+1))),a.length>1){const i=a.slice(1),s=i.indexOf("?");s!==-1?a=`#${i.slice(0,s+1)}${Pe(i.slice(s+1))}`:i.includes("=")&&(a=`#${Pe(i)}`)}return ut(o+a)}function On(t){if(t==null)return t;let e=String(t);return e&&(e=e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g,n=>pt(n)),e=e.replace(An,`Bearer ${U}`),ut(e))}function ke(t){const e=[];return{push(n){e.push(n),e.length>t&&e.splice(0,e.length-t)},all:()=>e.slice(),clear:()=>{e.length=0},get size(){return e.length}}}const ht=["log","info","warn","error","debug"];function zn(t,{levels:e=["warn","error","log","info"]}={}){const n={};for(const o of ht)n[o]=console[o],e.includes(o)&&(console[o]=(...a)=>{try{t.push({level:o,text:a.map(bt).join(" ").slice(0,2e3),at:new Date().toISOString()})}catch{}n[o].apply(console,a)});return()=>{for(const o of ht)console[o]=n[o]}}function Qn(t,{slowMs:e=2e3}={}){const n=window.fetch,o=XMLHttpRequest.prototype.open,a=XMLHttpRequest.prototype.send;return n&&(window.fetch=async function(...i){var f,d,u;const s=performance.now(),c=typeof i[0]=="string"?i[0]:(f=i[0])==null?void 0:f.url,l=((d=i[1])==null?void 0:d.method)||(typeof i[0]=="object"?(u=i[0])==null?void 0:u.method:"GET")||"GET";try{const g=await n.apply(this,i);return Ke(t,{url:c,method:l,status:g.status,ms:Math.round(performance.now()-s),slowMs:e}),g}catch(g){throw Ke(t,{url:c,method:l,status:0,error:String((g==null?void 0:g.message)||g),ms:Math.round(performance.now()-s),slowMs:e}),g}}),XMLHttpRequest.prototype.open=function(i,s,...c){return this.__bc={method:i,url:s,started:0},o.call(this,i,s,...c)},XMLHttpRequest.prototype.send=function(...i){return this.__bc&&(this.__bc.started=performance.now(),this.addEventListener("loadend",()=>{Ke(t,{url:this.__bc.url,method:this.__bc.method,status:this.status,ms:Math.round(performance.now()-this.__bc.started),slowMs:e})})),a.apply(this,i)},()=>{n&&(window.fetch=n),XMLHttpRequest.prototype.open=o,XMLHttpRequest.prototype.send=a}}function Ke(t,{url:e,method:n,status:o,ms:a,error:r,slowMs:i}){try{t.push({url:pt(String(e)).slice(0,500),method:n,status:o,ms:a,error:r===void 0?void 0:On(r),failed:o===0||o>=400,slow:a>=i,at:new Date().toISOString()})}catch{}}function Hn(t){const e=o=>{const a=String(o.message||"Error"),r=o.filename?` (${o.filename}:${o.lineno}:${o.colno})`:"";t.push({level:"error",text:(/^uncaught/i.test(a)?a:`Uncaught ${a}`)+r,at:new Date().toISOString()})},n=o=>{t.push({level:"error",text:`Unhandled rejection: ${bt(o.reason)}`,at:new Date().toISOString()})};return window.addEventListener("error",e),window.addEventListener("unhandledrejection",n),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",n)}}async function ft(){const t=gt();try{if(navigator.getBattery){const e=await navigator.getBattery();t.battery=Math.round(e.level*100),t.charging=e.charging}}catch{}return t}function gt(){var e,n,o,a,r,i,s,c,l;const t=window.navigator||{};return{userAgent:t.userAgent,platform:t.platform,language:t.language,languages:t.languages?[...t.languages]:null,online:t.onLine,cookieEnabled:t.cookieEnabled,maxTouchPoints:t.maxTouchPoints??null,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:(e=window.screen)==null?void 0:e.width,height:(n=window.screen)==null?void 0:n.height,availWidth:(o=window.screen)==null?void 0:o.availWidth,availHeight:(a=window.screen)==null?void 0:a.availHeight,colorDepth:(r=window.screen)==null?void 0:r.colorDepth,orientation:((s=(i=window.screen)==null?void 0:i.orientation)==null?void 0:s.type)||null},devicePixelRatio:window.devicePixelRatio,referrer:document.referrer||null,title:document.title,capturedAt:new Date().toISOString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffsetMinutes:new Date().getTimezoneOffset(),browserMode:t.webdriver?"Automated":"Normal",doNotTrack:t.doNotTrack||null,hardwareConcurrency:t.hardwareConcurrency??null,deviceMemory:t.deviceMemory??null,connection:t.connection?{effectiveType:t.connection.effectiveType,downlink:t.connection.downlink,rtt:t.connection.rtt,saveData:t.connection.saveData}:null,prefersColorScheme:(c=window.matchMedia)!=null&&c.call(window,"(prefers-color-scheme: dark)").matches?"dark":"light",prefersReducedMotion:((l=window.matchMedia)==null?void 0:l.call(window,"(prefers-reduced-motion: reduce)").matches)||!1}}function bt(t){if(typeof t=="string")return t;if(t instanceof Error)return`${t.name}: ${t.message}`;try{return JSON.stringify(t)}catch{return String(t)}}const mt='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>',qn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9.5l6 6 6-6"/></svg>',Dn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>',Nn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>',Un='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>',re='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>',fe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',ie='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',yt='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>',_n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>';function wt(t,e){console.warn(`[BugCatch] ${t}`,...e?[e]:[]);const n=new Error("[BugCatch] part of the widget could not be loaded — check the connection and try again.");return e&&(n.cause=e),n}function vt(t){let e=null;return(...n)=>(e||(e=t(...n).catch(o=>{throw e=null,o})),e)}const xt=vt(()=>Promise.resolve().then(()=>Ga).catch(t=>{throw wt("the report panel could not be loaded.",t)})),Se=vt(()=>Promise.resolve().then(()=>gr).catch(t=>{throw wt("the calling code could not be loaded.",t)})),Pn={info:yt,success:ie,warning:_n,critical:re};function kt(t,{where:e,onDismiss:n}){const o=document.createElement("div");o.className=`notice tone-${t.tone} at-${e}`,o.setAttribute("role","status");const a=document.createElement("span");a.className="notice-ico",a.setAttribute("aria-hidden","true"),a.innerHTML=Pn[t.tone]||yt;const r=document.createElement("div");r.className="notice-text";const i=document.createElement("strong");if(i.textContent=t.title,r.append(i),t.body){const s=document.createElement("p");s.textContent=t.body,r.append(s)}if(t.ctaHref&&t.ctaLabel){const s=document.createElement("a");s.className="notice-cta",s.href=t.ctaHref,s.textContent=t.ctaLabel,/^https?:/i.test(t.ctaHref)&&(s.target="_blank",s.rel="noopener noreferrer"),r.append(s)}if(o.append(a,r),t.dismissible&&n){const s=document.createElement("button");s.type="button",s.className="notice-x",s.setAttribute("aria-label","Dismiss this notice"),s.innerHTML=fe,s.addEventListener("click",()=>n(t)),o.append(s)}return o}const St={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"},$t=[{value:"light",label:"Light",icon:Dn},{value:"dark",label:"Dark",icon:Nn},{value:"auto",label:"System default",icon:Un}],Ct="bugcatch:theme";function Kn(){try{const t=localStorage.getItem(Ct);return $t.some(e=>e.value===t)?t:null}catch{return null}}function Vn(t){try{localStorage.setItem(Ct,t)}catch{}}const Fn=t=>`
|
|
1
|
+
(function(K,F){typeof exports=="object"&&typeof module<"u"?module.exports=F():typeof define=="function"&&define.amd?define(F):(K=typeof globalThis<"u"?globalThis:K||self,K.BugCatch=F())})(this,function(){"use strict";var Bn=K=>{throw TypeError(K)};var Or=(K,F,ie)=>F.has(K)||Bn("Cannot "+ie);var Rn=(K,F,ie)=>F.has(K)?Bn("Cannot add the same private member more than once"):F instanceof WeakSet?F.add(K):F.set(K,ie);var q=(K,F,ie)=>(Or(K,F,"access private method"),ie);var B,Pe,jn,re,On,pt,Ke,_e,ht,zn,qn,Dn,Ve,Qn;const K="[REDACTED]",F=new Set(["auth","bearer","session","sid","phpsessid","otp","pass","passwd","pwd","sig","codeverifier"]),ie=["token","secret","password","passwd","apikey","signature","credential","sessionid","privatekey","accesskey","authorization"],Hn=new Set(["key","code","state","nonce","salt","hash"]),ft=[/eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,/(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,/AIza[\w-]{35}/g,/gh[pousr]_[A-Za-z0-9]{36,}/g,/github_pat_\w{22,}/g,/[sprk]k_(?:live|test)_[0-9A-Za-z]{10,}/g,/xox[abposr]-[A-Za-z0-9-]{10,}/g,/sk-ant-[\w-]{20,}/g,/sk-[\w-]{20,}/g,/glpat-[\w-]{20,}/g,/shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g],Nn=/\bBearer\s+[\w.~+/=-]{8,}/gi,Un=/^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;function gt(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch{return e}}function Pn(e){return gt(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function Kn(e){return e.length>=20?!0:ft.some(t=>(t.lastIndex=0,t.test(e)))}function _n(e,t){const n=Pn(e);if(!n)return!1;if(F.has(n))return!0;for(const o of ie)if(n.includes(o))return!0;return Hn.has(n)?Kn(gt(t)):!1}function Fe(e){return e.split("&").map(t=>{const n=t.indexOf("=");if(n===-1)return t;const o=t.slice(0,n),a=t.slice(n+1);return a&&_n(o,a)?`${o}=${K}`:t}).join("&")}function bt(e){let t=e;for(const n of ft)n.lastIndex=0,t=t.replace(n,K);return t}function mt(e){if(e==null)return e;let t=String(e);if(!t)return t;t=t.replace(Un,`$1${K}@`);const n=t.indexOf("#");let o=n===-1?t:t.slice(0,n),a=n===-1?"":t.slice(n);const r=o.indexOf("?");if(r!==-1&&(o=o.slice(0,r+1)+Fe(o.slice(r+1))),a.length>1){const i=a.slice(1),s=i.indexOf("?");s!==-1?a=`#${i.slice(0,s+1)}${Fe(i.slice(s+1))}`:i.includes("=")&&(a=`#${Fe(i)}`)}return bt(o+a)}function Vn(e){if(e==null)return e;let t=String(e);return t&&(t=t.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g,n=>mt(n)),t=t.replace(Nn,`Bearer ${K}`),bt(t))}function $e(e){const t=[];return{push(n){t.push(n),t.length>e&&t.splice(0,t.length-e)},all:()=>t.slice(),clear:()=>{t.length=0},get size(){return t.length}}}const yt=["log","info","warn","error","debug"];function Fn(e,{levels:t=["warn","error","log","info"]}={}){const n={};for(const o of yt)n[o]=console[o],t.includes(o)&&(console[o]=(...a)=>{try{e.push({level:o,text:a.map(xt).join(" ").slice(0,2e3),at:new Date().toISOString()})}catch{}n[o].apply(console,a)});return()=>{for(const o of yt)console[o]=n[o]}}function Wn(e,{slowMs:t=2e3}={}){const n=window.fetch,o=XMLHttpRequest.prototype.open,a=XMLHttpRequest.prototype.send;return n&&(window.fetch=async function(...i){var p,f,u;const s=performance.now(),d=typeof i[0]=="string"?i[0]:(p=i[0])==null?void 0:p.url,c=((f=i[1])==null?void 0:f.method)||(typeof i[0]=="object"?(u=i[0])==null?void 0:u.method:"GET")||"GET";try{const h=await n.apply(this,i);return We(e,{url:d,method:c,status:h.status,ms:Math.round(performance.now()-s),slowMs:t}),h}catch(h){throw We(e,{url:d,method:c,status:0,error:String((h==null?void 0:h.message)||h),ms:Math.round(performance.now()-s),slowMs:t}),h}}),XMLHttpRequest.prototype.open=function(i,s,...d){return this.__bc={method:i,url:s,started:0},o.call(this,i,s,...d)},XMLHttpRequest.prototype.send=function(...i){return this.__bc&&(this.__bc.started=performance.now(),this.addEventListener("loadend",()=>{We(e,{url:this.__bc.url,method:this.__bc.method,status:this.status,ms:Math.round(performance.now()-this.__bc.started),slowMs:t})})),a.apply(this,i)},()=>{n&&(window.fetch=n),XMLHttpRequest.prototype.open=o,XMLHttpRequest.prototype.send=a}}function We(e,{url:t,method:n,status:o,ms:a,error:r,slowMs:i}){try{e.push({url:mt(String(t)).slice(0,500),method:n,status:o,ms:a,error:r===void 0?void 0:Vn(r),failed:o===0||o>=400,slow:a>=i,at:new Date().toISOString()})}catch{}}function Yn(e){const t=o=>{const a=String(o.message||"Error"),r=o.filename?` (${o.filename}:${o.lineno}:${o.colno})`:"";e.push({level:"error",text:(/^uncaught/i.test(a)?a:`Uncaught ${a}`)+r,at:new Date().toISOString()})},n=o=>{e.push({level:"error",text:`Unhandled rejection: ${xt(o.reason)}`,at:new Date().toISOString()})};return window.addEventListener("error",t),window.addEventListener("unhandledrejection",n),()=>{window.removeEventListener("error",t),window.removeEventListener("unhandledrejection",n)}}async function wt(){const e=vt();try{if(navigator.getBattery){const t=await navigator.getBattery();e.battery=Math.round(t.level*100),e.charging=t.charging}}catch{}return e}function vt(){var t,n,o,a,r,i,s,d,c;const e=window.navigator||{};return{userAgent:e.userAgent,platform:e.platform,language:e.language,languages:e.languages?[...e.languages]:null,online:e.onLine,cookieEnabled:e.cookieEnabled,maxTouchPoints:e.maxTouchPoints??null,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:(t=window.screen)==null?void 0:t.width,height:(n=window.screen)==null?void 0:n.height,availWidth:(o=window.screen)==null?void 0:o.availWidth,availHeight:(a=window.screen)==null?void 0:a.availHeight,colorDepth:(r=window.screen)==null?void 0:r.colorDepth,orientation:((s=(i=window.screen)==null?void 0:i.orientation)==null?void 0:s.type)||null},devicePixelRatio:window.devicePixelRatio,referrer:document.referrer||null,title:document.title,capturedAt:new Date().toISOString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffsetMinutes:new Date().getTimezoneOffset(),browserMode:e.webdriver?"Automated":"Normal",doNotTrack:e.doNotTrack||null,hardwareConcurrency:e.hardwareConcurrency??null,deviceMemory:e.deviceMemory??null,connection:e.connection?{effectiveType:e.connection.effectiveType,downlink:e.connection.downlink,rtt:e.connection.rtt,saveData:e.connection.saveData}:null,prefersColorScheme:(d=window.matchMedia)!=null&&d.call(window,"(prefers-color-scheme: dark)").matches?"dark":"light",prefersReducedMotion:((c=window.matchMedia)==null?void 0:c.call(window,"(prefers-reduced-motion: reduce)").matches)||!1}}function xt(e){if(typeof e=="string")return e;if(e instanceof Error)return`${e.name}: ${e.message}`;try{return JSON.stringify(e)}catch{return String(e)}}const Xn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>',Jn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9.5l6 6 6-6"/></svg>',kt='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>',St='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>',$t='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>',se='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>',ge='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',oe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',Ct='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>',Zn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>';function Tt(e,t){console.warn(`[BugCatch] ${e}`,...t?[t]:[]);const n=new Error("[BugCatch] part of the widget could not be loaded — check the connection and try again.");return t&&(n.cause=t),n}function Et(e){let t=null;return(...n)=>(t||(t=e(...n).catch(o=>{throw t=null,o})),t)}const It=Et(()=>Promise.resolve().then(()=>gr).catch(e=>{throw Tt("the report panel could not be loaded.",e)})),Ce=Et(()=>Promise.resolve().then(()=>Mr).catch(e=>{throw Tt("the calling code could not be loaded.",e)})),Gn={info:Ct,success:oe,warning:Zn,critical:se};function Lt(e,{where:t,onDismiss:n}){const o=document.createElement("div");o.className=`notice tone-${e.tone} at-${t}`,o.setAttribute("role","status");const a=document.createElement("span");a.className="notice-ico",a.setAttribute("aria-hidden","true"),a.innerHTML=Gn[e.tone]||Ct;const r=document.createElement("div");r.className="notice-text";const i=document.createElement("strong");if(i.textContent=e.title,r.append(i),e.body){const s=document.createElement("p");s.textContent=e.body,r.append(s)}if(e.ctaHref&&e.ctaLabel){const s=document.createElement("a");s.className="notice-cta",s.href=e.ctaHref,s.textContent=e.ctaLabel,/^https?:/i.test(e.ctaHref)&&(s.target="_blank",s.rel="noopener noreferrer"),r.append(s)}if(o.append(a,r),e.dismissible&&n){const s=document.createElement("button");s.type="button",s.className="notice-x",s.setAttribute("aria-label","Dismiss this notice"),s.innerHTML=ge,s.addEventListener("click",()=>n(e)),o.append(s)}return o}const Ye="#0e0e10",Te="#ffffff";function Xe(e){const t=eo(e);if(!t)return Te;const[n,o,a]=t.map(i=>{const s=i/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4});return .2126*n+.7152*o+.0722*a>.179?Ye:Te}function eo(e){const t=String(e||"").trim();let n=/^#([0-9a-f]{3})$/i.exec(t);return n?[...n[1]].map(o=>parseInt(o+o,16)):(n=/^#([0-9a-f]{6})$/i.exec(t),n?[0,2,4].map(o=>parseInt(n[1].slice(o,o+2),16)):(n=/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/i.exec(t),n?[n[1],n[2],n[3]].map(Number):null))}const At={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"},be=[{value:"light",label:"Light",icon:kt},{value:"dark",label:"Dark",icon:St},{value:"auto",label:"System default",icon:$t}],Mt="bugcatch:theme";function to(){try{const e=localStorage.getItem(Mt);return be.some(t=>t.value===e)?e:null}catch{return null}}function no(e){try{localStorage.setItem(Mt,e)}catch{}}const Bt=`
|
|
2
|
+
--bc-bg: #151517;
|
|
3
|
+
--bc-elevated: #1c1c1f;
|
|
4
|
+
--bc-fg: #f3f2ef;
|
|
5
|
+
--bc-muted: #b3b0aa;
|
|
6
|
+
--bc-faint: #8f8c86;
|
|
7
|
+
--bc-border: #2c2c30;
|
|
8
|
+
--bc-subtle: #1f1f22;
|
|
9
|
+
--bc-stone: #26262a;
|
|
10
|
+
--bc-raised: #303035;
|
|
11
|
+
--bc-danger: #ff6b81;
|
|
12
|
+
--bc-ok: #4fd19a;
|
|
13
|
+
--bc-warn: #f2a54a;
|
|
14
|
+
--bc-info: #79a8ff;
|
|
15
|
+
--bc-brand-ink: #b3b0aa;
|
|
16
|
+
--bc-brand-mark: #a59cff;
|
|
17
|
+
--bc-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 30px 70px -20px rgba(0,0,0,.8), 0 8px 20px -8px rgba(0,0,0,.5);
|
|
18
|
+
--bc-shadow-sm: 0 0 0 1px rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.4);
|
|
19
|
+
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 14%, var(--bc-bg));`,oo=e=>`
|
|
2
20
|
:host { all: initial; }
|
|
3
21
|
:host {
|
|
4
|
-
--bc-accent: ${
|
|
5
|
-
--bc-on-accent:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
--bc-
|
|
9
|
-
--bc-
|
|
10
|
-
--bc-
|
|
11
|
-
--bc-
|
|
12
|
-
--bc-
|
|
13
|
-
--bc-
|
|
14
|
-
--bc-
|
|
15
|
-
--bc-
|
|
16
|
-
--bc-
|
|
22
|
+
--bc-accent: ${e||"var(--bc-fg)"};
|
|
23
|
+
--bc-on-accent: ${e?Xe(e):"var(--bc-bg)"};
|
|
24
|
+
/* The assistant's orb: BugCatch's own three colours, or the host's accent
|
|
25
|
+
with two lighter cuts of it, so the orb on their site is in their colour. */
|
|
26
|
+
--bc-o1: ${e?`color-mix(in srgb, ${e} 32%, #fff)`:"#ffb3c9"};
|
|
27
|
+
--bc-o2: ${e||"#6a5cff"};
|
|
28
|
+
--bc-o3: ${e?`color-mix(in srgb, ${e} 22%, #ffe7d1)`:"#ffd6a0"};
|
|
29
|
+
--bc-bg: #ffffff;
|
|
30
|
+
--bc-elevated: #ffffff;
|
|
31
|
+
--bc-fg: #0e0e10;
|
|
32
|
+
--bc-muted: #57544e;
|
|
33
|
+
--bc-faint: #75726c;
|
|
34
|
+
--bc-border: #e9e7e3;
|
|
35
|
+
--bc-subtle: #f6f5f3;
|
|
36
|
+
/* Warm stone: fields, chips and the selected track. */
|
|
37
|
+
--bc-stone: #f0efec;
|
|
38
|
+
--bc-raised: #ffffff;
|
|
39
|
+
--bc-danger: #c8233d;
|
|
40
|
+
--bc-ok: #0b7a55;
|
|
41
|
+
--bc-warn: #a4570a;
|
|
42
|
+
--bc-info: #2459d1;
|
|
17
43
|
/* The lockup's own two colours, kept off --bc-accent on purpose: that one is
|
|
18
44
|
the customer's brand, and this mark is ours. Values are the light cut of
|
|
19
45
|
brand/sphoro-bugcatch-primary.svg, pulled up from near-black so the mark
|
|
20
46
|
identifies itself without out-shouting the host's page. */
|
|
21
|
-
--bc-brand-ink: #
|
|
47
|
+
--bc-brand-ink: #57544e;
|
|
22
48
|
--bc-brand-mark: #5647ee;
|
|
23
|
-
--bc-shadow: 0
|
|
24
|
-
--bc-shadow-sm: 0 1px
|
|
25
|
-
--bc-dur:
|
|
49
|
+
--bc-shadow: 0 0 0 1px rgba(20,18,14,.06), 0 30px 70px -24px rgba(20,18,14,.30), 0 8px 20px -8px rgba(20,18,14,.10);
|
|
50
|
+
--bc-shadow-sm: 0 0 0 1px rgba(20,18,14,.06), 0 1px 2px rgba(20,18,14,.05);
|
|
51
|
+
--bc-dur: 220ms;
|
|
26
52
|
--bc-ease: cubic-bezier(.22,1,.36,1);
|
|
53
|
+
/* Film grain over the orb, so it reads as light rather than a gradient. */
|
|
54
|
+
--bc-grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
|
|
27
55
|
/* The system everything below is drawn from. Derived tokens are written in
|
|
28
56
|
terms of the ones above, so a host that overrides --bc-accent or the
|
|
29
57
|
palette gets a coherent result without touching these. */
|
|
30
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent)
|
|
31
|
-
--bc-accent-line: color-mix(in srgb, var(--bc-accent)
|
|
32
|
-
--bc-ring: 0 0 0 3px color-mix(in srgb, var(--bc-accent)
|
|
58
|
+
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 7%, var(--bc-bg));
|
|
59
|
+
--bc-accent-line: color-mix(in srgb, var(--bc-accent) 30%, var(--bc-border));
|
|
60
|
+
--bc-ring: 0 0 0 3px color-mix(in srgb, var(--bc-accent) 16%, transparent);
|
|
33
61
|
--bc-r-sm: 8px;
|
|
34
62
|
--bc-r-md: 12px;
|
|
35
|
-
--bc-r-lg:
|
|
36
|
-
--bc-r-xl:
|
|
63
|
+
--bc-r-lg: 16px;
|
|
64
|
+
--bc-r-xl: 20px;
|
|
37
65
|
--bc-fs-xs: 11.5px;
|
|
38
66
|
--bc-fs-sm: 12.5px;
|
|
39
67
|
--bc-fs-md: 14px;
|
|
40
|
-
--bc-fs-lg:
|
|
68
|
+
--bc-fs-lg: 15px;
|
|
41
69
|
--bc-pad: 18px;
|
|
42
70
|
}
|
|
43
|
-
:host(.bc-dark) {
|
|
44
|
-
--bc-bg: #14161c;
|
|
45
|
-
--bc-elevated: #1c1f27;
|
|
46
|
-
--bc-fg: #eef0f4;
|
|
47
|
-
--bc-muted: #a3aab6;
|
|
48
|
-
--bc-faint: #6f7682;
|
|
49
|
-
--bc-border: #2a2e38;
|
|
50
|
-
--bc-subtle: #1f222a;
|
|
51
|
-
--bc-raised: #363d4b;
|
|
52
|
-
--bc-warn: #f59e0b;
|
|
53
|
-
--bc-brand-ink: #9aa1ad;
|
|
54
|
-
--bc-brand-mark: #9b8fff;
|
|
55
|
-
--bc-shadow: 0 24px 64px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.4);
|
|
56
|
-
--bc-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
|
|
57
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 18%, var(--bc-bg));
|
|
71
|
+
:host(.bc-dark) {${Bt}
|
|
58
72
|
}
|
|
59
73
|
@media (prefers-color-scheme: dark) {
|
|
60
|
-
:host(.bc-auto) {
|
|
61
|
-
--bc-bg: #14161c;
|
|
62
|
-
--bc-elevated: #1c1f27;
|
|
63
|
-
--bc-fg: #eef0f4;
|
|
64
|
-
--bc-muted: #a3aab6;
|
|
65
|
-
--bc-faint: #6f7682;
|
|
66
|
-
--bc-border: #2a2e38;
|
|
67
|
-
--bc-subtle: #1f222a;
|
|
68
|
-
--bc-raised: #363d4b;
|
|
69
|
-
--bc-warn: #f59e0b;
|
|
70
|
-
--bc-brand-ink: #9aa1ad;
|
|
71
|
-
--bc-brand-mark: #9b8fff;
|
|
72
|
-
--bc-shadow: 0 24px 64px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.4);
|
|
73
|
-
--bc-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
|
|
74
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 18%, var(--bc-bg));
|
|
74
|
+
:host(.bc-auto) {${Bt}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
* { box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif; }
|
|
79
|
+
|
|
80
|
+
/* ---------- the orb ----------
|
|
81
|
+
The assistant's face, on the launcher and at the top of every screen: three
|
|
82
|
+
blurred colour blobs turning slowly under a highlight and grain. Hue from
|
|
83
|
+
--bc-o1..3. Sized by whoever places it. */
|
|
84
|
+
.orb {
|
|
85
|
+
position: relative; display: block; flex: none; aspect-ratio: 1; border-radius: 50%;
|
|
86
|
+
background: var(--bc-o2); overflow: hidden; isolation: isolate;
|
|
87
|
+
box-shadow: inset -3px -5px 10px rgba(0,0,0,.22), inset 2px 3px 7px rgba(255,255,255,.35);
|
|
88
|
+
}
|
|
89
|
+
.orb::before {
|
|
90
|
+
content: ''; position: absolute; inset: -20%; border-radius: 50%; z-index: -1;
|
|
91
|
+
background:
|
|
92
|
+
radial-gradient(circle at 70% 72%, var(--bc-o3) 0%, transparent 44%),
|
|
93
|
+
radial-gradient(circle at 26% 66%, var(--bc-o1) 0%, transparent 48%),
|
|
94
|
+
radial-gradient(circle at 58% 30%, var(--bc-o2) 0%, transparent 62%);
|
|
95
|
+
filter: blur(3px);
|
|
96
|
+
animation: bc-orb-turn 18s linear infinite;
|
|
97
|
+
}
|
|
98
|
+
.orb::after {
|
|
99
|
+
content: ''; position: absolute; inset: 0; border-radius: 50%;
|
|
100
|
+
background: radial-gradient(circle at 34% 26%, rgba(255,255,255,.85) 0 5%, rgba(255,255,255,0) 30%), var(--bc-grain);
|
|
101
|
+
mix-blend-mode: soft-light;
|
|
102
|
+
}
|
|
103
|
+
@keyframes bc-orb-turn { to { transform: rotate(360deg); } }
|
|
79
104
|
svg { width: 1em; height: 1em; display: block; }
|
|
80
105
|
/* The hidden attribute has to actually hide. Nearly every element in here is given a
|
|
81
106
|
display by a rule below, and any of them beats the attribute's own UA style
|
|
@@ -106,65 +131,50 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
106
131
|
@keyframes bc-launcher-in { from { opacity: 0; transform: translateY(12px) scale(.86) } to { opacity: 1; transform: none } }
|
|
107
132
|
@keyframes bc-item-in { from { opacity: 0; transform: translateY(8px) scale(.96) } to { opacity: 1; transform: none } }
|
|
108
133
|
|
|
109
|
-
/* ---------- dock:
|
|
134
|
+
/* ---------- dock: the launcher, and what is said beside it ---------- */
|
|
110
135
|
.dock {
|
|
111
136
|
position: fixed; z-index: 2147483000;
|
|
112
137
|
display: flex; flex-direction: column; gap: 10px;
|
|
113
138
|
}
|
|
114
139
|
.dock[hidden] { display: none; }
|
|
115
|
-
/* While the panel is open the
|
|
116
|
-
|
|
140
|
+
/* While the panel is open the launcher rises above the scrim, so the button
|
|
141
|
+
that opened it is the button that closes it. */
|
|
117
142
|
.dock.over { z-index: 2147483002; }
|
|
118
143
|
.dock.at-right { align-items: flex-end; }
|
|
119
144
|
.dock.at-left { align-items: flex-start; }
|
|
120
|
-
/* Anchored to the top, "above the launcher" would be off-screen, so
|
|
121
|
-
|
|
145
|
+
/* Anchored to the top, "above the launcher" would be off-screen, so cards go
|
|
146
|
+
under it and the launcher stays the outermost thing. */
|
|
122
147
|
.dock.at-top { flex-direction: column-reverse; }
|
|
123
148
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
box-shadow: 0 6px 18px rgba(10,12,16,.14), 0 1px 3px rgba(10,12,16,.08);
|
|
129
|
-
animation: bc-launcher-in 420ms var(--bc-ease) both;
|
|
130
|
-
}
|
|
131
|
-
.themer button {
|
|
132
|
-
display: grid; place-items: center;
|
|
133
|
-
width: 28px; height: 28px; padding: 0;
|
|
134
|
-
border: none; border-radius: 999px; background: transparent;
|
|
135
|
-
color: var(--bc-muted); cursor: pointer;
|
|
136
|
-
transition: background var(--bc-dur) var(--bc-ease), color var(--bc-dur) var(--bc-ease), transform 140ms var(--bc-ease);
|
|
137
|
-
}
|
|
138
|
-
.themer button svg { font-size: 15px; }
|
|
139
|
-
.themer button:hover { background: var(--bc-subtle); color: var(--bc-fg); }
|
|
140
|
-
.themer button:active { transform: scale(.92); }
|
|
141
|
-
.themer button[aria-pressed="true"] { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
142
|
-
.themer button[aria-pressed="true"]:hover { background: var(--bc-accent); filter: brightness(1.06); }
|
|
143
|
-
|
|
144
|
-
/* ---------- launcher ---------- */
|
|
149
|
+
/* ---------- launcher ----------
|
|
150
|
+
A pill with the assistant's orb in it: ink by default, the host's colour when
|
|
151
|
+
they set one. The shadow is neutral, never tinted, so a bright brand colour
|
|
152
|
+
does not glow on somebody's checkout. */
|
|
145
153
|
.launcher {
|
|
146
154
|
position: relative;
|
|
147
|
-
display: inline-flex; align-items: center; gap:
|
|
148
|
-
height:
|
|
155
|
+
display: inline-flex; align-items: center; gap: 10px;
|
|
156
|
+
height: 46px; padding: 0 18px 0 7px; border: none; border-radius: 999px;
|
|
149
157
|
background: var(--bc-accent); color: var(--bc-on-accent);
|
|
150
|
-
font-size: var(--bc-fs-md); font-weight:
|
|
158
|
+
font-size: var(--bc-fs-md); font-weight: 560; line-height: 1; letter-spacing: -.01em;
|
|
151
159
|
cursor: pointer;
|
|
152
|
-
box-shadow: 0
|
|
153
|
-
transition: transform var(--bc-dur) var(--bc-ease), box-shadow var(--bc-dur) var(--bc-ease), filter 160ms linear
|
|
160
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.18), 0 10px 26px -8px rgba(0,0,0,.36);
|
|
161
|
+
transition: transform var(--bc-dur) var(--bc-ease), box-shadow var(--bc-dur) var(--bc-ease), filter 160ms linear;
|
|
154
162
|
animation: bc-launcher-in 420ms var(--bc-ease) both;
|
|
155
163
|
}
|
|
156
|
-
/* Two
|
|
164
|
+
/* Two faces in one circle: the orb when closed, a chevron when open, turned
|
|
157
165
|
into each other so the button reads as the panel's own handle. */
|
|
158
|
-
.launcher .ico { position: relative; width:
|
|
166
|
+
.launcher .ico { position: relative; width: 32px; height: 32px; flex: none; }
|
|
159
167
|
.launcher .ico > span {
|
|
160
|
-
position: absolute; inset: 0;
|
|
168
|
+
position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%;
|
|
161
169
|
transition: transform 320ms var(--bc-ease), opacity 200ms ease;
|
|
162
170
|
}
|
|
163
|
-
.launcher .ico
|
|
171
|
+
.launcher .ico .orb { width: 32px; }
|
|
172
|
+
.launcher .ico .when-open { background: color-mix(in srgb, var(--bc-on-accent) 14%, transparent); }
|
|
173
|
+
.launcher .ico svg { width: 18px; height: 18px; }
|
|
164
174
|
.launcher .ico .when-open { opacity: 0; transform: rotate(-90deg) scale(.6); }
|
|
165
175
|
.launcher[aria-expanded="true"] .ico .when-closed { opacity: 0; transform: rotate(90deg) scale(.6); }
|
|
166
176
|
.launcher[aria-expanded="true"] .ico .when-open { opacity: 1; transform: none; }
|
|
167
|
-
.launcher:hover { transform: translateY(-
|
|
177
|
+
.launcher:hover { transform: translateY(-1px); box-shadow: 0 1px 2px rgba(0,0,0,.18), 0 14px 30px -8px rgba(0,0,0,.42); }
|
|
168
178
|
.launcher:active { transform: translateY(0) scale(.97); transition-duration: 90ms; }
|
|
169
179
|
.launcher:focus-visible { outline-offset: 3px; }
|
|
170
180
|
.launcher[hidden] { display: none; }
|
|
@@ -187,11 +197,11 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
187
197
|
In this sheet because the card beside the button exists before the panel's
|
|
188
198
|
does. The tone is a colour and an icon; the site's accent is the info one. */
|
|
189
199
|
.notice {
|
|
190
|
-
--tone: var(--bc-
|
|
200
|
+
--tone: var(--bc-info);
|
|
191
201
|
display: flex; align-items: flex-start; gap: 10px;
|
|
192
|
-
padding:
|
|
193
|
-
background:
|
|
194
|
-
border: 1px solid
|
|
202
|
+
padding: 11px 10px 11px 12px; border-radius: var(--bc-r-md);
|
|
203
|
+
background: var(--bc-subtle);
|
|
204
|
+
border: 1px solid var(--bc-border);
|
|
195
205
|
color: var(--bc-fg);
|
|
196
206
|
font-size: var(--bc-fs-sm); line-height: 1.45; text-align: left;
|
|
197
207
|
animation: bc-item-in 240ms var(--bc-ease) both;
|
|
@@ -199,33 +209,48 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
199
209
|
.notice.tone-success { --tone: var(--bc-ok); }
|
|
200
210
|
.notice.tone-warning { --tone: var(--bc-warn); }
|
|
201
211
|
.notice.tone-critical { --tone: var(--bc-danger); }
|
|
202
|
-
|
|
212
|
+
/* The tone is the icon's colour and a wash behind it — enough to tell a delay
|
|
213
|
+
from a fix at a glance, without a coloured card shouting over the form. */
|
|
214
|
+
.notice-ico {
|
|
215
|
+
flex: none; display: grid; place-items: center; width: 22px; height: 22px; margin-top: -1px;
|
|
216
|
+
border-radius: 7px; font-size: 14px;
|
|
217
|
+
color: var(--tone); background: color-mix(in srgb, var(--tone) 13%, transparent);
|
|
218
|
+
}
|
|
203
219
|
.notice-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
204
|
-
.notice-text strong { display: block; font-weight:
|
|
220
|
+
.notice-text strong { display: block; font-weight: 600; letter-spacing: -.005em; }
|
|
205
221
|
.notice-text p { margin: 2px 0 0; color: var(--bc-muted); white-space: pre-line; }
|
|
206
222
|
.notice-cta {
|
|
207
|
-
display: inline-
|
|
208
|
-
color: var(--
|
|
223
|
+
display: inline-flex; align-items: center; gap: 4px; margin-top: 6px;
|
|
224
|
+
color: var(--bc-fg); font-weight: 600; text-decoration: underline;
|
|
225
|
+
text-decoration-color: color-mix(in srgb, var(--bc-fg) 30%, transparent); text-underline-offset: 3px;
|
|
209
226
|
}
|
|
210
|
-
.notice-cta:hover { text-decoration
|
|
227
|
+
.notice-cta:hover { text-decoration-color: currentColor; }
|
|
211
228
|
.notice-x {
|
|
212
229
|
flex: none; display: grid; place-items: center;
|
|
213
|
-
width:
|
|
230
|
+
width: 24px; height: 24px; margin: -2px -2px 0 0; padding: 0;
|
|
214
231
|
border: 0; border-radius: 999px; background: transparent;
|
|
215
|
-
color: var(--bc-
|
|
232
|
+
color: var(--bc-faint); cursor: pointer;
|
|
216
233
|
}
|
|
217
|
-
.notice-x:hover { background: color-mix(in srgb, var(--
|
|
218
|
-
.notice-x svg { font-size:
|
|
234
|
+
.notice-x:hover { background: color-mix(in srgb, var(--bc-fg) 7%, transparent); color: var(--bc-fg); }
|
|
235
|
+
.notice-x svg { font-size: 13px; }
|
|
219
236
|
/* Beside the button it floats over somebody else's page: opaque, lifted, and
|
|
220
237
|
never taller than a glance. The whole text is in the panel. */
|
|
221
238
|
.notice.at-launcher {
|
|
222
239
|
width: min(320px, calc(100vw - 40px));
|
|
223
|
-
|
|
240
|
+
background: var(--bc-elevated); border-color: transparent;
|
|
241
|
+
box-shadow: var(--bc-shadow);
|
|
242
|
+
padding: 13px 12px 13px 13px;
|
|
224
243
|
}
|
|
225
244
|
.notice.at-launcher .notice-text p {
|
|
226
245
|
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
|
|
227
246
|
}
|
|
228
|
-
|
|
247
|
+
/* In the panel they are a stack of short lines above the form, not a wall:
|
|
248
|
+
the body is held to two lines, and the whole of it was beside the button. */
|
|
249
|
+
.notice.at-panel { margin-bottom: 8px; padding: 9px 8px 9px 10px; }
|
|
250
|
+
.notice.at-panel .notice-text p {
|
|
251
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
|
|
252
|
+
}
|
|
253
|
+
.notice.at-panel .notice-cta { margin-top: 3px; }
|
|
229
254
|
|
|
230
255
|
/* The dock sits in a corner of a page the widget does not own. On a notched
|
|
231
256
|
phone that corner is under the home indicator, and in landscape it is under
|
|
@@ -245,25 +270,12 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
245
270
|
.dock.over { display: none; }
|
|
246
271
|
}
|
|
247
272
|
@media (pointer: coarse) {
|
|
248
|
-
/* The theme switch's buttons are small glyphs whose boxes cannot grow without
|
|
249
|
-
moving the launcher under them, so each keeps its size and gets an
|
|
250
|
-
invisible target drawn around it instead. */
|
|
251
|
-
.themer button { position: relative; }
|
|
252
|
-
.themer button::after {
|
|
253
|
-
content: '';
|
|
254
|
-
position: absolute;
|
|
255
|
-
inset: -8px;
|
|
256
|
-
}
|
|
257
|
-
/* The themer's three buttons sit side by side, so their expanders would
|
|
258
|
-
overlap each other without a gap to grow into. */
|
|
259
|
-
.themer { gap: 4px; }
|
|
260
273
|
.notice-x { width: 36px; height: 36px; margin: -9px -8px -6px 0; }
|
|
261
274
|
}
|
|
262
275
|
/* Hover is a lie on a touchscreen: it latches on tap and stays. The launcher's
|
|
263
276
|
lift in particular was left applied after the panel closed. */
|
|
264
277
|
@media (hover: none) {
|
|
265
278
|
.launcher:hover { transform: none; filter: none; }
|
|
266
|
-
.themer button:hover { transform: none; }
|
|
267
279
|
}
|
|
268
280
|
|
|
269
281
|
/* ---------- while the panel's code is on its way ----------
|
|
@@ -288,13 +300,13 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
288
300
|
}
|
|
289
301
|
.loadfail button[data-act="retry"] { text-decoration: underline; text-underline-offset: 2px; }
|
|
290
302
|
.loadfail button svg { font-size: 13px; margin: 0; }
|
|
291
|
-
`;function Wn(t){const e=document.createElement("div");e.setAttribute("data-bugcatch","widget");let n=Kn()||Yn(t.config.theme);e.className=Tt(n);const o=e.attachShadow({mode:"open"}),a=document.createElement("style");a.textContent=Fn(t.config.accent||"#4F46E5"),o.appendChild(a);const r=St[t.config.widgetPosition]?t.config.widgetPosition:"bottom-right",i=document.createElement("div");i.className=`dock ${r.includes("right")?"at-right":"at-left"}`+(r.startsWith("top")?" at-top":""),i.style.cssText=St[r];const s=document.createElement("div");s.className="themer",s.setAttribute("role","group"),s.setAttribute("aria-label","Report widget theme"),s.innerHTML=$t.map(C=>`<button type="button" data-theme="${C.value}" title="${C.label}" aria-label="${C.label}" aria-pressed="${C.value===n}">${C.icon}</button>`).join(""),s.addEventListener("click",C=>{const S=C.target.closest("button[data-theme]");!S||S.dataset.theme===n||(n=S.dataset.theme,e.className=Tt(n),Vn(n),s.querySelectorAll("button").forEach(x=>{x.setAttribute("aria-pressed",String(x.dataset.theme===n))}))});const c=document.createElement("button");c.className="launcher",c.type="button",c.innerHTML=`<span class="ico" aria-hidden="true"><span class="when-closed">${mt}</span><span class="when-open">${qn}</span></span><span>Report a bug</span>`,c.setAttribute("aria-haspopup","dialog"),c.setAttribute("aria-expanded","false");let l=null;c.addEventListener("click",()=>{if(l){l.close();return}l=f()});function f(){w(),b();let C=null,S=!1;const x=()=>{S=!0,c.removeAttribute("aria-busy"),l=null},v={close:()=>C?C.close():x(),destroy:()=>C?C.destroy():x()};return c.setAttribute("aria-busy","true"),xt(t.config.chunkBase).then(({openPanel:k})=>{S||(c.removeAttribute("aria-busy"),i.classList.add("over"),c.setAttribute("aria-expanded","true"),C=k({root:o,host:e,dock:i,client:t,preloadCall:g,onClose:()=>{l=null,i.classList.remove("over"),c.setAttribute("aria-expanded","false")}}))},()=>{S||(x(),m())}),v}const d=()=>{xt(t.config.chunkBase).catch(()=>{})};for(const C of["pointerenter","touchstart","focus"])c.addEventListener(C,d,{once:!0,passive:!0});const u=Et(d);function g(){Se(t.config.chunkBase).catch(()=>{})}let y=null;function m(){w(),y=document.createElement("div"),y.className="msg err loadfail",y.setAttribute("role","alert"),y.innerHTML=`${re}<span>The report form didn't load. Check your connection and try again.</span><button type="button" data-act="retry">Try again</button><button type="button" data-act="dismiss" aria-label="Dismiss">${fe}</button>`,y.querySelector('[data-act="retry"]').addEventListener("click",()=>{c.focus(),l||(l=f())}),y.querySelector('[data-act="dismiss"]').addEventListener("click",()=>{c.focus(),w()}),i.prepend(y)}function w(){y==null||y.remove(),y=null}let p=null;function h(C){b(),p=kt(C,{where:"launcher",onDismiss:S=>{t.dismissAnnouncement(S),c.focus(),b()}}),y?y.after(p):i.prepend(p)}function b(){p==null||p.remove(),p=null}const T=t.config.announcements===!1?()=>{}:Et(()=>{t.announcements().then(C=>{const S=C.find(x=>x.placement==="launcher");S&&!l&&e.isConnected&&h(S)}).catch(()=>{})});return i.append(s,c),o.appendChild(i),document.body.appendChild(e),t.widgetControls={open:()=>{l||c.click()},close:()=>{l==null||l.close()},isOpen:()=>!!l},()=>{u(),T(),l==null||l.destroy(),e.remove(),t.widgetControls=null}}function Yn(t){return t==="dark"||t==="light"?t:"auto"}function Tt(t){return t==="dark"?"bc-dark":t==="light"?"bc-light":"bc-auto"}function Et(t){let e=()=>{};const n=()=>{if(typeof requestIdleCallback=="function"){const o=requestIdleCallback(t,{timeout:5e3});e=()=>cancelIdleCallback(o)}else{const o=setTimeout(t,1500);e=()=>clearTimeout(o)}};return document.readyState==="complete"?n():(window.addEventListener("load",n,{once:!0}),e=()=>window.removeEventListener("load",n)),()=>e()}const Xn="Too many requests are being sent from here at the moment. Please try again in a minute.";function ue(t){return t||Xn}const Jn=typeof window<"u"&&window.fetch?window.fetch.bind(window):null,Zn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.open:null,Gn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.send:null,It=["image/png","image/jpeg","image/webp","image/gif","video/webm","video/mp4","audio/webm","audio/ogg","audio/mpeg","audio/mp4","audio/wav","application/pdf","text/plain","text/csv","application/json","application/zip","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],$e=["image/png","image/jpeg","image/webp","video/webm","video/mp4"],eo=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getUserMedia&&typeof MediaRecorder<"u")},to=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia&&typeof MediaRecorder<"u")},no=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia)};function Ce(t,e=It){const n=String(t||"").split(";")[0].trim().toLowerCase();return e.includes(n)?n:null}async function oo(){const t=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:1},audio:!1});try{const e=t.getVideoTracks()[0],n=document.createElement("video");n.srcObject=t,n.muted=!0,n.playsInline=!0,await n.play(),await new Promise(s=>requestAnimationFrame(()=>requestAnimationFrame(s)));const{width:o,height:a}=e.getSettings(),r=document.createElement("canvas");r.width=o||n.videoWidth,r.height=a||n.videoHeight,r.getContext("2d").drawImage(n,0,0,r.width,r.height);const i=await new Promise(s=>r.toBlob(s,"image/png"));if(!i)throw new Error("The browser returned an empty screenshot.");return{blob:i,mime:"image/png",kind:"SCREENSHOT"}}finally{t.getTracks().forEach(e=>e.stop())}}async function ao({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:15},audio:!1}),a=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"].find(g=>MediaRecorder.isTypeSupported(g))||"video/webm",r=new MediaRecorder(o,{mimeType:a,videoBitsPerSecond:25e5}),i=[];r.ondataavailable=g=>{g.data.size&&i.push(g.data)},r.start(1e3);const s=Date.now(),c=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-s)/1e3)),500),l=()=>{clearInterval(c),clearTimeout(u),o.getTracks().forEach(g=>g.stop())},f=new Promise(g=>{r.onstop=()=>{l(),g(new Blob(i,{type:a}))}}),d=()=>{r.state!=="inactive"&&r.stop(),n==null||n()};o.getVideoTracks()[0].addEventListener("ended",d);const u=setTimeout(d,t);return{mime:a,maxMs:t,async stop(){return clearTimeout(u),r.state!=="inactive"&&r.stop(),{blob:await f,mime:a,kind:"VIDEO"}},cancel(){l(),r.state!=="inactive"&&r.stop()}}}async function ro({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getUserMedia({audio:!0}),a=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg"].find(g=>MediaRecorder.isTypeSupported(g))||"",r=new MediaRecorder(o,a?{mimeType:a}:void 0),i=[];r.ondataavailable=g=>{g.data.size&&i.push(g.data)},r.start(1e3);const s=Date.now(),c=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-s)/1e3)),500),l=()=>{clearInterval(c),clearTimeout(u),o.getTracks().forEach(g=>g.stop())},f=new Promise(g=>{r.onstop=()=>{l(),g(new Blob(i,{type:r.mimeType||a}))}}),u=setTimeout(()=>{r.state!=="inactive"&&r.stop(),n==null||n()},t);return{mime:r.mimeType||a,maxMs:t,async stop(){clearTimeout(u),r.state!=="inactive"&&r.stop();const g=await f;return{blob:g,mime:g.type||r.mimeType||a,kind:"AUDIO"}},cancel(){l(),r.state!=="inactive"&&r.stop()}}}async function io({apiBase:t,apiKey:e,blob:n,mime:o,onProgress:a}){var l;const r=Ce(o||n.type);if(!r)throw new Error(`[BugCatch] ${o||n.type||"that file"} can't be attached.`);const i=await Jn(`${t}/ingest/presign`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e},body:JSON.stringify({mime:r})});if(i.status===429){let f="";try{f=((l=await i.json())==null?void 0:l.message)||""}catch{}throw new Error(`[BugCatch] ${ue(typeof f=="string"?f:"")}`)}if(!i.ok)throw new Error(`[BugCatch] could not start the upload (HTTP ${i.status}).`);const{key:s,uploadUrl:c}=await i.json();return await so(c,n,r,a),{storageKey:s,mime:r}}function so(t,e,n,o){return new Promise((a,r)=>{const i=new XMLHttpRequest;Zn.call(i,"PUT",t,!0),i.setRequestHeader("Content-Type",n),i.upload.onprogress=s=>{s.lengthComputable&&(o==null||o(s.loaded/s.total))},i.onload=()=>{i.status>=200&&i.status<300?a():r(new Error(`[BugCatch] upload failed (HTTP ${i.status}).`))},i.onerror=()=>r(new Error("[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy.")),i.onabort=()=>r(new Error("[BugCatch] upload cancelled.")),Gn.call(i,e)})}function pe(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(0)} KB`:`${(t/1024/1024).toFixed(1)} MB`}function Te(t){const e=Math.floor(t/60),n=t%60;return`${e}:${String(n).padStart(2,"0")}`}const Ee="bugcatch.watch",Lt=[2e3,5e3,15e3,3e4,6e4],co=5e3;let ge=null;function lo(t){ge=t||null}const Ve=()=>ge?`${Ee}:${ge}`:Ee;function Fe(){return ge?`?projectId=${encodeURIComponent(ge)}`:""}function P(){try{const t=window.localStorage;return(t==null?void 0:t.getItem(Ve()))||(t==null?void 0:t.getItem(Ee))||null}catch{return null}}function We(t){var e;if(t)try{(e=window.localStorage)==null||e.setItem(Ve(),t)}catch{}}function se(){var t,e;try{(t=window.localStorage)==null||t.removeItem(Ve()),(e=window.localStorage)==null||e.removeItem(Ee)}catch{}At()}const Ie="bugcatch.unread";function uo(t){return[(t==null?void 0:t.bugId)||"report",(t==null?void 0:t.kind)||"status",(t==null?void 0:t.at)||""].join("|")}function be(){var t;try{const e=(t=window.localStorage)==null?void 0:t.getItem(Ie),n=e?JSON.parse(e):[];return Array.isArray(n)?n.filter(o=>o&&typeof o.id=="string"):[]}catch{return[]}}function Le(t){var e,n;try{t.length?(e=window.localStorage)==null||e.setItem(Ie,JSON.stringify(t)):(n=window.localStorage)==null||n.removeItem(Ie)}catch{}}function po(t){const e={...t,id:uo(t)},n=be().filter(o=>o.id!==e.id);return n.push(e),Le(n.slice(-20)),e}function ho(t){const e=be().filter(n=>n.id!==t);return Le(e),e}function fo(t){const e=be().filter(n=>n.bugId!==t);return Le(e),e}function At(){return Le([]),[]}function go(t,e){let n=t,o=n.indexOf(`
|
|
303
|
+
`;function ao(e){const t=document.createElement("div");t.setAttribute("data-bugcatch","widget");let n=to()||ro(e.config.theme);t.className=Rt(n);const o=t.attachShadow({mode:"open"}),a=document.createElement("style");a.textContent=oo(e.config.accent||null),o.appendChild(a);const r=At[e.config.widgetPosition]?e.config.widgetPosition:"bottom-right",i=document.createElement("div");i.className=`dock ${r.includes("right")?"at-right":"at-left"}`+(r.startsWith("top")?" at-top":""),i.style.cssText=At[r];const s={current:()=>n,label:()=>be.find(y=>y.value===n).label,cycle(){const y=be[(be.findIndex(x=>x.value===n)+1)%be.length];return n=y.value,t.className=Rt(n),no(n),y}},d=document.createElement("button");d.className="launcher",d.type="button",d.innerHTML=`<span class="ico" aria-hidden="true"><span class="when-closed"><span class="orb"></span></span><span class="when-open">${Jn}</span></span><span>Report a bug</span>`,d.setAttribute("aria-haspopup","dialog"),d.setAttribute("aria-expanded","false");let c=null;d.addEventListener("click",()=>{if(c){c.close();return}c=p()});function p(){w(),l();let y=null,x=!1;const v=()=>{x=!0,d.removeAttribute("aria-busy"),c=null},k={close:()=>y?y.close():v(),destroy:()=>y?y.destroy():v()};return d.setAttribute("aria-busy","true"),It(e.config.chunkBase).then(({openPanel:T})=>{x||(d.removeAttribute("aria-busy"),i.classList.add("over"),d.setAttribute("aria-expanded","true"),y=T({root:o,host:t,dock:i,client:e,preloadCall:h,themeControls:s,onClose:()=>{c=null,i.classList.remove("over"),d.setAttribute("aria-expanded","false")}}))},()=>{x||(v(),C())}),k}const f=()=>{It(e.config.chunkBase).catch(()=>{})};for(const y of["pointerenter","touchstart","focus"])d.addEventListener(y,f,{once:!0,passive:!0});const u=jt(f);function h(){Ce(e.config.chunkBase).catch(()=>{})}let m=null;function C(){w(),m=document.createElement("div"),m.className="msg err loadfail",m.setAttribute("role","alert"),m.innerHTML=`${se}<span>The report form didn't load. Check your connection and try again.</span><button type="button" data-act="retry">Try again</button><button type="button" data-act="dismiss" aria-label="Dismiss">${ge}</button>`,m.querySelector('[data-act="retry"]').addEventListener("click",()=>{d.focus(),c||(c=p())}),m.querySelector('[data-act="dismiss"]').addEventListener("click",()=>{d.focus(),w()}),i.prepend(m)}function w(){m==null||m.remove(),m=null}let g=null;function b(y){l(),g=Lt(y,{where:"launcher",onDismiss:x=>{e.dismissAnnouncement(x),d.focus(),l()}}),m?m.after(g):i.prepend(g)}function l(){g==null||g.remove(),g=null}const S=e.config.announcements===!1?()=>{}:jt(()=>{e.announcements().then(y=>{const x=y.find(v=>v.placement==="launcher");x&&!c&&t.isConnected&&b(x)}).catch(()=>{})});return i.append(d),o.appendChild(i),document.body.appendChild(t),e.widgetControls={open:()=>{c||d.click()},close:()=>{c==null||c.close()},isOpen:()=>!!c},()=>{u(),S(),c==null||c.destroy(),t.remove(),e.widgetControls=null}}function ro(e){return e==="dark"||e==="light"?e:"auto"}function Rt(e){return e==="dark"?"bc-dark":e==="light"?"bc-light":"bc-auto"}function jt(e){let t=()=>{};const n=()=>{if(typeof requestIdleCallback=="function"){const o=requestIdleCallback(e,{timeout:5e3});t=()=>cancelIdleCallback(o)}else{const o=setTimeout(e,1500);t=()=>clearTimeout(o)}};return document.readyState==="complete"?n():(window.addEventListener("load",n,{once:!0}),t=()=>window.removeEventListener("load",n)),()=>t()}const io="Too many requests are being sent from here at the moment. Please try again in a minute.";function pe(e){return e||io}const so=typeof window<"u"&&window.fetch?window.fetch.bind(window):null,co=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.open:null,lo=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.send:null,Ot=["image/png","image/jpeg","image/webp","image/gif","video/webm","video/mp4","audio/webm","audio/ogg","audio/mpeg","audio/mp4","audio/wav","application/pdf","text/plain","text/csv","application/json","application/zip","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],Ee=["image/png","image/jpeg","image/webp","video/webm","video/mp4"],uo=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getUserMedia&&typeof MediaRecorder<"u")},po=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getDisplayMedia&&typeof MediaRecorder<"u")},ho=()=>{var e;return!!((e=navigator==null?void 0:navigator.mediaDevices)!=null&&e.getDisplayMedia)};function Ie(e,t=Ot){const n=String(e||"").split(";")[0].trim().toLowerCase();return t.includes(n)?n:null}async function fo(){const e=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:1},audio:!1});try{const t=e.getVideoTracks()[0],n=document.createElement("video");n.srcObject=e,n.muted=!0,n.playsInline=!0,await n.play(),await new Promise(s=>requestAnimationFrame(()=>requestAnimationFrame(s)));const{width:o,height:a}=t.getSettings(),r=document.createElement("canvas");r.width=o||n.videoWidth,r.height=a||n.videoHeight,r.getContext("2d").drawImage(n,0,0,r.width,r.height);const i=await new Promise(s=>r.toBlob(s,"image/png"));if(!i)throw new Error("The browser returned an empty screenshot.");return{blob:i,mime:"image/png",kind:"SCREENSHOT"}}finally{e.getTracks().forEach(t=>t.stop())}}async function go({maxMs:e=12e4,onTick:t,onAutoStop:n}={}){const o=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:15},audio:!1}),a=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"].find(h=>MediaRecorder.isTypeSupported(h))||"video/webm",r=new MediaRecorder(o,{mimeType:a,videoBitsPerSecond:25e5}),i=[];r.ondataavailable=h=>{h.data.size&&i.push(h.data)},r.start(1e3);const s=Date.now(),d=setInterval(()=>t==null?void 0:t(Math.floor((Date.now()-s)/1e3)),500),c=()=>{clearInterval(d),clearTimeout(u),o.getTracks().forEach(h=>h.stop())},p=new Promise(h=>{r.onstop=()=>{c(),h(new Blob(i,{type:a}))}}),f=()=>{r.state!=="inactive"&&r.stop(),n==null||n()};o.getVideoTracks()[0].addEventListener("ended",f);const u=setTimeout(f,e);return{mime:a,maxMs:e,async stop(){return clearTimeout(u),r.state!=="inactive"&&r.stop(),{blob:await p,mime:a,kind:"VIDEO"}},cancel(){c(),r.state!=="inactive"&&r.stop()}}}async function bo({maxMs:e=12e4,onTick:t,onAutoStop:n}={}){const o=await navigator.mediaDevices.getUserMedia({audio:!0}),a=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg"].find(h=>MediaRecorder.isTypeSupported(h))||"",r=new MediaRecorder(o,a?{mimeType:a}:void 0),i=[];r.ondataavailable=h=>{h.data.size&&i.push(h.data)},r.start(1e3);const s=Date.now(),d=setInterval(()=>t==null?void 0:t(Math.floor((Date.now()-s)/1e3)),500),c=()=>{clearInterval(d),clearTimeout(u),o.getTracks().forEach(h=>h.stop())},p=new Promise(h=>{r.onstop=()=>{c(),h(new Blob(i,{type:r.mimeType||a}))}}),u=setTimeout(()=>{r.state!=="inactive"&&r.stop(),n==null||n()},e);return{mime:r.mimeType||a,maxMs:e,async stop(){clearTimeout(u),r.state!=="inactive"&&r.stop();const h=await p;return{blob:h,mime:h.type||r.mimeType||a,kind:"AUDIO"}},cancel(){c(),r.state!=="inactive"&&r.stop()}}}async function mo({apiBase:e,apiKey:t,blob:n,mime:o,onProgress:a}){var c;const r=Ie(o||n.type);if(!r)throw new Error(`[BugCatch] ${o||n.type||"that file"} can't be attached.`);const i=await so(`${e}/ingest/presign`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":t},body:JSON.stringify({mime:r})});if(i.status===429){let p="";try{p=((c=await i.json())==null?void 0:c.message)||""}catch{}throw new Error(`[BugCatch] ${pe(typeof p=="string"?p:"")}`)}if(!i.ok)throw new Error(`[BugCatch] could not start the upload (HTTP ${i.status}).`);const{key:s,uploadUrl:d}=await i.json();return await yo(d,n,r,a),{storageKey:s,mime:r}}function yo(e,t,n,o){return new Promise((a,r)=>{const i=new XMLHttpRequest;co.call(i,"PUT",e,!0),i.setRequestHeader("Content-Type",n),i.upload.onprogress=s=>{s.lengthComputable&&(o==null||o(s.loaded/s.total))},i.onload=()=>{i.status>=200&&i.status<300?a():r(new Error(`[BugCatch] upload failed (HTTP ${i.status}).`))},i.onerror=()=>r(new Error("[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy.")),i.onabort=()=>r(new Error("[BugCatch] upload cancelled.")),lo.call(i,t)})}function he(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(0)} KB`:`${(e/1024/1024).toFixed(1)} MB`}function Le(e){const t=Math.floor(e/60),n=e%60;return`${t}:${String(n).padStart(2,"0")}`}const Ae="bugcatch.watch",zt=[2e3,5e3,15e3,3e4,6e4],wo=5e3;let me=null;function vo(e){me=e||null}const Je=()=>me?`${Ae}:${me}`:Ae;function Me(){return me?`?projectId=${encodeURIComponent(me)}`:""}function V(){try{const e=window.localStorage;return(e==null?void 0:e.getItem(Je()))||(e==null?void 0:e.getItem(Ae))||null}catch{return null}}function Ze(e){var t;if(e)try{(t=window.localStorage)==null||t.setItem(Je(),e)}catch{}}function ce(){var e,t;try{(e=window.localStorage)==null||e.removeItem(Je()),(t=window.localStorage)==null||t.removeItem(Ae)}catch{}qt()}const Be="bugcatch.unread";function xo(e){return[(e==null?void 0:e.bugId)||"report",(e==null?void 0:e.kind)||"status",(e==null?void 0:e.at)||""].join("|")}function ye(){var e;try{const t=(e=window.localStorage)==null?void 0:e.getItem(Be),n=t?JSON.parse(t):[];return Array.isArray(n)?n.filter(o=>o&&typeof o.id=="string"):[]}catch{return[]}}function Re(e){var t,n;try{e.length?(t=window.localStorage)==null||t.setItem(Be,JSON.stringify(e)):(n=window.localStorage)==null||n.removeItem(Be)}catch{}}function ko(e){const t={...e,id:xo(e)},n=ye().filter(o=>o.id!==t.id);return n.push(t),Re(n.slice(-20)),t}function So(e){const t=ye().filter(n=>n.id!==e);return Re(t),t}function $o(e){const t=ye().filter(n=>n.bugId!==e);return Re(t),t}function qt(){return Re([]),[]}function Co(e,t){let n=e,o=n.indexOf(`
|
|
292
304
|
|
|
293
305
|
`);for(;o!==-1;){const a=n.slice(0,o);n=n.slice(o+2);const r=a.split(`
|
|
294
306
|
`).filter(i=>i.startsWith("data:")).map(i=>i.slice(5).trim()).join(`
|
|
295
|
-
`);if(r)try{
|
|
307
|
+
`);if(r)try{t(JSON.parse(r))}catch{}o=n.indexOf(`
|
|
296
308
|
|
|
297
|
-
`)}return n}async function bo({apiBase:t}){const e=P();if(!e)return{reporter:null,reports:[]};const n=await fetch(`${t}/ingest/watch/reports${Fe()}`,{headers:{Authorization:`Bearer ${e}`}});if(n.status===401)return se(),{reporter:null,reports:[]};if(!n.ok)throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);return n.json()}async function mo({apiBase:t,bugId:e}){const n=P();if(!n)return null;const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}${Fe()}`,{headers:{Authorization:`Bearer ${n}`}});if(o.status===401)return se(),null;if(o.status===404)return null;if(!o.ok)throw new Error(`[BugCatch] could not load that report (HTTP ${o.status})`);return o.json()}async function yo({apiBase:t,bugId:e,body:n,attachments:o}){const a=P();if(!a)throw new Error("[BugCatch] nothing filed from this browser yet.");const r=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/messages`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({...n?{body:n}:{},...o!=null&&o.length?{attachments:o}:{}})});if(r.status===401)throw se(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!r.ok){let i="";try{const s=await r.json();i=Array.isArray(s.message)?s.message.join(", "):s.message||""}catch{}throw r.status===429?new Error(ue(i)):new Error(i||`[BugCatch] could not send that (HTTP ${r.status}).`)}return r.json()}async function wo({apiBase:t,apiKey:e,projectId:n}){const o={agent:!1,live:!1};try{const a=await fetch(`${t}/ingest/calls?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!a.ok)return o;const r=await a.json();return r!=null&&r.available?r.kinds&&typeof r.kinds=="object"?{agent:!1,live:!!r.kinds.live}:{agent:!1,live:r.kind==="live"}:o}catch{return o}}async function vo({apiBase:t,apiKey:e,token:n,payload:o,watchToken:a}){const r=await fetch(`${t}/ingest/calls`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e,...n?{"X-BugCatch-Session":n}:{}},body:JSON.stringify(a?{...o,watchToken:a}:o)});if(!r.ok){let i="";try{const c=await r.json();i=Array.isArray(c.message)?c.message.join(", "):c.message||""}catch{}const s=new Error(r.status===429?ue(i):i||`[BugCatch] the call could not be started (HTTP ${r.status}).`);throw s.status=r.status,s}return r.json()}async function Mt({apiBase:t,bugId:e}){const n=P();if(!n)return!1;try{const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)return!1;const a=await o.json();return!!(a!=null&&a.offered)}catch{return!1}}async function xo({apiBase:t,bugId:e}){const n=P();if(!n)throw new Error("[BugCatch] nothing filed from this browser yet.");const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{method:"POST",headers:{Authorization:`Bearer ${n}`}});if(o.status===401)throw se(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!o.ok){let a="";try{const r=await o.json();a=Array.isArray(r.message)?r.message.join(", "):r.message||""}catch{}throw new Error(a||`[BugCatch] the call could not be started (HTTP ${o.status}).`)}return o.json()}async function ko({apiBase:t,bugId:e,callId:n}){const o=P();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/give-up`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}async function So({apiBase:t,bugId:e,callId:n}){const o=P();if(!o)throw new Error("[BugCatch] nothing filed from this browser yet.");const a=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,{method:"POST",headers:{Authorization:`Bearer ${o}`}});if(a.status===401)throw se(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(a.status===409)throw new Error("[BugCatch] that call is no longer ringing.");if(!a.ok){let r="";try{const i=await a.json();r=Array.isArray(i.message)?i.message.join(", "):i.message||""}catch{}throw new Error(r||`[BugCatch] the call could not be answered (HTTP ${a.status}).`)}return a.json()}async function Bt({apiBase:t,bugId:e,callId:n}){const o=P();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/decline`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}function $o({apiBase:t,onUpdate:e}){let n=!0,o=0,a=null;async function r(){const i=P();if(!i)throw new Error("nothing filed from this browser yet");a=new AbortController;const s=await fetch(`${t}/ingest/watch/stream${Fe()}`,{headers:{Authorization:`Bearer ${i}`,Accept:"text/event-stream"},signal:a.signal});if(s.status===401)throw n=!1,se(),new Error("subscription no longer valid");if(!s.ok||!s.body)throw new Error(`stream failed (${s.status})`);const c=Date.now(),l=s.body.getReader(),f=new TextDecoder;let d="";try{for(;;){const{value:u,done:g}=await l.read();if(g)break;d+=f.decode(u,{stream:!0}),d=go(d,y=>{if(y.type!=="ping")try{e(y)}catch{}})}}finally{Date.now()-c>=co&&(o=0)}}return(async()=>{for(;n;){try{await r()}catch(s){if((s==null?void 0:s.name)==="AbortError")return}if(!n)return;const i=Lt[Math.min(o,Lt.length-1)];o+=1,await new Promise(s=>setTimeout(s,i))}})(),()=>{n=!1,a==null||a.abort(),a=null}}const Co={OPEN:"is open",IN_PROGRESS:"is being worked on",RESOLVED:"has been fixed",CLOSED:"has been closed"},To={status:null,severity:"#e8912a",assignment:"#4da3ff",reply:"#35b87f"};function Rt(t){return t!=null&&t.summary?t.summary:`Your report ${Co[t==null?void 0:t.status]||"was updated"}`}function Eo(t){var e;return(t==null?void 0:t.kind)==="reply"&&((e=t.reply)!=null&&e.body)?`${t.reply.author?`${t.reply.author}: `:""}${t.reply.body}`:(t==null?void 0:t.title)||""}function Io(t){const e=Date.parse(t||"");if(!Number.isFinite(e))return"";const n=Math.round((Date.now()-e)/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const o=Math.round(n/60);if(o<24)return`${o}h ago`;const a=Math.round(o/24);return a===1?"yesterday":`${a}d ago`}function Lo(){var t;try{const e=document.querySelector('[data-bugcatch="widget"]'),n=(t=e==null?void 0:e.shadowRoot)==null?void 0:t.querySelector(".dock"),o=(n==null?void 0:n.getBoundingClientRect().height)||0;return o?Math.round(o)+12:0}catch{return 0}}function Ao({accent:t="#4F46E5",position:e="bottom-right",onRead:n=null,onReadAll:o=null,onCall:a=null}={}){const[r,i]=String(e).split("-"),s=r==="top",c=i==="left",l=new Map;let f=null,d=null;function u(){return f!=null&&f.isConnected||(f=document.createElement("div"),f.setAttribute("data-bugcatch","updates"),f.style.cssText=["position:fixed",`${s?"top":"bottom"}:${20+Lo()}px`,`${c?"left":"right"}:20px`,"z-index:2147482998","display:flex","flex-direction:column","gap:10px",`align-items:${c?"flex-start":"flex-end"}`,"width:min(320px,calc(100vw - 40px))","pointer-events:none"].join(";"),document.body.appendChild(f)),f}function g(p){if(!p._bcShown){p.remove();return}p.style.opacity="0",p.style.transform=`translateY(${s?-8:8}px)`,setTimeout(()=>p.remove(),250)}function y(p,h){const b=document.createElement("button");return b.type="button",b.textContent=p,b.style.cssText=["padding:5px 11px",`border:${h?"0":"1px solid rgba(236,238,242,.24)"}`,"border-radius:6px",`background:${h?t:"transparent"}`,`color:${h?"#fff":"#eceef2"}`,"font:600 12px/1.4 inherit","cursor:pointer","white-space:nowrap"].join(";"),b}function m(p){var v;const h=document.createElement("div");h.setAttribute("role","status"),h.style.cssText=["box-sizing:border-box","width:100%","padding:12px 14px","border-radius:10px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)",`border-left:3px solid ${To[p==null?void 0:p.kind]||t}`,"opacity:0",`transform:translateY(${s?-8:8}px)`,"transition:opacity .2s ease,transform .2s ease","pointer-events:auto"].join(";");const b=document.createElement("div");b.style.cssText="font-weight:600;margin-bottom:2px",b.textContent=Rt(p);const T=document.createElement("div");T.style.cssText=(p==null?void 0:p.kind)==="reply"?"color:#a4abba;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden":"color:#a4abba",T.textContent=Eo(p);const C=document.createElement("div");C.style.cssText="display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap";const S=document.createElement("span");S.style.cssText="color:#7b8394;font-size:11px;margin-right:auto",S.textContent=Io(p==null?void 0:p.at);const x=y("Mark as read",!1);if(x.setAttribute("aria-label",`Mark as read: ${Rt(p)}`),x.addEventListener("click",()=>n==null?void 0:n(p.id)),C.append(S,x),(v=p==null?void 0:p.call)!=null&&v.offered&&typeof a=="function"){const k=y("Talk it through",!0);k.addEventListener("click",()=>a(p)),C.insertBefore(k,x)}return h.append(b,T,C),h}function w(p){const h=document.createElement("div");h.style.cssText=["box-sizing:border-box","width:100%","display:flex","align-items:center","gap:8px","padding:8px 12px","border-radius:10px","background:#1b1e26","color:#a4abba",'font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)","pointer-events:auto"].join(";");const b=document.createElement("span");b.style.cssText="margin-right:auto",b.textContent=`${p} more update${p===1?"":"s"}`;const T=y("Mark all as read",!1);return T.style.cssText+=";padding:4px 9px",T.addEventListener("click",()=>o==null?void 0:o()),h.append(b,T),h}return{render(p){const h=Array.isArray(p)?p:[];if(!h.length){for(const k of l.values())g(k);l.clear(),d==null||d.remove(),d=null,f==null||f.remove(),f=null;return}const b=h.slice(-3),T=new Set(b.map(k=>k.id)),C=u();for(const[k,O]of l)T.has(k)||(g(O),l.delete(k));const S=[];for(const k of b){if(l.has(k.id))continue;const O=m(k);l.set(k.id,O),S.push(O)}const x=s?[...b].reverse():b;for(const k of x)C.appendChild(l.get(k.id));const v=h.length-b.length;v>0?(d==null||d.remove(),d=w(v),s?C.appendChild(d):C.insertBefore(d,C.firstChild)):(d==null||d.remove(),d=null),requestAnimationFrame(()=>{for(const k of S)k.isConnected&&(k._bcShown=!0,k.style.opacity="1",k.style.transform="translateY(0)")})},destroy(){l.clear(),d=null,f==null||f.remove(),f=null}}}async function Mo({apiBase:t,apiKey:e,projectId:n,sessionToken:o}){try{const a=await fetch(`${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,{headers:Ye(e,o)});if(!a.ok)return[];const r=await a.json();return Array.isArray(r==null?void 0:r.issues)?r.issues:[]}catch{return[]}}async function Bo({apiBase:t,apiKey:e,projectId:n,q:o,sessionToken:a,signal:r}){try{const i=`${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(o)}`,s=await fetch(i,{headers:Ye(e,a),signal:r});if(!s.ok)return[];const c=await s.json();return Array.isArray(c==null?void 0:c.issues)?c.issues:[]}catch{return[]}}async function Ro({apiBase:t,apiKey:e,projectId:n,bugId:o,reporterEmail:a,reporterName:r,metadata:i,logs:s,sessionToken:c}){const l=P(),f=await fetch(`${t}/ingest/known-issues/${encodeURIComponent(o)}/join`,{method:"POST",headers:Ye(e,c),body:JSON.stringify({projectId:n,reporterEmail:a,reporterName:r,metadata:i,logs:s,...l?{watchToken:l}:{}})});if(!f.ok)throw new Error(await jo(f));const d=await f.json();return d!=null&&d.watchToken&&We(d.watchToken),d}function Ye(t,e){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function jo(t){let e="";try{const n=await t.json();e=Array.isArray(n.message)?n.message.join(", "):n.message||""}catch{}return t.status===429?ue(e):e||`Could not add you to this issue (HTTP ${t.status})`}async function Oo({apiBase:t,bugId:e,...n}){const o=P();if(!o)throw new Error("This browser cannot access that report.");const a=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(n)}),r=await a.json().catch(()=>({}));if(!a.ok)throw new Error(r.message||"Could not record feedback. Please refresh and try again.");return r}const zo="bugcatch.session.",Xe=t=>`${zo}${t}`,Je=new Map;function te(t){var e;if(!t)return null;try{const n=(e=window.localStorage)==null?void 0:e.getItem(Xe(t));if(n){const o=JSON.parse(n);if(o!=null&&o.token)return o}}catch{}return Je.get(t)||null}function Qo(t,e){var o;if(!t||!(e!=null&&e.token))return;const n={token:e.token,email:e.email||null,name:e.name||null};Je.set(t,n);try{(o=window.localStorage)==null||o.setItem(Xe(t),JSON.stringify(n))}catch{}}function Ze(t){var e;if(t){Je.delete(t);try{(e=window.localStorage)==null||e.removeItem(Xe(t))}catch{}}}function Ae({apiKey:t,token:e}){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function jt(t){let e="";try{const n=await t.json();e=Array.isArray(n.message)?n.message.join(", "):n.message||""}catch{}return t.status===429?ue(e):e||`Request failed (HTTP ${t.status})`}async function Ho({apiBase:t,apiKey:e,projectId:n,token:o}){const a={mode:"off",signedIn:null,signedOutReason:null};try{const r=await fetch(`${t}/ingest/login?projectId=${encodeURIComponent(n)}`,{headers:Ae({apiKey:e,token:o})});if(!r.ok)return a;const i=await r.json();return{mode:i.mode==="optional"||i.mode==="required"?i.mode:"off",signedIn:i.signedIn||null,signedOutReason:i.signedOutReason||null}}catch{return a}}async function qo({apiBase:t,apiKey:e,projectId:n,email:o,name:a}){const r=await fetch(`${t}/ingest/login/start`,{method:"POST",headers:Ae({apiKey:e}),body:JSON.stringify({projectId:n,email:o,...a?{name:a}:{}})});if(!r.ok)throw new Error(await jt(r));return r.json()}async function Do({apiBase:t,apiKey:e,projectId:n,email:o,code:a}){const r=await fetch(`${t}/ingest/login`,{method:"POST",headers:Ae({apiKey:e}),body:JSON.stringify({projectId:n,email:o,code:a})});if(!r.ok)throw new Error(await jt(r));const i=await r.json(),s={token:i.sessionToken,email:i.email,name:i.name};return Qo(n,s),s}async function No({apiBase:t,apiKey:e,projectId:n,token:o}){if(Ze(n),!o)return{signedOut:!0};try{await fetch(`${t}/ingest/logout`,{method:"POST",headers:Ae({apiKey:e,token:o}),body:JSON.stringify({projectId:n})})}catch{}return{signedOut:!0}}let Ot=!1;if(typeof window<"u"&&window.addEventListener)for(const t of["pointerdown","keydown","touchstart"])window.addEventListener(t,()=>{Ot=!0},{once:!0,capture:!0,passive:!0});function Uo(){return Ot}const _o=2e4,zt=120,Ge=200;function Qt(t){if(typeof t!="string"||!t.trim()||t.length>400)return null;try{return new RegExp(t.trim(),"gi")}catch{return null}}const Ht=t=>String(t).replace(/\s+/g," ").trim().slice(0,zt);function qt(t,e){const n=t&&t.normalize;if(n==="phone"){const o=e.replace(/\D/g,"");return o.length===10?o:o.length===12&&o.startsWith("91")?o.slice(2):o.length===11&&o.startsWith("0")?o.slice(1):e}return n==="upper"?e.toUpperCase():e}function Dt(t){const e=t.length>1&&t[1]!==void 0?t[1]:t[0];return typeof e!="string"||!e.trim()?null:{value:Ht(e),start:t.index,end:t.index+t[0].length}}function Po(t,e){return((t.slice(e.start,e.valueStart)+t.slice(e.valueEnd,e.end)).match(/[a-z]/gi)||[]).length}const Ko=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi,Nt=/[\w-]/;function Vo(t,e){const n=(t||[]).filter(u=>u&&u.scan!==!1&&u.pattern),o=[],a=[],r=(e||[]).map(u=>typeof u=="string"?u.slice(0,_o):"");r.forEach((u,g)=>{u&&n.forEach((y,m)=>{const w=Qt(y.pattern);if(!w)return;let p,h=0;for(w.lastIndex=0;(p=w.exec(u))!==null&&!(++h>Ge);){if(p[0]===""){w.lastIndex+=1;continue}const b=Dt(p);if(!b)continue;const T=p.length>1&&p[1]!==void 0?p[1]:p[0],C=p.index+Math.max(0,p[0].indexOf(T)),S={block:g,order:m,key:y.key,label:y.label,value:qt(y,b.value),start:b.start,end:b.end,valueStart:C,valueEnd:C+T.length};S.weight=Po(u,S),o.push(S)}})});const i=o.filter(u=>!o.some(g=>g!==u&&g.block===u.block&&g.key!==u.key&&g.valueStart<=u.valueStart&&g.valueEnd>=u.valueEnd&&g.weight>u.weight)),s=new Map;for(const u of i){const g=u.value.toLowerCase();s.has(g)||s.set(g,{value:u.value,keys:new Map});const y=s.get(g);y.keys.has(u.key)||y.keys.set(u.key,{key:u.key,label:u.label,order:u.order})}const c=[],l=[],f=new Map;for(const u of s.values()){const g=[...u.keys.values()].sort((w,p)=>w.order-p.order);if(g.length>1){l.push({value:u.value,kinds:g.map(({key:w,label:p})=>({key:w,label:p}))});continue}const[{key:y,label:m}]=g;f.has(y)||f.set(y,[]),f.get(y).push({key:y,label:m,value:u.value})}for(const u of f.values())if(u.length===1)c.push(u[0]);else for(const g of u)l.push({value:g.value,kinds:[{key:g.key,label:g.label}]});const d=new Set(s.keys());return r.forEach((u,g)=>{if(!u)return;const y=o.filter(h=>h.block===g),m=new RegExp(Ko.source,"gi");let w,p=0;for(;(w=m.exec(u))!==null&&++p<=Ge;){const h=w.index,b=h+w[0].length;if(y.some(k=>h<k.end&&b>k.start))continue;const T=u[h-1]||"",C=u[b]||"";if(Nt.test(T)||Nt.test(C)||T==="/"||T==="@"||C==="@"||T==="."||C==="."&&/\w/.test(u[b+1]||"")||!/\d/.test(w[0]))continue;const S=Ht(w[0]),x=S.toLowerCase();if(d.has(x))continue;const v=(t||[]).filter(k=>k&&Ut(k,S)).map(({key:k,label:O})=>({key:k,label:O}));v.length&&(d.add(x),a.push({value:S,kinds:v}))}}),{found:c,conflicts:l,loose:a}}function Ut(t,e){const n=typeof e=="string"?e.trim():"";if(!n||n.length>zt)return null;const o=Qt(t&&(t.valuePattern||t.pattern));if(!o)return null;let a,r=0;for(o.lastIndex=0;(a=o.exec(n))!==null&&!(++r>Ge);){if(a[0]===""){o.lastIndex+=1;continue}const i=a.index+a[0].length===n.length,s=a.index===0||a.index===1;if(i&&s){const c=Dt(a);if(c)return qt(t,c.value)}}return null}async function Fo({apiBase:t,apiKey:e,projectId:n}){const o={policy:"off",fields:[]};try{const a=await fetch(`${t}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!a.ok)return o;const r=await a.json(),i=r.policy==="optional"||r.policy==="required"?r.policy:"off",s=Array.isArray(r.fields)?r.fields:[];return s.length?{policy:i,fields:s}:o}catch{return o}}const Wo=/Did this answer your question\?/i;async function Yo({apiBase:t,apiKey:e,projectId:n}){try{const o=await fetch(`${t}/ingest/agent-issues?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!o.ok)return[];const a=await o.json();return(Array.isArray(a==null?void 0:a.issues)?a.issues:[]).filter(r=>r&&typeof r.key=="string"&&typeof r.title=="string").map(r=>({key:r.key,title:r.title,hint:typeof r.hint=="string"?r.hint:""}))}catch{return[]}}const Xo=5*6e4,_t="bugcatch:announcements:seen",Jo=40,Zo=["info","success","warning","critical"],Pt=t=>`bugcatch:announcements:${t}`;async function Go({apiBase:t,apiKey:e,projectId:n,fresh:o=!1}){var a;if(!o){const r=ia(n);if(r)return r}try{const r=await fetch(`${t}/ingest/announcements?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}}),i=r.ok?ra((a=await r.json())==null?void 0:a.announcements):[];return sa(n,i),i}catch{return[]}}function ea(t,{on:e=oa(),seen:n=Vt()}={}){return(t||[]).filter(o=>aa(o,e)&&!(o.dismissible&&n.includes(Kt(o))))}function ta(t){if(!(!(t!=null&&t.id)||!t.dismissible))try{const e=Kt(t),n=[...Vt().filter(o=>o!==e),e];localStorage.setItem(_t,JSON.stringify(n.slice(-Jo)))}catch{}}function na(t){return typeof t!="string"||!t||t.startsWith("//")?null:t.startsWith("/")||/^(https?:\/\/|mailto:)./i.test(t)?t:null}function oa(t=new Date){const e=n=>String(n).padStart(2,"0");return`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}`}function aa(t,e){return!(t.startsOn&&e<t.startsOn||t.endsOn&&e>t.endsOn)}function Kt(t){return`${t.id}#${t.revision||0}`}function ra(t){return(Array.isArray(t)?t:[]).filter(e=>e&&typeof e.id=="string"&&typeof e.title=="string"&&e.title.trim()).map(e=>{const n=e.placement==="launcher"?"launcher":"panel",o=na(e.ctaHref);return{id:e.id,revision:Number.isInteger(e.revision)?e.revision:0,title:e.title,body:typeof e.body=="string"?e.body:"",tone:Zo.includes(e.tone)?e.tone:"info",ctaLabel:o&&typeof e.ctaLabel=="string"?e.ctaLabel:"",ctaHref:o&&typeof e.ctaLabel=="string"?o:"",placement:n,dismissible:n==="launcher"||e.dismissible!==!1,startsOn:typeof e.startsOn=="string"?e.startsOn:"",endsOn:typeof e.endsOn=="string"?e.endsOn:""}})}function Vt(){try{const t=JSON.parse(localStorage.getItem(_t)||"[]");return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}catch{return[]}}function ia(t){try{const e=JSON.parse(localStorage.getItem(Pt(t))||"null");if(!e||!Array.isArray(e.list)||typeof e.at!="number")return null;const n=Date.now()-e.at;return n>=0&&n<Xo?e.list:null}catch{return null}}function sa(t,e){try{localStorage.setItem(Pt(t),JSON.stringify({at:Date.now(),list:e}))}catch{}}const Me=120,ca=500,Be=30,la=1e3,et={loanId:["loanId","loanNumber"],applicationId:["applicationId"],customerNumber:["customerNumber","customerId"]},da=/[\u0000-\u001f\u007f]/;function ua(t){if(typeof t=="number")return Number.isFinite(t)?String(t):null;if(typeof t!="string")return null;const e=t.trim();return!e||e.length>Me||da.test(e)?null:e}function J(t){return t===null?"null":Array.isArray(t)?"an array":typeof t=="object"?"an object":`a ${typeof t}`}function tt(t,e,n,o,a){for(const r of n){if(!(r in t)||t[r]===void 0||t[r]===null||t[r]==="")continue;const i=ua(t[r]);if(i)return i;const s=t[r];a(typeof s=="string"&&s.trim().length>Me?`${o}.${r} is longer than ${Me} characters and was dropped — pass the identifier itself, not a sentence or a URL.`:`${o}.${r} should be a string or number, got ${J(s)} — it was dropped.`)}return null}function Ft(t){if(t===null||typeof t=="boolean")return{ok:!0,value:t};if(typeof t=="number")return Number.isFinite(t)?{ok:!0,value:t}:{ok:!1};if(typeof t=="string")return{ok:!0,value:t.slice(0,ca)};if(typeof t=="object")try{const e=JSON.stringify(t);if(e&&e.length<=la)return{ok:!0,value:JSON.parse(e)}}catch{}return{ok:!1}}const Wt=["email","name","phone"],pa=new Set(["id","userId",...Wt,...Object.values(et).flat()]);function Yt(t,e=()=>{}){if(t==null)return null;if(typeof t!="object"||Array.isArray(t))return e(`identify() takes an object like { id, email, name } or null, got ${J(t)} — ignored.`),null;const n={};try{const o=tt(t,"id",["id","userId"],"identify()",e);o&&(n.id=o);for(const r of Wt){const i=t[r];if(i==null||i==="")continue;if(r==="phone"&&typeof i=="number"&&Number.isFinite(i)){n.phone=String(i);continue}if(typeof i!="string"){e(`identify().${r} should be a string, got ${J(i)} — it was dropped.`);continue}const s=i.trim().slice(0,r==="name"?200:Me);s&&(r==="email"&&!s.includes("@")&&e(`identify().email "${s}" does not look like an email address — reports cannot be threaded or followed up without one.`),n[r]=s)}for(const[r,i]of Object.entries(et)){const s=tt(t,r,i,"identify()",e);s&&(n[r]=s)}let a=0;for(const[r,i]of Object.entries(t)){if(pa.has(r)||i===void 0||typeof i=="function")continue;if(a>=Be){e(`identify() was given more than ${Be} extra fields; the rest were dropped.`);break}const s=Ft(i);if(!s.ok){e(`identify().${r} could not be sent (${J(i)} too large or not serialisable) — dropped.`);continue}n[r]=s.value,a+=1}}catch{}return!n.id&&!n.email&&e("identify() was called without an id or email — reports will not be attributed to anyone, and nothing can be looked up by user."),n}function Xt(t,e,n=()=>{}){if(e===null)return{};const o={...t||{}};if(e===void 0)return o;if(typeof e!="object"||Array.isArray(e))return n(`setContext() takes an object like { loanId, screen } or null, got ${J(e)} — ignored.`),o;try{const a=new Map;for(const[r,i]of Object.entries(et))for(const s of i)a.set(s,r);for(const[r,i]of Object.entries(e)){const s=a.get(r);if(i==null){delete o[s||r];continue}if(s){const l=tt({[r]:i},s,[r],"setContext()",n);l?o[s]=l:delete o[s];continue}if(typeof i=="function")continue;if(!(r in o)&&Object.keys(o).length>=Be){n(`setContext() holds at most ${Be} keys; "${r}" was dropped.`);continue}const c=Ft(i);if(!c.ok){n(`setContext().${r} could not be sent (${J(i)} too large or not serialisable) — dropped.`);continue}o[r]=c.value}}catch{}return o}const Jt=["apiBase","apiKey","projectId","consoleLimit","networkLimit","captureConsole","captureNetwork","captureErrors","widget","widgetPosition","theme","accent","attachments","maxAttachments","maxAttachmentBytes","maxRecordingMs","beforeSend","user","context","updates","updateToast","onUpdate","voice","onCallState","onIncomingCall","onReportSubmitted","onAssistantPhase","onError","debug","drafts","knownIssues","agentIssues","release","environment","buildId","chunkBase","announcements"],ha=["beforeSend","onUpdate","onCallState","onIncomingCall","onReportSubmitted","onAssistantPhase","onError"];function fa(t){const e=t.toLowerCase().replace(/[-_]/g,"");return Jt.find(n=>n.toLowerCase()===e)||null}const Zt=/^(your[_-]|<|xxx|todo|changeme)/i,ga=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function ba(t,{pageHost:e=""}={}){const n=[],o=[];if(!t||typeof t!="object")return n.push("init() takes an options object: BugCatch.init({ apiBase, apiKey, projectId })."),{errors:n,warnings:o};const{apiKey:a,projectId:r,apiBase:i}=t;a?typeof a!="string"?n.push(`apiKey must be a string, got ${J(a)}.`):Zt.test(a)?n.push(`apiKey is still the placeholder "${a}" — paste the key you saved when you created it.`):ga.test(a)?o.push("apiKey looks like a project id — did you swap apiKey and projectId?"):a.startsWith("bc_")||o.push('apiKey does not look like a BugCatch key (they start with "bc_live_") — reports will be refused with HTTP 401.'):n.push("apiKey is required — create one under Workspace Settings → API Keys."),r?typeof r!="string"?n.push(`projectId must be a string, got ${J(r)}.`):Zt.test(r)?n.push(`projectId is still the placeholder "${r}".`):r.startsWith("bc_")?o.push("projectId looks like an API key — did you swap apiKey and projectId?"):/\s/.test(r)&&o.push("projectId contains whitespace — check it was copied cleanly."):n.push("projectId is required — copy it from Project Settings → Web SDK."),i==null?!e||/^(localhost|127\.|0\.0\.0\.0|\[::1\])/.test(e)||o.push("apiBase is not set, so reports go to http://localhost:3000 — set apiBase to your BugCatch API URL."):(typeof i!="string"||!/^https?:\/\//.test(i))&&o.push(`apiBase should be an absolute http(s) URL, got ${JSON.stringify(i)}.`);for(const s of Object.keys(t)){if(Jt.includes(s))continue;const c=fa(s);o.push(c?`unknown option "${s}" — did you mean "${c}"?`:`unknown option "${s}" is ignored.`)}for(const s of ha){const c=t[s];c!=null&&typeof c!="function"&&o.push(`${s} should be a function, got ${J(c)} — it will not be called.`)}return{errors:n,warnings:o}}function ma(t){return typeof t=="string"?t.replace(/\/+$/,""):t}const me={name:"@sphoro/bugcatch-web-sdk",version:"0.18.0"},ye={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:"#4F46E5",announcements:!0,attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null,onReportSubmitted:null,onAssistantPhase:null,onError:null,context:null,chunkBase:null,debug:!1};function ya(t){const e=P();return e?{...t,watchToken:e}:t}class Gt{constructor(){kn(this,B);this.config={...ye},this.started=!1,this.teardown=[],this.consoleBuffer=ke(ye.consoleLimit),this.networkBuffer=ke(ye.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map,this.context={},this.warned=new Set,this.phases=new Map}warn(e){this.warned.has(e)||(this.warned.add(e),console.warn(`[BugCatch] ${e}`))}debugLog(...e){this.config.debug&&console.info("[BugCatch]",...e)}init(e={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;const{errors:n,warnings:o}=ba(e,{pageHost:typeof location<"u"?location.hostname:""});if(n.length)throw new Error(`[BugCatch] ${n[0]}`);for(const r of o)this.warn(r);const a=this.config.user;return this.config={...ye,...e,apiBase:ma(e.apiBase??ye.apiBase)},this.config.user=e.user!==void 0?Yt(e.user,r=>this.warn(r.replace("identify()","init({ user })"))):a||null,e.context&&this.setContext(e.context),this.consoleBuffer=ke(this.config.consoleLimit),this.networkBuffer=ke(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(zn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(Qn(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Hn(this.consoleBuffer)),lo(this.config.projectId),this.config.widget&&this.teardown.push(Wn(this)),this.config.updates&&P()&&(this.startWatching(),queueMicrotask(()=>H(this,B,oe).call(this))),this.started=!0,H(this,B,Sn).call(this),this.debugLog("initialised",{version:me.version,apiBase:this.config.apiBase,projectId:this.config.projectId,user:this.config.user,context:this.context}),this}startWatching(){if(this.stopWatching)return this;this.stopWatching=$o({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){H(this,B,En).call(this,n);return}if(n!=null&&n.callWithdrawn){H(this,B,_e).call(this,n.callWithdrawn.callId);return}const o=po(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),H(this,B,oe).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>H(this,B,_e).call(this));const e=n=>{(n.key===Ie||n.key===null)&&H(this,B,oe).call(this)};return window.addEventListener("storage",e),this.teardown.push(()=>window.removeEventListener("storage",e)),this}on(e,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(e)||new Set;return o.add(n),this.listeners.set(e,o),()=>this.off(e,n)}off(e,n){var o;return(o=this.listeners.get(e))==null||o.delete(n),this}emit(e,n){for(const o of this.listeners.get(e)||[])try{o(n)}catch(a){console.error(`[BugCatch] a '${e}' listener threw:`,a)}}unreadUpdates(){return be()}markUpdateRead(e){return ho(e),H(this,B,oe).call(this),this}markReportRead(e){return fo(e),H(this,B,oe).call(this),this}markUpdatesRead(){return At(),H(this,B,oe).call(this),this}async verifyFix(e,{result:n,resolvedAt:o,note:a}){const r=n==="STILL_HAPPENING"?await H(this,B,Ue).call(this,{}):{};return Oo({apiBase:this.config.apiBase,bugId:e,result:n,resolvedAt:o,note:a,metadata:r.metadata,logs:r.logs})}async myReport(e){const n=await mo({apiBase:this.config.apiBase,bugId:e});return H(this,B,$n).call(this,e,n==null?void 0:n.assistant),n}replyToReport(e,{body:n,attachments:o}={}){return yo({apiBase:this.config.apiBase,bugId:e,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const e={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?e:this.kinds!==void 0?this.kinds:(this.kinds=await wo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(e){return this.config.voice?Mt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}async startCall(e){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await H(this,B,Tn).call(this,e)}finally{this.callStarting=!1}}startLiveCall(e){return this.startCall(e)}canCallTeam(e){return this.config.voice?Mt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}endCall(){var e;return(e=this.call)==null||e.hangUp(),this.call=null,this}myReports(){return bo({apiBase:this.config.apiBase})}hasReports(){return!!P()}forgetReports(){var e;return(e=this.stopWatching)==null||e.call(this),this.stopWatching=null,this.endCall(),se(),H(this,B,oe).call(this),this}identify(e){const n=Yt(e,o=>this.warn(o));return e!=null&&!n?this:(this.config.user=n,this.debugLog("identify",n),this)}setContext(e){return this.context=Xt(this.context,e,n=>this.warn(n)),this.debugLog("context",this.context),this}getContext(){return{...this.context}}open(){return this.started?this.widgetControls?(this.widgetControls.open(),this):(this.warn("open() needs the built-in widget; it was turned off with widget: false."),this):(this.warn("open() was called before init() — nothing to open yet."),this)}close(){var e;return(e=this.widgetControls)==null||e.close(),this}isOpen(){var e;return!!((e=this.widgetControls)!=null&&e.isOpen())}async uploadAttachment(e,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return io({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:e,mime:n||(e==null?void 0:e.type),onProgress:o})}async report({title:e,description:n="",priority:o="MEDIUM",metadata:a={},attachments:r=[],references:i=[],context:s=null,issue:c=null}={}){var w,p,h,b,T,C,S,x;if(!this.started)throw new Error("[BugCatch] call init() first.");if(typeof e!="string"||!e.trim())throw new Error("[BugCatch] a title is required.");["LOW","MEDIUM","HIGH","CRITICAL"].includes(String(o).toUpperCase())||(this.warn(`priority "${o}" is not one of LOW, MEDIUM, HIGH, CRITICAL — sent as MEDIUM.`),o="MEDIUM");const l=(r||[]).filter(v=>(v==null?void 0:v.storageKey)&&Ce(v.mime,$e)).map(v=>({type:v.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:v.storageKey,mime:Ce(v.mime,$e)})),f=(Array.isArray(i)?i:[]).filter(v=>v&&typeof v.key=="string"&&v.key&&(typeof v.value=="string"||typeof v.value=="number")).map(v=>({key:v.key.slice(0,64),value:String(v.value).trim().slice(0,120)})).filter(v=>v.value);Array.isArray(i)&&f.length<i.length&&this.warn("report({ references }) takes [{ key, value }] with string values; malformed entries were dropped.");let d=await H(this,B,Ue).call(this,{title:e.trim(),description:typeof n=="string"?n:String(n??""),priority:String(o).toUpperCase(),metadata:a,media:l,references:f,context:s,issue:typeof c=="string"&&c?c.slice(0,32):null});const u=H(this,B,ct).call(this,d);if(u===!1)return{cancelled:!0};d=u,this.debugLog("sending report",{title:d.title,user:(w=d.metadata)==null?void 0:w.user,context:(p=d.metadata)==null?void 0:p.context,references:d.references,console:(T=(b=(h=d.logs)==null?void 0:h.console)==null?void 0:b.entries)==null?void 0:T.length,network:(x=(S=(C=d.logs)==null?void 0:C.network)==null?void 0:S.entries)==null?void 0:x.length});const g=te(this.config.projectId);let y;try{y=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...g!=null&&g.token?{"X-BugCatch-Session":g.token}:{}},body:JSON.stringify(ya(d))})}catch(v){const k=new Error(`[BugCatch] could not reach ${this.config.apiBase} — check apiBase, and that this site's origin is allowed by the API.`);throw k.cause=v,H(this,B,Ne).call(this,"report",k),k}if(y.status===401&&g&&Ze(this.config.projectId),!y.ok){let v="";try{const O=await y.json();v=Array.isArray(O.message)?O.message.join(", "):O.message||""}catch{}y.status===401&&!g&&(v||(v="the apiKey was not accepted")),y.status===403&&(v||(v="the apiKey is not allowed to report to this projectId"));const k=y.status===429?new Error(`[BugCatch] ${ue(v)}`):new Error(`[BugCatch] report failed (HTTP ${y.status})${v?": "+v:""}`);throw k.status=y.status,H(this,B,Ne).call(this,"report",k),k}const m=await y.json();return H(this,B,st).call(this,m,{title:d.title??e.trim(),via:"form"}),m.watchToken&&(We(m.watchToken),this.config.updates&&this.startWatching()),m}loginState(){var e;return Ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(e=te(this.config.projectId))==null?void 0:e.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=Fo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}agentIssues(){return this.agentIssueList?this.agentIssueList:(this.agentIssueList=Yo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.agentIssueList)}async announcements(){const e=await Go({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId});return ea(e)}dismissAnnouncement(e){ta(e)}signedInAs(){const e=te(this.config.projectId);return e?{email:e.email,name:e.name}:null}signIn(e,{name:n}={}){var o;return qo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(e,n){var a;const o=await Do({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,code:n});return(a=this.config.user)!=null&&a.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const e=te(this.config.projectId),n=await No({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:e==null?void 0:e.token});return e!=null&&e.email&&((o=this.config.user)==null?void 0:o.email)===e.email&&(this.config.user=null),this.emit("signout",{email:(e==null?void 0:e.email)||null}),n}knownIssues(){var e;return Mo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(e=te(this.config.projectId))==null?void 0:e.token})}matchKnownIssues(e,{signal:n}={}){var o;return Bo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:e||"",sessionToken:(o=te(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(e,{email:n,name:o}={}){var i,s;const a=te(this.config.projectId),r=await ft();return Ro({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:e,reporterEmail:n||((i=this.config.user)==null?void 0:i.email),reporterName:o||((s=this.config.user)==null?void 0:s.name),metadata:{...r,user:this.config.user||void 0,...Object.keys(this.context).length?{context:this.context}:{},sdk:me},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:a==null?void 0:a.token})}snapshot(){return{user:this.config.user||null,context:{...this.context},console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:gt()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(e=>{try{e()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,De=function(e,n){const o=this.config[e];if(typeof o=="function")try{o(n)}catch(a){console.error(`[BugCatch] your ${e} callback threw:`,a)}},Sn=function(){if(typeof window>"u"||typeof fetch!="function")return;const e=`bugcatch:hello:${this.config.projectId}`,n=new Date().toISOString().slice(0,10);try{if(window.localStorage.getItem(e)===n)return}catch{}const o=setTimeout(()=>{try{window.localStorage.setItem(e,n)}catch{}fetch(`${this.config.apiBase}/ingest/hello`,{method:"POST",keepalive:!0,headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey},body:JSON.stringify({projectId:this.config.projectId,version:me.version,identify:!!this.config.user,context:!!(this.context&&Object.keys(this.context).length),widget:!!this.config.widget,environment:this.config.environment||null,release:this.config.release||null})}).catch(()=>{})},5e3);this.teardown.push(()=>clearTimeout(o))},oe=function(){const e=be();if(this.emit("unread",{count:e.length,updates:e}),!!this.config.updateToast){if(!this.notifier){if(!e.length)return;this.notifier=Ao({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(e)}},$n=function(e,n){const o=n==null?void 0:n.phase;if(!e||typeof o!="string"||this.phases.get(e)===o)return;this.phases.set(e,o);const a={bugId:e,phase:o,title:n.title??null,detail:n.detail??null};this.debugLog("assistant",a),H(this,B,De).call(this,"onAssistantPhase",a),this.emit("assistant",a)},st=function(e,{title:n,via:o}){if(!(e!=null&&e.id))return;const a={bugId:e.id,title:n??null,via:o,result:e};this.debugLog("report accepted",a),H(this,B,De).call(this,"onReportSubmitted",a),this.emit("report",a)},Ne=function(e,n){H(this,B,De).call(this,"onError",{action:e,error:n}),this.emit("error",{action:e,error:n})},Ue=async function({title:e,description:n="",priority:o="MEDIUM",metadata:a={},media:r=[],references:i=[],context:s=null,issue:c=null}){var f,d;const l=s?Xt(this.context,s,u=>this.warn(u.replace("setContext()","report({ context })"))):this.context;return{projectId:this.config.projectId,...e?{title:e}:{},description:n,priority:o,url:window.location.href,reporterEmail:(f=this.config.user)==null?void 0:f.email,reporterName:(d=this.config.user)==null?void 0:d.name,metadata:{...await ft(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...a,user:this.config.user||void 0,...Object.keys(l).length?{context:l}:{},sdk:me},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...i.length?{references:i}:{},...c?{issue:c}:{}}},ct=function(e){if(typeof this.config.beforeSend!="function")return e;let n;try{n=this.config.beforeSend(e)}catch(o){return this.warn(`beforeSend threw, so nothing was sent: ${(o==null?void 0:o.message)||o}`),!1}return n===!1?!1:n&&typeof n=="object"?n:e},Cn=async function(){const e=te(this.config.projectId),n=H(this,B,ct).call(this,await H(this,B,Ue).call(this,{}));if(n===!1)return this.debugLog("call cancelled by beforeSend"),{cancelled:!0};let o;try{o=await vo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:e==null?void 0:e.token,payload:n,watchToken:P()})}catch(a){throw a.status===401&&e&&Ze(this.config.projectId),H(this,B,Ne).call(this,"call",a),a}return H(this,B,st).call(this,o,{title:null,via:"call"}),o.watchToken&&(We(o.watchToken),this.config.updates&&this.startWatching()),o},Tn=async function(e){const{joinLiveCall:n,liveCallSupported:o,openMicrophone:a}=await Se(this.config.chunkBase);if(!o())throw new Error("[BugCatch] this browser cannot make live calls.");const r=await a();let i,s=null;try{if(e)i=await xo({apiBase:this.config.apiBase,bugId:e});else if(s=await H(this,B,Cn).call(this),e=s.id,i=s.live_call,!(i!=null&&i.realtime_url)){const l=new Error(`[BugCatch] the report was filed, but the team could not be rung${s.call_error?`: ${s.call_error}`:"."}`);throw l.filed=s,l.reason=s.call_error||null,l}}catch(l){for(const f of r.getTracks())f.stop();throw l}const c=await n({realtimeUrl:i.realtime_url,stream:r,ringsUntil:i.rings_until,onState:(l,f)=>{(l==="ended"||l==="failed"||l==="missed")&&(this.call=null),l==="missed"&&ko({apiBase:this.config.apiBase,bugId:e,callId:i.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(l,{bugId:e,live:!0,...f}),this.emit("call",{bugId:e,live:!0,state:l,...f})}});return this.call=c,Object.assign(c,{bugId:e,callId:i.call_id,live:!0,filed:s,recorded:!!i.recorded})},En=function(e){var a;const n=e.incomingCall;if(!this.config.voice||((a=this.ringing)==null?void 0:a.callId)===n.callId||this.call||this.callStarting)return;H(this,B,_e).call(this);const o={callId:n.callId,dismiss:()=>{}};this.ringing=o,Se(this.config.chunkBase).then(({liveCallSupported:r,showIncomingCall:i})=>{if(this.ringing!==o||(this.ringing=null,!r())||this.call||this.callStarting)return;const s=i({call:n,accent:this.config.accent,position:this.config.widgetPosition,touched:Uo,onAnswer:()=>{H(this,B,In).call(this,e.bugId,n)},onDecline:()=>{this.ringing=null,Bt({apiBase:this.config.apiBase,bugId:e.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:s},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:e.bugId,...n})}catch{}this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"ringing"})},()=>{this.ringing===o&&(this.ringing=null)})},_e=function(e){if(this.ringing&&!(e&&this.ringing.callId!==e)){try{this.ringing.dismiss()}catch{}this.ringing=null}},In=async function(e,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o,a;try{const i=await Se(this.config.chunkBase);a=i.joinLiveCall,o=await i.openMicrophone()}catch(i){this.callStarting=!1,Bt({apiBase:this.config.apiBase,bugId:e,callId:n.callId}),this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:i});return}let r;try{r=await So({apiBase:this.config.apiBase,bugId:e,callId:n.callId})}catch(i){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"missed",error:i});return}try{const i=await a({realtimeUrl:r.realtime_url,stream:o,onState:(s,c)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,incoming:!0,...c}),this.emit("call",{bugId:e,live:!0,incoming:!0,state:s,...c})}});this.call=i,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"answered"})}catch(i){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:i})}finally{this.callStarting=!1}};const nt=new Gt;nt.Client=Gt,nt.version=me.version;const wa='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',va='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',en='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',tn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',nn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',xa='<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',ka='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',Re='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',Sa='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',we='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.5c.5 4.6 2.9 7 7.5 7.5v.1c-4.6.5-7 2.9-7.5 7.5h-.1c-.5-4.6-2.9-7-7.5-7.5V10c4.6-.5 7-2.9 7.5-7.5z"/><path d="M18.6 15.2c.2 1.9 1.2 2.9 3.1 3.1v.1c-1.9.2-2.9 1.2-3.1 3.1h-.1c-.2-1.9-1.2-2.9-3.1-3.1v-.1c1.9-.2 2.9-1.2 3.1-3.1z" opacity=".7"/></svg>',$a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 6l6 6-6 6"/></svg>',Ca='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5l2.6-7.2A1.5 1.5 0 0 1 7.5 5.3h9a1.5 1.5 0 0 1 1.4 1L20.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 18z"/><path d="M3.5 13.5h4.8l1.2 2.2h5l1.2-2.2h4.8"/></svg>',Ta='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',Ea=`
|
|
309
|
+
`)}return n}async function To({apiBase:e}){const t=V();if(!t)return{reporter:null,reports:[]};const n=await fetch(`${e}/ingest/watch/reports${Me()}`,{headers:{Authorization:`Bearer ${t}`}});if(n.status===401)return ce(),{reporter:null,reports:[]};if(!n.ok)throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);return n.json()}async function Eo({apiBase:e,bugId:t}){const n=V();if(!n)return null;const o=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}${Me()}`,{headers:{Authorization:`Bearer ${n}`}});if(o.status===401)return ce(),null;if(o.status===404)return null;if(!o.ok)throw new Error(`[BugCatch] could not load that report (HTTP ${o.status})`);return o.json()}async function Io({apiBase:e,bugId:t,body:n,attachments:o}){const a=V();if(!a)throw new Error("[BugCatch] nothing filed from this browser yet.");const r=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/messages`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({...n?{body:n}:{},...o!=null&&o.length?{attachments:o}:{}})});if(r.status===401)throw ce(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!r.ok){let i="";try{const s=await r.json();i=Array.isArray(s.message)?s.message.join(", "):s.message||""}catch{}throw r.status===429?new Error(pe(i)):new Error(i||`[BugCatch] could not send that (HTTP ${r.status}).`)}return r.json()}async function Lo({apiBase:e,apiKey:t,projectId:n}){const o={agent:!1,live:!1};try{const a=await fetch(`${e}/ingest/calls?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":t}});if(!a.ok)return o;const r=await a.json();return r!=null&&r.available?r.kinds&&typeof r.kinds=="object"?{agent:!1,live:!!r.kinds.live}:{agent:!1,live:r.kind==="live"}:o}catch{return o}}async function Ao({apiBase:e,apiKey:t,token:n,payload:o,watchToken:a}){const r=await fetch(`${e}/ingest/calls`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":t,...n?{"X-BugCatch-Session":n}:{}},body:JSON.stringify(a?{...o,watchToken:a}:o)});if(!r.ok){let i="";try{const d=await r.json();i=Array.isArray(d.message)?d.message.join(", "):d.message||""}catch{}const s=new Error(r.status===429?pe(i):i||`[BugCatch] the call could not be started (HTTP ${r.status}).`);throw s.status=r.status,s}return r.json()}async function Dt({apiBase:e,bugId:t}){const n=V();if(!n)return!1;try{const o=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/live-call`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)return!1;const a=await o.json();return!!(a!=null&&a.offered)}catch{return!1}}async function Mo({apiBase:e,bugId:t}){const n=V();if(!n)throw new Error("[BugCatch] nothing filed from this browser yet.");const o=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/live-call`,{method:"POST",headers:{Authorization:`Bearer ${n}`}});if(o.status===401)throw ce(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!o.ok){let a="";try{const r=await o.json();a=Array.isArray(r.message)?r.message.join(", "):r.message||""}catch{}throw new Error(a||`[BugCatch] the call could not be started (HTTP ${o.status}).`)}return o.json()}async function Bo({apiBase:e,bugId:t,callId:n}){const o=V();if(o)try{await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/live-call/${encodeURIComponent(n)}/give-up`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}async function Ro({apiBase:e,bugId:t,callId:n}){const o=V();if(!o)throw new Error("[BugCatch] nothing filed from this browser yet.");const a=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/live-call/${encodeURIComponent(n)}/answer`,{method:"POST",headers:{Authorization:`Bearer ${o}`}});if(a.status===401)throw ce(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(a.status===409)throw new Error("[BugCatch] that call is no longer ringing.");if(!a.ok){let r="";try{const i=await a.json();r=Array.isArray(i.message)?i.message.join(", "):i.message||""}catch{}throw new Error(r||`[BugCatch] the call could not be answered (HTTP ${a.status}).`)}return a.json()}async function Qt({apiBase:e,bugId:t,callId:n}){const o=V();if(o)try{await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/live-call/${encodeURIComponent(n)}/decline`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}function jo({apiBase:e,onUpdate:t}){let n=!0,o=0,a=null;async function r(){const i=V();if(!i)throw new Error("nothing filed from this browser yet");a=new AbortController;const s=await fetch(`${e}/ingest/watch/stream${Me()}`,{headers:{Authorization:`Bearer ${i}`,Accept:"text/event-stream"},signal:a.signal});if(s.status===401)throw n=!1,ce(),new Error("subscription no longer valid");if(!s.ok||!s.body)throw new Error(`stream failed (${s.status})`);const d=Date.now(),c=s.body.getReader(),p=new TextDecoder;let f="";try{for(;;){const{value:u,done:h}=await c.read();if(h)break;f+=p.decode(u,{stream:!0}),f=Co(f,m=>{if(m.type!=="ping")try{t(m)}catch{}})}}finally{Date.now()-d>=wo&&(o=0)}}return(async()=>{for(;n;){try{await r()}catch(s){if((s==null?void 0:s.name)==="AbortError")return}if(!n)return;const i=zt[Math.min(o,zt.length-1)];o+=1,await new Promise(s=>setTimeout(s,i))}})(),()=>{n=!1,a==null||a.abort(),a=null}}const Oo={OPEN:"is open",IN_PROGRESS:"is being worked on",RESOLVED:"has been fixed",CLOSED:"has been closed"},zo={status:null,severity:"#f2a54a",assignment:"#79a8ff",reply:"#4fd19a"},X={bg:"#111113",fg:"#f3f2ef",muted:"#b3b0aa",faint:"#8f8c86",ring:"rgba(255,255,255,.09)",brand:"#a59cff"};function Ht(e){return e!=null&&e.summary?e.summary:`Your report ${Oo[e==null?void 0:e.status]||"was updated"}`}function qo(e){var t;return(e==null?void 0:e.kind)==="reply"&&((t=e.reply)!=null&&t.body)?`${e.reply.author?`${e.reply.author}: `:""}${e.reply.body}`:(e==null?void 0:e.title)||""}function Do(e){const t=Date.parse(e||"");if(!Number.isFinite(t))return"";const n=Math.round((Date.now()-t)/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const o=Math.round(n/60);if(o<24)return`${o}h ago`;const a=Math.round(o/24);return a===1?"yesterday":`${a}d ago`}function Qo(){var e;try{const t=document.querySelector('[data-bugcatch="widget"]'),n=(e=t==null?void 0:t.shadowRoot)==null?void 0:e.querySelector(".dock"),o=(n==null?void 0:n.getBoundingClientRect().height)||0;return o?Math.round(o)+12:0}catch{return 0}}function Ho({accent:e=null,position:t="bottom-right",onRead:n=null,onReadAll:o=null,onCall:a=null}={}){const[r,i]=String(t).split("-"),s=r==="top",d=i==="left",c=new Map;let p=null,f=null;function u(){return p!=null&&p.isConnected||(p=document.createElement("div"),p.setAttribute("data-bugcatch","updates"),p.style.cssText=["position:fixed",`${s?"top":"bottom"}:${20+Qo()}px`,`${d?"left":"right"}:20px`,"z-index:2147482998","display:flex","flex-direction:column","gap:10px",`align-items:${d?"flex-start":"flex-end"}`,"width:min(320px,calc(100vw - 40px))","pointer-events:none"].join(";"),document.body.appendChild(p)),p}function h(l){if(!l._bcShown){l.remove();return}l.style.opacity="0",l.style.transform=`translateY(${s?-8:8}px)`,setTimeout(()=>l.remove(),250)}const m=e||Te,C=e?Xe(e):Ye;function w(l,S){const y=document.createElement("button");return y.type="button",y.textContent=l,y.style.cssText=["padding:6px 12px","border:0",`box-shadow:${S?"none":`inset 0 0 0 1px ${X.ring}`}`,"border-radius:999px",`background:${S?m:"rgba(255,255,255,.06)"}`,`color:${S?C:X.fg}`,"font:560 12px/1.4 inherit","cursor:pointer","white-space:nowrap"].join(";"),y}function g(l){var _;const S=document.createElement("div");S.setAttribute("role","status"),S.style.cssText=["box-sizing:border-box","width:100%","padding:13px 14px","border-radius:14px",`background:${X.bg}`,`color:${X.fg}`,'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',`box-shadow:0 0 0 1px ${X.ring},0 20px 44px -12px rgba(0,0,0,.55),0 4px 12px rgba(0,0,0,.25)`,"opacity:0",`transform:translateY(${s?-8:8}px)`,"transition:opacity .2s ease,transform .2s ease","pointer-events:auto"].join(";");const y=document.createElement("div");y.style.cssText="display:flex;align-items:baseline;gap:8px;font-weight:600;margin-bottom:2px";const x=document.createElement("span");x.setAttribute("aria-hidden","true"),x.style.cssText=`flex:none;width:7px;height:7px;border-radius:50%;transform:translateY(-1px);background:${zo[l==null?void 0:l.kind]||e||X.brand}`;const v=document.createElement("span");v.textContent=Ht(l),y.append(x,v);const k=document.createElement("div");k.style.cssText=(l==null?void 0:l.kind)==="reply"?`color:${X.muted};padding-left:15px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden`:`color:${X.muted};padding-left:15px`,k.textContent=qo(l);const T=document.createElement("div");T.style.cssText="display:flex;align-items:center;gap:8px;margin-top:10px;padding-left:15px;flex-wrap:wrap";const j=document.createElement("span");j.style.cssText=`color:${X.faint};font-size:11px;margin-right:auto`,j.textContent=Do(l==null?void 0:l.at);const O=w("Mark as read",!1);if(O.setAttribute("aria-label",`Mark as read: ${Ht(l)}`),O.addEventListener("click",()=>n==null?void 0:n(l.id)),T.append(j,O),(_=l==null?void 0:l.call)!=null&&_.offered&&typeof a=="function"){const Y=w("Talk it through",!0);Y.addEventListener("click",()=>a(l)),T.insertBefore(Y,O)}return S.append(y,k,T),S}function b(l){const S=document.createElement("div");S.style.cssText=["box-sizing:border-box","width:100%","display:flex","align-items:center","gap:8px","padding:8px 10px 8px 14px","border-radius:999px",`background:${X.bg}`,`color:${X.muted}`,'font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',`box-shadow:0 0 0 1px ${X.ring},0 12px 30px -10px rgba(0,0,0,.5)`,"pointer-events:auto"].join(";");const y=document.createElement("span");y.style.cssText="margin-right:auto",y.textContent=`${l} more update${l===1?"":"s"}`;const x=w("Mark all as read",!1);return x.style.cssText+=";padding:4px 9px",x.addEventListener("click",()=>o==null?void 0:o()),S.append(y,x),S}return{render(l){const S=Array.isArray(l)?l:[];if(!S.length){for(const O of c.values())h(O);c.clear(),f==null||f.remove(),f=null,p==null||p.remove(),p=null;return}const y=S.slice(-3),x=new Set(y.map(O=>O.id)),v=u();for(const[O,_]of c)x.has(O)||(h(_),c.delete(O));const k=[];for(const O of y){if(c.has(O.id))continue;const _=g(O);c.set(O.id,_),k.push(_)}const T=s?[...y].reverse():y;for(const O of T)v.appendChild(c.get(O.id));const j=S.length-y.length;j>0?(f==null||f.remove(),f=b(j),s?v.appendChild(f):v.insertBefore(f,v.firstChild)):(f==null||f.remove(),f=null),requestAnimationFrame(()=>{for(const O of k)O.isConnected&&(O._bcShown=!0,O.style.opacity="1",O.style.transform="translateY(0)")})},destroy(){c.clear(),f=null,p==null||p.remove(),p=null}}}async function No({apiBase:e,apiKey:t,projectId:n,sessionToken:o}){try{const a=await fetch(`${e}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,{headers:Ge(t,o)});if(!a.ok)return[];const r=await a.json();return Array.isArray(r==null?void 0:r.issues)?r.issues:[]}catch{return[]}}async function Uo({apiBase:e,apiKey:t,projectId:n,q:o,sessionToken:a,signal:r}){try{const i=`${e}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(o)}`,s=await fetch(i,{headers:Ge(t,a),signal:r});if(!s.ok)return[];const d=await s.json();return Array.isArray(d==null?void 0:d.issues)?d.issues:[]}catch{return[]}}async function Po({apiBase:e,apiKey:t,projectId:n,bugId:o,reporterEmail:a,reporterName:r,metadata:i,logs:s,sessionToken:d}){const c=V(),p=await fetch(`${e}/ingest/known-issues/${encodeURIComponent(o)}/join`,{method:"POST",headers:Ge(t,d),body:JSON.stringify({projectId:n,reporterEmail:a,reporterName:r,metadata:i,logs:s,...c?{watchToken:c}:{}})});if(!p.ok)throw new Error(await Ko(p));const f=await p.json();return f!=null&&f.watchToken&&Ze(f.watchToken),f}function Ge(e,t){return{"Content-Type":"application/json","X-BugCatch-Key":e,...t?{"X-BugCatch-Session":t}:{}}}async function Ko(e){let t="";try{const n=await e.json();t=Array.isArray(n.message)?n.message.join(", "):n.message||""}catch{}return e.status===429?pe(t):t||`Could not add you to this issue (HTTP ${e.status})`}async function _o({apiBase:e,bugId:t,score:n,comment:o}){const a=V();if(!a)throw new Error("This browser cannot access that report.");const r=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/rating${Me()}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({score:n,...o?{comment:o}:{}})}),i=await r.json().catch(()=>({}));if(!r.ok){const s=Array.isArray(i.message)?i.message.join(", "):i.message;throw new Error(s||"Could not send your rating. Please try again.")}return i}async function Vo({apiBase:e,bugId:t,...n}){const o=V();if(!o)throw new Error("This browser cannot access that report.");const a=await fetch(`${e}/ingest/watch/reports/${encodeURIComponent(t)}/verification`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(n)}),r=await a.json().catch(()=>({}));if(!a.ok)throw new Error(r.message||"Could not record feedback. Please refresh and try again.");return r}const Fo="bugcatch.session.",et=e=>`${Fo}${e}`,tt=new Map;function ae(e){var t;if(!e)return null;try{const n=(t=window.localStorage)==null?void 0:t.getItem(et(e));if(n){const o=JSON.parse(n);if(o!=null&&o.token)return o}}catch{}return tt.get(e)||null}function Wo(e,t){var o;if(!e||!(t!=null&&t.token))return;const n={token:t.token,email:t.email||null,name:t.name||null};tt.set(e,n);try{(o=window.localStorage)==null||o.setItem(et(e),JSON.stringify(n))}catch{}}function nt(e){var t;if(e){tt.delete(e);try{(t=window.localStorage)==null||t.removeItem(et(e))}catch{}}}function je({apiKey:e,token:t}){return{"Content-Type":"application/json","X-BugCatch-Key":e,...t?{"X-BugCatch-Session":t}:{}}}async function Nt(e){let t="";try{const n=await e.json();t=Array.isArray(n.message)?n.message.join(", "):n.message||""}catch{}return e.status===429?pe(t):t||`Request failed (HTTP ${e.status})`}async function Yo({apiBase:e,apiKey:t,projectId:n,token:o}){const a={mode:"off",signedIn:null,signedOutReason:null};try{const r=await fetch(`${e}/ingest/login?projectId=${encodeURIComponent(n)}`,{headers:je({apiKey:t,token:o})});if(!r.ok)return a;const i=await r.json();return{mode:i.mode==="optional"||i.mode==="required"?i.mode:"off",signedIn:i.signedIn||null,signedOutReason:i.signedOutReason||null}}catch{return a}}async function Xo({apiBase:e,apiKey:t,projectId:n,email:o,name:a}){const r=await fetch(`${e}/ingest/login/start`,{method:"POST",headers:je({apiKey:t}),body:JSON.stringify({projectId:n,email:o,...a?{name:a}:{}})});if(!r.ok)throw new Error(await Nt(r));return r.json()}async function Jo({apiBase:e,apiKey:t,projectId:n,email:o,code:a}){const r=await fetch(`${e}/ingest/login`,{method:"POST",headers:je({apiKey:t}),body:JSON.stringify({projectId:n,email:o,code:a})});if(!r.ok)throw new Error(await Nt(r));const i=await r.json(),s={token:i.sessionToken,email:i.email,name:i.name};return Wo(n,s),s}async function Zo({apiBase:e,apiKey:t,projectId:n,token:o}){if(nt(n),!o)return{signedOut:!0};try{await fetch(`${e}/ingest/logout`,{method:"POST",headers:je({apiKey:t,token:o}),body:JSON.stringify({projectId:n})})}catch{}return{signedOut:!0}}let Ut=!1;if(typeof window<"u"&&window.addEventListener)for(const e of["pointerdown","keydown","touchstart"])window.addEventListener(e,()=>{Ut=!0},{once:!0,capture:!0,passive:!0});function Go(){return Ut}const ea=2e4,Pt=120,ot=200;function Kt(e){if(typeof e!="string"||!e.trim()||e.length>400)return null;try{return new RegExp(e.trim(),"gi")}catch{return null}}const _t=e=>String(e).replace(/\s+/g," ").trim().slice(0,Pt);function Vt(e,t){const n=e&&e.normalize;if(n==="phone"){const o=t.replace(/\D/g,"");return o.length===10?o:o.length===12&&o.startsWith("91")?o.slice(2):o.length===11&&o.startsWith("0")?o.slice(1):t}return n==="upper"?t.toUpperCase():t}function Ft(e){const t=e.length>1&&e[1]!==void 0?e[1]:e[0];return typeof t!="string"||!t.trim()?null:{value:_t(t),start:e.index,end:e.index+e[0].length}}function ta(e,t){return((e.slice(t.start,t.valueStart)+e.slice(t.valueEnd,t.end)).match(/[a-z]/gi)||[]).length}const na=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi,Wt=/[\w-]/;function oa(e,t){const n=(e||[]).filter(u=>u&&u.scan!==!1&&u.pattern),o=[],a=[],r=(t||[]).map(u=>typeof u=="string"?u.slice(0,ea):"");r.forEach((u,h)=>{u&&n.forEach((m,C)=>{const w=Kt(m.pattern);if(!w)return;let g,b=0;for(w.lastIndex=0;(g=w.exec(u))!==null&&!(++b>ot);){if(g[0]===""){w.lastIndex+=1;continue}const l=Ft(g);if(!l)continue;const S=g.length>1&&g[1]!==void 0?g[1]:g[0],y=g.index+Math.max(0,g[0].indexOf(S)),x={block:h,order:C,key:m.key,label:m.label,value:Vt(m,l.value),start:l.start,end:l.end,valueStart:y,valueEnd:y+S.length};x.weight=ta(u,x),o.push(x)}})});const i=o.filter(u=>!o.some(h=>h!==u&&h.block===u.block&&h.key!==u.key&&h.valueStart<=u.valueStart&&h.valueEnd>=u.valueEnd&&h.weight>u.weight)),s=new Map;for(const u of i){const h=u.value.toLowerCase();s.has(h)||s.set(h,{value:u.value,keys:new Map});const m=s.get(h);m.keys.has(u.key)||m.keys.set(u.key,{key:u.key,label:u.label,order:u.order})}const d=[],c=[],p=new Map;for(const u of s.values()){const h=[...u.keys.values()].sort((w,g)=>w.order-g.order);if(h.length>1){c.push({value:u.value,kinds:h.map(({key:w,label:g})=>({key:w,label:g}))});continue}const[{key:m,label:C}]=h;p.has(m)||p.set(m,[]),p.get(m).push({key:m,label:C,value:u.value})}for(const u of p.values())if(u.length===1)d.push(u[0]);else for(const h of u)c.push({value:h.value,kinds:[{key:h.key,label:h.label}]});const f=new Set(s.keys());return r.forEach((u,h)=>{if(!u)return;const m=o.filter(b=>b.block===h),C=new RegExp(na.source,"gi");let w,g=0;for(;(w=C.exec(u))!==null&&++g<=ot;){const b=w.index,l=b+w[0].length;if(m.some(T=>b<T.end&&l>T.start))continue;const S=u[b-1]||"",y=u[l]||"";if(Wt.test(S)||Wt.test(y)||S==="/"||S==="@"||y==="@"||S==="."||y==="."&&/\w/.test(u[l+1]||"")||!/\d/.test(w[0]))continue;const x=_t(w[0]),v=x.toLowerCase();if(f.has(v))continue;const k=(e||[]).filter(T=>T&&Yt(T,x)).map(({key:T,label:j})=>({key:T,label:j}));k.length&&(f.add(v),a.push({value:x,kinds:k}))}}),{found:d,conflicts:c,loose:a}}function Yt(e,t){const n=typeof t=="string"?t.trim():"";if(!n||n.length>Pt)return null;const o=Kt(e&&(e.valuePattern||e.pattern));if(!o)return null;let a,r=0;for(o.lastIndex=0;(a=o.exec(n))!==null&&!(++r>ot);){if(a[0]===""){o.lastIndex+=1;continue}const i=a.index+a[0].length===n.length,s=a.index===0||a.index===1;if(i&&s){const d=Ft(a);if(d)return Vt(e,d.value)}}return null}async function aa({apiBase:e,apiKey:t,projectId:n}){const o={policy:"off",fields:[]};try{const a=await fetch(`${e}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":t}});if(!a.ok)return o;const r=await a.json(),i=r.policy==="optional"||r.policy==="required"?r.policy:"off",s=Array.isArray(r.fields)?r.fields:[];return s.length?{policy:i,fields:s}:o}catch{return o}}const ra=/Did this answer your question\?/i;async function ia({apiBase:e,apiKey:t,projectId:n}){try{const o=await fetch(`${e}/ingest/agent-issues?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":t}});if(!o.ok)return[];const a=await o.json();return(Array.isArray(a==null?void 0:a.issues)?a.issues:[]).filter(r=>r&&typeof r.key=="string"&&typeof r.title=="string").map(r=>({key:r.key,title:r.title,hint:typeof r.hint=="string"?r.hint:""}))}catch{return[]}}const sa=5*6e4,Xt="bugcatch:announcements:seen",ca=40,la=["info","success","warning","critical"],Jt=e=>`bugcatch:announcements:${e}`;async function da({apiBase:e,apiKey:t,projectId:n,fresh:o=!1}){var a;if(!o){const r=ma(n);if(r)return r}try{const r=await fetch(`${e}/ingest/announcements?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":t}}),i=r.ok?ba((a=await r.json())==null?void 0:a.announcements):[];return ya(n,i),i}catch{return[]}}function ua(e,{on:t=fa(),seen:n=Gt()}={}){return(e||[]).filter(o=>ga(o,t)&&!(o.dismissible&&n.includes(Zt(o))))}function pa(e){if(!(!(e!=null&&e.id)||!e.dismissible))try{const t=Zt(e),n=[...Gt().filter(o=>o!==t),t];localStorage.setItem(Xt,JSON.stringify(n.slice(-ca)))}catch{}}function ha(e){return typeof e!="string"||!e||e.startsWith("//")?null:e.startsWith("/")||/^(https?:\/\/|mailto:)./i.test(e)?e:null}function fa(e=new Date){const t=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function ga(e,t){return!(e.startsOn&&t<e.startsOn||e.endsOn&&t>e.endsOn)}function Zt(e){return`${e.id}#${e.revision||0}`}function ba(e){return(Array.isArray(e)?e:[]).filter(t=>t&&typeof t.id=="string"&&typeof t.title=="string"&&t.title.trim()).map(t=>{const n=t.placement==="launcher"?"launcher":"panel",o=ha(t.ctaHref);return{id:t.id,revision:Number.isInteger(t.revision)?t.revision:0,title:t.title,body:typeof t.body=="string"?t.body:"",tone:la.includes(t.tone)?t.tone:"info",ctaLabel:o&&typeof t.ctaLabel=="string"?t.ctaLabel:"",ctaHref:o&&typeof t.ctaLabel=="string"?o:"",placement:n,dismissible:n==="launcher"||t.dismissible!==!1,startsOn:typeof t.startsOn=="string"?t.startsOn:"",endsOn:typeof t.endsOn=="string"?t.endsOn:""}})}function Gt(){try{const e=JSON.parse(localStorage.getItem(Xt)||"[]");return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}catch{return[]}}function ma(e){try{const t=JSON.parse(localStorage.getItem(Jt(e))||"null");if(!t||!Array.isArray(t.list)||typeof t.at!="number")return null;const n=Date.now()-t.at;return n>=0&&n<sa?t.list:null}catch{return null}}function ya(e,t){try{localStorage.setItem(Jt(e),JSON.stringify({at:Date.now(),list:t}))}catch{}}const Oe=120,wa=500,ze=30,va=1e3,at={loanId:["loanId","loanNumber"],applicationId:["applicationId"],customerNumber:["customerNumber","customerId"]},xa=/[\u0000-\u001f\u007f]/;function ka(e){if(typeof e=="number")return Number.isFinite(e)?String(e):null;if(typeof e!="string")return null;const t=e.trim();return!t||t.length>Oe||xa.test(t)?null:t}function ee(e){return e===null?"null":Array.isArray(e)?"an array":typeof e=="object"?"an object":`a ${typeof e}`}function rt(e,t,n,o,a){for(const r of n){if(!(r in e)||e[r]===void 0||e[r]===null||e[r]==="")continue;const i=ka(e[r]);if(i)return i;const s=e[r];a(typeof s=="string"&&s.trim().length>Oe?`${o}.${r} is longer than ${Oe} characters and was dropped — pass the identifier itself, not a sentence or a URL.`:`${o}.${r} should be a string or number, got ${ee(s)} — it was dropped.`)}return null}function en(e){if(e===null||typeof e=="boolean")return{ok:!0,value:e};if(typeof e=="number")return Number.isFinite(e)?{ok:!0,value:e}:{ok:!1};if(typeof e=="string")return{ok:!0,value:e.slice(0,wa)};if(typeof e=="object")try{const t=JSON.stringify(e);if(t&&t.length<=va)return{ok:!0,value:JSON.parse(t)}}catch{}return{ok:!1}}const tn=["email","name","phone"],Sa=new Set(["id","userId",...tn,...Object.values(at).flat()]);function nn(e,t=()=>{}){if(e==null)return null;if(typeof e!="object"||Array.isArray(e))return t(`identify() takes an object like { id, email, name } or null, got ${ee(e)} — ignored.`),null;const n={};try{const o=rt(e,"id",["id","userId"],"identify()",t);o&&(n.id=o);for(const r of tn){const i=e[r];if(i==null||i==="")continue;if(r==="phone"&&typeof i=="number"&&Number.isFinite(i)){n.phone=String(i);continue}if(typeof i!="string"){t(`identify().${r} should be a string, got ${ee(i)} — it was dropped.`);continue}const s=i.trim().slice(0,r==="name"?200:Oe);s&&(r==="email"&&!s.includes("@")&&t(`identify().email "${s}" does not look like an email address — reports cannot be threaded or followed up without one.`),n[r]=s)}for(const[r,i]of Object.entries(at)){const s=rt(e,r,i,"identify()",t);s&&(n[r]=s)}let a=0;for(const[r,i]of Object.entries(e)){if(Sa.has(r)||i===void 0||typeof i=="function")continue;if(a>=ze){t(`identify() was given more than ${ze} extra fields; the rest were dropped.`);break}const s=en(i);if(!s.ok){t(`identify().${r} could not be sent (${ee(i)} too large or not serialisable) — dropped.`);continue}n[r]=s.value,a+=1}}catch{}return!n.id&&!n.email&&t("identify() was called without an id or email — reports will not be attributed to anyone, and nothing can be looked up by user."),n}function on(e,t,n=()=>{}){if(t===null)return{};const o={...e||{}};if(t===void 0)return o;if(typeof t!="object"||Array.isArray(t))return n(`setContext() takes an object like { loanId, screen } or null, got ${ee(t)} — ignored.`),o;try{const a=new Map;for(const[r,i]of Object.entries(at))for(const s of i)a.set(s,r);for(const[r,i]of Object.entries(t)){const s=a.get(r);if(i==null){delete o[s||r];continue}if(s){const c=rt({[r]:i},s,[r],"setContext()",n);c?o[s]=c:delete o[s];continue}if(typeof i=="function")continue;if(!(r in o)&&Object.keys(o).length>=ze){n(`setContext() holds at most ${ze} keys; "${r}" was dropped.`);continue}const d=en(i);if(!d.ok){n(`setContext().${r} could not be sent (${ee(i)} too large or not serialisable) — dropped.`);continue}o[r]=d.value}}catch{}return o}const an=["apiBase","apiKey","projectId","consoleLimit","networkLimit","captureConsole","captureNetwork","captureErrors","widget","widgetPosition","theme","accent","attachments","maxAttachments","maxAttachmentBytes","maxRecordingMs","beforeSend","user","context","updates","updateToast","onUpdate","voice","onCallState","onIncomingCall","onReportSubmitted","onAssistantPhase","onError","debug","drafts","knownIssues","agentIssues","release","environment","buildId","chunkBase","announcements"],$a=["beforeSend","onUpdate","onCallState","onIncomingCall","onReportSubmitted","onAssistantPhase","onError"];function Ca(e){const t=e.toLowerCase().replace(/[-_]/g,"");return an.find(n=>n.toLowerCase()===t)||null}const rn=/^(your[_-]|<|xxx|todo|changeme)/i,Ta=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Ea(e,{pageHost:t=""}={}){const n=[],o=[];if(!e||typeof e!="object")return n.push("init() takes an options object: BugCatch.init({ apiBase, apiKey, projectId })."),{errors:n,warnings:o};const{apiKey:a,projectId:r,apiBase:i}=e;a?typeof a!="string"?n.push(`apiKey must be a string, got ${ee(a)}.`):rn.test(a)?n.push(`apiKey is still the placeholder "${a}" — paste the key you saved when you created it.`):Ta.test(a)?o.push("apiKey looks like a project id — did you swap apiKey and projectId?"):a.startsWith("bc_")||o.push('apiKey does not look like a BugCatch key (they start with "bc_live_") — reports will be refused with HTTP 401.'):n.push("apiKey is required — create one under Workspace Settings → API Keys."),r?typeof r!="string"?n.push(`projectId must be a string, got ${ee(r)}.`):rn.test(r)?n.push(`projectId is still the placeholder "${r}".`):r.startsWith("bc_")?o.push("projectId looks like an API key — did you swap apiKey and projectId?"):/\s/.test(r)&&o.push("projectId contains whitespace — check it was copied cleanly."):n.push("projectId is required — copy it from Project Settings → Web SDK."),i==null?!t||/^(localhost|127\.|0\.0\.0\.0|\[::1\])/.test(t)||o.push("apiBase is not set, so reports go to http://localhost:3000 — set apiBase to your BugCatch API URL."):(typeof i!="string"||!/^https?:\/\//.test(i))&&o.push(`apiBase should be an absolute http(s) URL, got ${JSON.stringify(i)}.`);for(const s of Object.keys(e)){if(an.includes(s))continue;const d=Ca(s);o.push(d?`unknown option "${s}" — did you mean "${d}"?`:`unknown option "${s}" is ignored.`)}for(const s of $a){const d=e[s];d!=null&&typeof d!="function"&&o.push(`${s} should be a function, got ${ee(d)} — it will not be called.`)}return{errors:n,warnings:o}}function Ia(e){return typeof e=="string"?e.replace(/\/+$/,""):e}const we={name:"@sphoro/bugcatch-web-sdk",version:"0.20.0"},ve={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:null,announcements:!0,attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null,onReportSubmitted:null,onAssistantPhase:null,onError:null,context:null,chunkBase:null,debug:!1};function La(e){const t=V();return t?{...e,watchToken:t}:e}class sn{constructor(){Rn(this,B);this.config={...ve},this.started=!1,this.teardown=[],this.consoleBuffer=$e(ve.consoleLimit),this.networkBuffer=$e(ve.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map,this.context={},this.warned=new Set,this.phases=new Map}warn(t){this.warned.has(t)||(this.warned.add(t),console.warn(`[BugCatch] ${t}`))}debugLog(...t){this.config.debug&&console.info("[BugCatch]",...t)}init(t={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;const{errors:n,warnings:o}=Ea(t,{pageHost:typeof location<"u"?location.hostname:""});if(n.length)throw new Error(`[BugCatch] ${n[0]}`);for(const r of o)this.warn(r);const a=this.config.user;return this.config={...ve,...t,apiBase:Ia(t.apiBase??ve.apiBase)},this.config.user=t.user!==void 0?nn(t.user,r=>this.warn(r.replace("identify()","init({ user })"))):a||null,t.context&&this.setContext(t.context),this.consoleBuffer=$e(this.config.consoleLimit),this.networkBuffer=$e(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(Fn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(Wn(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Yn(this.consoleBuffer)),vo(this.config.projectId),this.config.widget&&this.teardown.push(ao(this)),this.config.updates&&V()&&(this.startWatching(),queueMicrotask(()=>q(this,B,re).call(this))),this.started=!0,q(this,B,jn).call(this),this.debugLog("initialised",{version:we.version,apiBase:this.config.apiBase,projectId:this.config.projectId,user:this.config.user,context:this.context}),this}startWatching(){if(this.stopWatching)return this;this.stopWatching=jo({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){q(this,B,Dn).call(this,n);return}if(n!=null&&n.callWithdrawn){q(this,B,Ve).call(this,n.callWithdrawn.callId);return}const o=ko(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),q(this,B,re).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>q(this,B,Ve).call(this));const t=n=>{(n.key===Be||n.key===null)&&q(this,B,re).call(this)};return window.addEventListener("storage",t),this.teardown.push(()=>window.removeEventListener("storage",t)),this}on(t,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(t)||new Set;return o.add(n),this.listeners.set(t,o),()=>this.off(t,n)}off(t,n){var o;return(o=this.listeners.get(t))==null||o.delete(n),this}emit(t,n){for(const o of this.listeners.get(t)||[])try{o(n)}catch(a){console.error(`[BugCatch] a '${t}' listener threw:`,a)}}unreadUpdates(){return ye()}markUpdateRead(t){return So(t),q(this,B,re).call(this),this}markReportRead(t){return $o(t),q(this,B,re).call(this),this}markUpdatesRead(){return qt(),q(this,B,re).call(this),this}async verifyFix(t,{result:n,resolvedAt:o,note:a}){const r=n==="STILL_HAPPENING"?await q(this,B,_e).call(this,{}):{};return Vo({apiBase:this.config.apiBase,bugId:t,result:n,resolvedAt:o,note:a,metadata:r.metadata,logs:r.logs})}async rate(t,{score:n,comment:o}={}){return _o({apiBase:this.config.apiBase,bugId:t,score:n,comment:o})}async myReport(t){const n=await Eo({apiBase:this.config.apiBase,bugId:t});return q(this,B,On).call(this,t,n==null?void 0:n.assistant),n}replyToReport(t,{body:n,attachments:o}={}){return Io({apiBase:this.config.apiBase,bugId:t,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const t={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?t:this.kinds!==void 0?this.kinds:(this.kinds=await Lo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(t){return this.config.voice?Dt({apiBase:this.config.apiBase,bugId:t}):Promise.resolve(!1)}async startCall(t){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await q(this,B,qn).call(this,t)}finally{this.callStarting=!1}}startLiveCall(t){return this.startCall(t)}canCallTeam(t){return this.config.voice?Dt({apiBase:this.config.apiBase,bugId:t}):Promise.resolve(!1)}endCall(){var t;return(t=this.call)==null||t.hangUp(),this.call=null,this}myReports(){return To({apiBase:this.config.apiBase})}hasReports(){return!!V()}forgetReports(){var t;return(t=this.stopWatching)==null||t.call(this),this.stopWatching=null,this.endCall(),ce(),q(this,B,re).call(this),this}identify(t){const n=nn(t,o=>this.warn(o));return t!=null&&!n?this:(this.config.user=n,this.debugLog("identify",n),this)}setContext(t){return this.context=on(this.context,t,n=>this.warn(n)),this.debugLog("context",this.context),this}getContext(){return{...this.context}}open(){return this.started?this.widgetControls?(this.widgetControls.open(),this):(this.warn("open() needs the built-in widget; it was turned off with widget: false."),this):(this.warn("open() was called before init() — nothing to open yet."),this)}close(){var t;return(t=this.widgetControls)==null||t.close(),this}isOpen(){var t;return!!((t=this.widgetControls)!=null&&t.isOpen())}async uploadAttachment(t,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return mo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:t,mime:n||(t==null?void 0:t.type),onProgress:o})}async report({title:t,description:n="",priority:o="MEDIUM",metadata:a={},attachments:r=[],references:i=[],context:s=null,issue:d=null}={}){var w,g,b,l,S,y,x,v;if(!this.started)throw new Error("[BugCatch] call init() first.");if(typeof t!="string"||!t.trim())throw new Error("[BugCatch] a title is required.");["LOW","MEDIUM","HIGH","CRITICAL"].includes(String(o).toUpperCase())||(this.warn(`priority "${o}" is not one of LOW, MEDIUM, HIGH, CRITICAL — sent as MEDIUM.`),o="MEDIUM");const c=(r||[]).filter(k=>(k==null?void 0:k.storageKey)&&Ie(k.mime,Ee)).map(k=>({type:k.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:k.storageKey,mime:Ie(k.mime,Ee)})),p=(Array.isArray(i)?i:[]).filter(k=>k&&typeof k.key=="string"&&k.key&&(typeof k.value=="string"||typeof k.value=="number")).map(k=>({key:k.key.slice(0,64),value:String(k.value).trim().slice(0,120)})).filter(k=>k.value);Array.isArray(i)&&p.length<i.length&&this.warn("report({ references }) takes [{ key, value }] with string values; malformed entries were dropped.");let f=await q(this,B,_e).call(this,{title:t.trim(),description:typeof n=="string"?n:String(n??""),priority:String(o).toUpperCase(),metadata:a,media:c,references:p,context:s,issue:typeof d=="string"&&d?d.slice(0,32):null});const u=q(this,B,ht).call(this,f);if(u===!1)return{cancelled:!0};f=u,this.debugLog("sending report",{title:f.title,user:(w=f.metadata)==null?void 0:w.user,context:(g=f.metadata)==null?void 0:g.context,references:f.references,console:(S=(l=(b=f.logs)==null?void 0:b.console)==null?void 0:l.entries)==null?void 0:S.length,network:(v=(x=(y=f.logs)==null?void 0:y.network)==null?void 0:x.entries)==null?void 0:v.length});const h=ae(this.config.projectId);let m;try{m=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...h!=null&&h.token?{"X-BugCatch-Session":h.token}:{}},body:JSON.stringify(La(f))})}catch(k){const T=new Error(`[BugCatch] could not reach ${this.config.apiBase} — check apiBase, and that this site's origin is allowed by the API.`);throw T.cause=k,q(this,B,Ke).call(this,"report",T),T}if(m.status===401&&h&&nt(this.config.projectId),!m.ok){let k="";try{const j=await m.json();k=Array.isArray(j.message)?j.message.join(", "):j.message||""}catch{}m.status===401&&!h&&(k||(k="the apiKey was not accepted")),m.status===403&&(k||(k="the apiKey is not allowed to report to this projectId"));const T=m.status===429?new Error(`[BugCatch] ${pe(k)}`):new Error(`[BugCatch] report failed (HTTP ${m.status})${k?": "+k:""}`);throw T.status=m.status,q(this,B,Ke).call(this,"report",T),T}const C=await m.json();return q(this,B,pt).call(this,C,{title:f.title??t.trim(),via:"form"}),C.watchToken&&(Ze(C.watchToken),this.config.updates&&this.startWatching()),C}loginState(){var t;return Yo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(t=ae(this.config.projectId))==null?void 0:t.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=aa({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}agentIssues(){return this.agentIssueList?this.agentIssueList:(this.agentIssueList=ia({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.agentIssueList)}async announcements(){const t=await da({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId});return ua(t)}dismissAnnouncement(t){pa(t)}signedInAs(){const t=ae(this.config.projectId);return t?{email:t.email,name:t.name}:null}signIn(t,{name:n}={}){var o;return Xo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:t,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(t,n){var a;const o=await Jo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:t,code:n});return(a=this.config.user)!=null&&a.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const t=ae(this.config.projectId),n=await Zo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:t==null?void 0:t.token});return t!=null&&t.email&&((o=this.config.user)==null?void 0:o.email)===t.email&&(this.config.user=null),this.emit("signout",{email:(t==null?void 0:t.email)||null}),n}knownIssues(){var t;return No({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(t=ae(this.config.projectId))==null?void 0:t.token})}matchKnownIssues(t,{signal:n}={}){var o;return Uo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:t||"",sessionToken:(o=ae(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(t,{email:n,name:o}={}){var i,s;const a=ae(this.config.projectId),r=await wt();return Po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:t,reporterEmail:n||((i=this.config.user)==null?void 0:i.email),reporterName:o||((s=this.config.user)==null?void 0:s.name),metadata:{...r,user:this.config.user||void 0,...Object.keys(this.context).length?{context:this.context}:{},sdk:we},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:a==null?void 0:a.token})}snapshot(){return{user:this.config.user||null,context:{...this.context},console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:vt()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(t=>{try{t()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,Pe=function(t,n){const o=this.config[t];if(typeof o=="function")try{o(n)}catch(a){console.error(`[BugCatch] your ${t} callback threw:`,a)}},jn=function(){if(typeof window>"u"||typeof fetch!="function")return;const t=`bugcatch:hello:${this.config.projectId}`,n=new Date().toISOString().slice(0,10);try{if(window.localStorage.getItem(t)===n)return}catch{}const o=setTimeout(()=>{try{window.localStorage.setItem(t,n)}catch{}fetch(`${this.config.apiBase}/ingest/hello`,{method:"POST",keepalive:!0,headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey},body:JSON.stringify({projectId:this.config.projectId,version:we.version,identify:!!this.config.user,context:!!(this.context&&Object.keys(this.context).length),widget:!!this.config.widget,environment:this.config.environment||null,release:this.config.release||null})}).catch(()=>{})},5e3);this.teardown.push(()=>clearTimeout(o))},re=function(){const t=ye();if(this.emit("unread",{count:t.length,updates:t}),!!this.config.updateToast){if(!this.notifier){if(!t.length)return;this.notifier=Ho({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(t)}},On=function(t,n){const o=n==null?void 0:n.phase;if(!t||typeof o!="string"||this.phases.get(t)===o)return;this.phases.set(t,o);const a={bugId:t,phase:o,title:n.title??null,detail:n.detail??null};this.debugLog("assistant",a),q(this,B,Pe).call(this,"onAssistantPhase",a),this.emit("assistant",a)},pt=function(t,{title:n,via:o}){if(!(t!=null&&t.id))return;const a={bugId:t.id,title:n??null,via:o,result:t};this.debugLog("report accepted",a),q(this,B,Pe).call(this,"onReportSubmitted",a),this.emit("report",a)},Ke=function(t,n){q(this,B,Pe).call(this,"onError",{action:t,error:n}),this.emit("error",{action:t,error:n})},_e=async function({title:t,description:n="",priority:o="MEDIUM",metadata:a={},media:r=[],references:i=[],context:s=null,issue:d=null}){var p,f;const c=s?on(this.context,s,u=>this.warn(u.replace("setContext()","report({ context })"))):this.context;return{projectId:this.config.projectId,...t?{title:t}:{},description:n,priority:o,url:window.location.href,reporterEmail:(p=this.config.user)==null?void 0:p.email,reporterName:(f=this.config.user)==null?void 0:f.name,metadata:{...await wt(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...a,user:this.config.user||void 0,...Object.keys(c).length?{context:c}:{},sdk:we},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...i.length?{references:i}:{},...d?{issue:d}:{}}},ht=function(t){if(typeof this.config.beforeSend!="function")return t;let n;try{n=this.config.beforeSend(t)}catch(o){return this.warn(`beforeSend threw, so nothing was sent: ${(o==null?void 0:o.message)||o}`),!1}return n===!1?!1:n&&typeof n=="object"?n:t},zn=async function(){const t=ae(this.config.projectId),n=q(this,B,ht).call(this,await q(this,B,_e).call(this,{}));if(n===!1)return this.debugLog("call cancelled by beforeSend"),{cancelled:!0};let o;try{o=await Ao({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:t==null?void 0:t.token,payload:n,watchToken:V()})}catch(a){throw a.status===401&&t&&nt(this.config.projectId),q(this,B,Ke).call(this,"call",a),a}return q(this,B,pt).call(this,o,{title:null,via:"call"}),o.watchToken&&(Ze(o.watchToken),this.config.updates&&this.startWatching()),o},qn=async function(t){const{joinLiveCall:n,liveCallSupported:o,openMicrophone:a}=await Ce(this.config.chunkBase);if(!o())throw new Error("[BugCatch] this browser cannot make live calls.");const r=await a();let i,s=null;try{if(t)i=await Mo({apiBase:this.config.apiBase,bugId:t});else if(s=await q(this,B,zn).call(this),t=s.id,i=s.live_call,!(i!=null&&i.realtime_url)){const c=new Error(`[BugCatch] the report was filed, but the team could not be rung${s.call_error?`: ${s.call_error}`:"."}`);throw c.filed=s,c.reason=s.call_error||null,c}}catch(c){for(const p of r.getTracks())p.stop();throw c}const d=await n({realtimeUrl:i.realtime_url,stream:r,ringsUntil:i.rings_until,onState:(c,p)=>{(c==="ended"||c==="failed"||c==="missed")&&(this.call=null),c==="missed"&&Bo({apiBase:this.config.apiBase,bugId:t,callId:i.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(c,{bugId:t,live:!0,...p}),this.emit("call",{bugId:t,live:!0,state:c,...p})}});return this.call=d,Object.assign(d,{bugId:t,callId:i.call_id,live:!0,filed:s,recorded:!!i.recorded})},Dn=function(t){var a;const n=t.incomingCall;if(!this.config.voice||((a=this.ringing)==null?void 0:a.callId)===n.callId||this.call||this.callStarting)return;q(this,B,Ve).call(this);const o={callId:n.callId,dismiss:()=>{}};this.ringing=o,Ce(this.config.chunkBase).then(({liveCallSupported:r,showIncomingCall:i})=>{if(this.ringing!==o||(this.ringing=null,!r())||this.call||this.callStarting)return;const s=i({call:n,accent:this.config.accent,position:this.config.widgetPosition,touched:Go,onAnswer:()=>{q(this,B,Qn).call(this,t.bugId,n)},onDecline:()=>{this.ringing=null,Qt({apiBase:this.config.apiBase,bugId:t.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:t.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:t.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:s},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:t.bugId,...n})}catch{}this.emit("incoming-call",{bugId:t.bugId,callId:n.callId,state:"ringing"})},()=>{this.ringing===o&&(this.ringing=null)})},Ve=function(t){if(this.ringing&&!(t&&this.ringing.callId!==t)){try{this.ringing.dismiss()}catch{}this.ringing=null}},Qn=async function(t,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o,a;try{const i=await Ce(this.config.chunkBase);a=i.joinLiveCall,o=await i.openMicrophone()}catch(i){this.callStarting=!1,Qt({apiBase:this.config.apiBase,bugId:t,callId:n.callId}),this.emit("incoming-call",{bugId:t,callId:n.callId,state:"failed",error:i});return}let r;try{r=await Ro({apiBase:this.config.apiBase,bugId:t,callId:n.callId})}catch(i){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:t,callId:n.callId,state:"missed",error:i});return}try{const i=await a({realtimeUrl:r.realtime_url,stream:o,onState:(s,d)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:t,live:!0,incoming:!0,...d}),this.emit("call",{bugId:t,live:!0,incoming:!0,state:s,...d})}});this.call=i,this.emit("incoming-call",{bugId:t,callId:n.callId,state:"answered"})}catch(i){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:t,callId:n.callId,state:"failed",error:i})}finally{this.callStarting=!1}};const it=new sn;it.Client=sn,it.version=we.version;const Aa='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',Ma='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',cn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',ln='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',dn='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',Ba='<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',Ra='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',qe='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',ja='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',Oa='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 6l6 6-6 6"/></svg>',un='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.9l2.75 5.82 6.37.76-4.7 4.37 1.24 6.3L12 17.03l-5.66 3.12 1.24-6.3-4.7-4.37 6.37-.76z"/></svg>',za='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5l2.6-7.2A1.5 1.5 0 0 1 7.5 5.3h9a1.5 1.5 0 0 1 1.4 1L20.5 13.5V18a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 18z"/><path d="M3.5 13.5h4.8l1.2 2.2h5l1.2-2.2h4.8"/></svg>',qa='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',Da=`
|
|
298
310
|
@keyframes bc-fade-in { from { opacity: 0 } to { opacity: 1 } }
|
|
299
311
|
@keyframes bc-fade-out { to { opacity: 0 } }
|
|
300
312
|
@keyframes bc-panel-in { from { opacity: 0; transform: translateY(14px) scale(.965) } to { opacity: 1; transform: none } }
|
|
@@ -310,9 +322,12 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
310
322
|
@keyframes bc-shimmer { from { background-position: 200% 0 } to { background-position: -200% 0 } }
|
|
311
323
|
|
|
312
324
|
/* ---------- scrim + panel ---------- */
|
|
325
|
+
/* Still modal — focus stays in the panel and a click outside closes it — but
|
|
326
|
+
the host's page only dims enough to say so. It is their product, and the
|
|
327
|
+
visitor is reporting something about what is on it. */
|
|
313
328
|
.scrim {
|
|
314
329
|
position: fixed; inset: 0; z-index: 2147483001;
|
|
315
|
-
background: rgba(
|
|
330
|
+
background: rgba(14,14,16,.14);
|
|
316
331
|
animation: bc-fade-in 200ms ease both;
|
|
317
332
|
}
|
|
318
333
|
.scrim.closing { animation: bc-fade-out 170ms ease both; }
|
|
@@ -324,12 +339,11 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
324
339
|
.panel {
|
|
325
340
|
position: fixed;
|
|
326
341
|
display: flex; flex-direction: column;
|
|
327
|
-
width: calc(100vw - 40px); max-width:
|
|
342
|
+
width: calc(100vw - 40px); max-width: 400px;
|
|
328
343
|
max-height: calc(100vh - var(--bc-dock-h, 84px) - 52px);
|
|
329
344
|
overflow: hidden;
|
|
330
345
|
background: var(--bc-bg); color: var(--bc-fg);
|
|
331
346
|
border-radius: var(--bc-r-xl); box-shadow: var(--bc-shadow);
|
|
332
|
-
border: 1px solid color-mix(in srgb, var(--bc-border) 70%, transparent);
|
|
333
347
|
animation: bc-panel-in 340ms var(--bc-ease) both;
|
|
334
348
|
}
|
|
335
349
|
/* A conversation wants a height of its own, so the thread fills the panel
|
|
@@ -344,57 +358,58 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
344
358
|
/* ---------- header ---------- */
|
|
345
359
|
.head {
|
|
346
360
|
flex: none; position: relative;
|
|
347
|
-
display: flex; align-items: center; gap:
|
|
348
|
-
padding:
|
|
349
|
-
background:
|
|
361
|
+
display: flex; align-items: center; gap: 11px;
|
|
362
|
+
padding: 14px 10px 13px var(--bc-pad);
|
|
363
|
+
background: var(--bc-bg);
|
|
350
364
|
border-bottom: 1px solid var(--bc-border);
|
|
351
365
|
}
|
|
352
|
-
.head .mark
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
background: linear-gradient(140deg, var(--bc-accent), color-mix(in srgb, var(--bc-accent) 60%, #fff));
|
|
356
|
-
color: var(--bc-on-accent); font-size: 19px;
|
|
357
|
-
box-shadow: 0 4px 12px color-mix(in srgb, var(--bc-accent) 30%, transparent);
|
|
358
|
-
}
|
|
359
|
-
/* The little "online" dot says someone — or something — is on the other end. */
|
|
360
|
-
.head .mark::after {
|
|
361
|
-
content: ''; position: absolute; right: -1px; bottom: -1px;
|
|
362
|
-
width: 11px; height: 11px; border-radius: 50%;
|
|
363
|
-
background: #22c55e; border: 2px solid var(--bc-bg);
|
|
364
|
-
}
|
|
366
|
+
.head .mark { width: 32px; }
|
|
367
|
+
/* The assistant asking its one follow-up wears the same orb, smaller. */
|
|
368
|
+
.avatar.orb { width: 26px; }
|
|
365
369
|
.head .titles { flex: 1; min-width: 0; }
|
|
366
370
|
.head h2 {
|
|
367
|
-
margin: 0 0
|
|
371
|
+
margin: 0 0 1px; font-size: var(--bc-fs-lg); font-weight: 600; letter-spacing: -.015em; line-height: 1.3;
|
|
372
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
373
|
+
}
|
|
374
|
+
.head p {
|
|
375
|
+
margin: 0; font-size: var(--bc-fs-sm); line-height: 1.4; color: var(--bc-muted);
|
|
368
376
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
369
377
|
}
|
|
370
|
-
.head p { margin: 0; font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted); }
|
|
371
378
|
.icon-btn {
|
|
372
379
|
flex: none; display: grid; place-items: center;
|
|
373
380
|
width: 32px; height: 32px; padding: 0; font-size: 16px;
|
|
374
|
-
border: none; border-radius:
|
|
381
|
+
border: none; border-radius: 999px; background: none; color: var(--bc-muted);
|
|
375
382
|
cursor: pointer; transition: background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
376
383
|
}
|
|
377
384
|
.icon-btn:hover { background: color-mix(in srgb, var(--bc-fg) 7%, transparent); color: var(--bc-fg); }
|
|
378
385
|
.icon-btn:active { transform: scale(.92); }
|
|
379
386
|
.icon-btn.back { margin: 0 -6px 0 -8px; }
|
|
387
|
+
/* The theme button holds all three glyphs; the host's class picks one. */
|
|
388
|
+
.icon-btn.theme { font-size: 15px; margin-right: -4px; }
|
|
389
|
+
.icon-btn.theme > span { display: none; }
|
|
390
|
+
:host(.bc-light) .icon-btn.theme .m-light,
|
|
391
|
+
:host(.bc-dark) .icon-btn.theme .m-dark,
|
|
392
|
+
:host(.bc-auto) .icon-btn.theme .m-auto { display: block; }
|
|
380
393
|
|
|
381
394
|
.body {
|
|
382
395
|
flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
|
|
383
|
-
padding:
|
|
396
|
+
padding: 14px var(--bc-pad) 4px;
|
|
384
397
|
}
|
|
385
398
|
|
|
386
|
-
label { display: block; font-size:
|
|
399
|
+
label { display: block; font-size: 13px; font-weight: 560; color: var(--bc-fg); margin-bottom: 6px; letter-spacing: -.005em; }
|
|
387
400
|
label .opt { font-weight: 450; color: var(--bc-faint); }
|
|
401
|
+
/* Fields are stone wells that turn white when you are in them, the way the
|
|
402
|
+
rest of the product's forms do. */
|
|
388
403
|
input[type=text], input[type=email], textarea {
|
|
389
|
-
width: 100%; padding:
|
|
390
|
-
color: var(--bc-fg); background: var(--bc-
|
|
391
|
-
border: 1px solid
|
|
404
|
+
width: 100%; padding: 10px 12px; font-size: var(--bc-fs-md); line-height: 1.45;
|
|
405
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
406
|
+
border: 1px solid transparent; border-radius: var(--bc-r-md);
|
|
392
407
|
transition: border-color 160ms, box-shadow 160ms, background 160ms;
|
|
393
408
|
}
|
|
394
409
|
input[type=text]::placeholder, input[type=email]::placeholder, textarea::placeholder { color: var(--bc-faint); }
|
|
395
|
-
input[type=text]:hover, input[type=email]:hover, textarea:hover { border-color:
|
|
410
|
+
input[type=text]:hover, input[type=email]:hover, textarea:hover { border-color: var(--bc-border); }
|
|
396
411
|
input[type=text]:focus, input[type=email]:focus, textarea:focus {
|
|
397
|
-
outline: none; border-color: var(--bc-accent); box-shadow: var(--bc-ring);
|
|
412
|
+
outline: none; background: var(--bc-bg); border-color: var(--bc-accent); box-shadow: var(--bc-ring);
|
|
398
413
|
}
|
|
399
414
|
input.invalid, input.invalid:focus, textarea.invalid {
|
|
400
415
|
border-color: var(--bc-danger); animation: bc-nudge 240ms ease;
|
|
@@ -406,8 +421,8 @@ input.invalid, input.invalid:focus, textarea.invalid {
|
|
|
406
421
|
animation: bc-rise 200ms var(--bc-ease) both;
|
|
407
422
|
}
|
|
408
423
|
.field-err svg { font-size: 13px; flex: none; }
|
|
409
|
-
textarea { min-height:
|
|
410
|
-
.field { margin-bottom:
|
|
424
|
+
textarea { min-height: 76px; resize: vertical; }
|
|
425
|
+
.field { margin-bottom: 14px; }
|
|
411
426
|
.field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
|
|
412
427
|
.field-head .count { font-size: var(--bc-fs-xs); color: var(--bc-faint); font-variant-numeric: tabular-nums; }
|
|
413
428
|
|
|
@@ -417,15 +432,15 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
417
432
|
.compose > .note:has(button) {
|
|
418
433
|
display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
|
|
419
434
|
margin: 0 0 14px; padding: 10px 12px; border-radius: var(--bc-r-md);
|
|
420
|
-
background: var(--bc-
|
|
435
|
+
background: var(--bc-subtle); border: 1px solid var(--bc-border);
|
|
421
436
|
font-size: var(--bc-fs-sm); color: var(--bc-fg);
|
|
422
437
|
}
|
|
423
438
|
.compose > .note button {
|
|
424
|
-
padding: 5px 11px; font: inherit; font-size: var(--bc-fs-xs); font-weight:
|
|
439
|
+
padding: 5px 11px; font: inherit; font-size: var(--bc-fs-xs); font-weight: 600;
|
|
425
440
|
border-radius: 999px; cursor: pointer;
|
|
426
441
|
border: 1px solid var(--bc-accent); background: var(--bc-accent); color: var(--bc-on-accent);
|
|
427
442
|
}
|
|
428
|
-
.compose > .note button[data-discard] { background:
|
|
443
|
+
.compose > .note button[data-discard] { background: var(--bc-bg); color: var(--bc-fg); border-color: var(--bc-border); }
|
|
429
444
|
|
|
430
445
|
/* ---------- what is already known ----------
|
|
431
446
|
A help surface in front of the form, not a step in it. Everything here is
|
|
@@ -433,58 +448,57 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
433
448
|
leave, tap "this is happening to me too" and leave, or type straight past all
|
|
434
449
|
of it and file the report they came to file. Nothing is ever in their way,
|
|
435
450
|
because a reporter who feels handled rather than helped stops reporting. */
|
|
436
|
-
|
|
437
|
-
.known .known-h {
|
|
438
|
-
margin: 0 0
|
|
451
|
+
/* One small eyebrow style for every group above the form. */
|
|
452
|
+
.known .known-h, .picks .picks-h {
|
|
453
|
+
margin: 0 0 7px; font-size: 11px; font-weight: 600; letter-spacing: .07em;
|
|
439
454
|
text-transform: uppercase; color: var(--bc-faint);
|
|
440
455
|
}
|
|
456
|
+
.known { margin-bottom: 14px; }
|
|
457
|
+
/* Hairline rows on the panel's own white, so they read as a list to scan
|
|
458
|
+
rather than more coloured cards to wade through. */
|
|
441
459
|
.known .issue {
|
|
442
460
|
display: flex; align-items: center; gap: 10px;
|
|
443
|
-
padding:
|
|
444
|
-
background: var(--bc-
|
|
461
|
+
padding: 8px 8px 8px 12px; margin-bottom: 6px;
|
|
462
|
+
background: var(--bc-bg); border: 1px solid var(--bc-border); border-radius: var(--bc-r-md);
|
|
445
463
|
animation: bc-rise 240ms var(--bc-ease) both;
|
|
446
464
|
}
|
|
447
|
-
.known .issue.is-joined {
|
|
465
|
+
.known .issue.is-joined { background: color-mix(in srgb, var(--bc-ok) 6%, var(--bc-bg)); }
|
|
448
466
|
.known .issue .who { flex: 1; min-width: 0; }
|
|
449
467
|
.known .issue .t {
|
|
450
|
-
display: block; font-size: 13px; font-weight:
|
|
468
|
+
display: block; font-size: 13px; font-weight: 560; line-height: 1.4;
|
|
451
469
|
color: var(--bc-fg); overflow-wrap: anywhere;
|
|
452
470
|
}
|
|
453
471
|
.known .issue .meta {
|
|
454
|
-
display: block; margin-top:
|
|
472
|
+
display: block; margin-top: 2px; font-size: var(--bc-fs-xs); line-height: 1.45; color: var(--bc-muted);
|
|
455
473
|
}
|
|
456
474
|
.known .issue .join {
|
|
457
|
-
flex: none; padding:
|
|
458
|
-
color: var(--bc-
|
|
459
|
-
border:
|
|
460
|
-
transition: background 160ms,
|
|
475
|
+
flex: none; height: 30px; padding: 0 12px; font: inherit; font-size: 12px; font-weight: 560;
|
|
476
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
477
|
+
border: 0; border-radius: 999px; cursor: pointer;
|
|
478
|
+
transition: background 160ms, color 160ms;
|
|
461
479
|
}
|
|
462
|
-
.known .issue .join:hover {
|
|
463
|
-
.known .issue .join:disabled { color: var(--bc-ok);
|
|
480
|
+
.known .issue .join:hover { background: color-mix(in srgb, var(--bc-fg) 12%, var(--bc-stone)); }
|
|
481
|
+
.known .issue .join:disabled { color: var(--bc-ok); background: transparent; cursor: default; opacity: 1; }
|
|
464
482
|
.known .ask { display: flex; gap: 8px; margin: 2px 0 8px; }
|
|
465
483
|
.known .ask input { flex: 1; min-width: 0; }
|
|
466
484
|
.known .ask button { flex: none; }
|
|
467
485
|
.known .err { margin: 6px 0 0; font-size: 12px; line-height: 1.45; color: var(--bc-danger); }
|
|
468
486
|
|
|
469
487
|
/* ---------- questions the assistant answers by itself ---------- */
|
|
470
|
-
.picks { margin-bottom:
|
|
471
|
-
.picks .picks-
|
|
472
|
-
margin: 0 0 8px; font-size: 11px; font-weight: 680; letter-spacing: .06em;
|
|
473
|
-
text-transform: uppercase; color: var(--bc-faint);
|
|
474
|
-
}
|
|
475
|
-
.picks .picks-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
|
|
488
|
+
.picks { margin-bottom: 14px; }
|
|
489
|
+
.picks .picks-grid { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
476
490
|
.picks .pick {
|
|
477
|
-
display: flex;
|
|
478
|
-
padding:
|
|
479
|
-
color: var(--bc-fg); background: var(--bc-
|
|
480
|
-
border: 1px solid
|
|
481
|
-
transition: background 160ms, border-color 160ms, transform 160ms;
|
|
491
|
+
display: inline-flex; align-items: center; max-width: 100%;
|
|
492
|
+
min-height: 32px; padding: 6px 13px; text-align: left; cursor: pointer; font: inherit;
|
|
493
|
+
color: var(--bc-fg); background: var(--bc-stone);
|
|
494
|
+
border: 1px solid transparent; border-radius: 999px;
|
|
495
|
+
transition: background 160ms, border-color 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
482
496
|
animation: bc-rise 240ms var(--bc-ease) both;
|
|
483
497
|
}
|
|
484
|
-
.picks .pick:hover {
|
|
485
|
-
.picks .pick
|
|
486
|
-
.picks .pick
|
|
487
|
-
.picks .pick .
|
|
498
|
+
.picks .pick:hover { background: color-mix(in srgb, var(--bc-fg) 10%, var(--bc-stone)); }
|
|
499
|
+
.picks .pick:active { transform: scale(.97); }
|
|
500
|
+
.picks .pick[aria-pressed="true"] { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
501
|
+
.picks .pick .t { font-size: 13px; font-weight: 520; line-height: 1.35; overflow-wrap: anywhere; }
|
|
488
502
|
.picks .picks-note {
|
|
489
503
|
display: flex; gap: 6px; align-items: flex-start; margin: 8px 0 0;
|
|
490
504
|
font-size: 12px; line-height: 1.45; color: var(--bc-muted);
|
|
@@ -498,18 +512,21 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
498
512
|
strip is the whole panel. */
|
|
499
513
|
.whoami {
|
|
500
514
|
display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
|
|
501
|
-
margin-bottom:
|
|
515
|
+
margin-bottom: 14px; padding: 9px 12px;
|
|
502
516
|
font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted);
|
|
503
517
|
background: var(--bc-subtle); border: 1px solid var(--bc-border); border-radius: var(--bc-r-md);
|
|
504
518
|
}
|
|
505
519
|
.whoami.asking { display: block; padding: 14px; }
|
|
520
|
+
.whoami.asking .row input { background: var(--bc-bg); border-color: var(--bc-border); }
|
|
506
521
|
.whoami .who { flex: 1; min-width: 0; }
|
|
507
522
|
.whoami .who strong { color: var(--bc-fg); font-weight: 620; word-break: break-all; }
|
|
508
523
|
.link {
|
|
509
|
-
padding: 0; font: inherit; font-size: var(--bc-fs-sm); font-weight:
|
|
510
|
-
color: var(--bc-
|
|
524
|
+
padding: 0; font: inherit; font-size: var(--bc-fs-sm); font-weight: 560; line-height: 1.45;
|
|
525
|
+
color: var(--bc-fg); background: none; border: none; cursor: pointer; border-radius: 4px;
|
|
526
|
+
text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--bc-fg) 30%, transparent);
|
|
527
|
+
text-underline-offset: 3px;
|
|
511
528
|
}
|
|
512
|
-
.link:hover { text-decoration
|
|
529
|
+
.link:hover { text-decoration-color: currentColor; }
|
|
513
530
|
.link:disabled { color: var(--bc-faint); cursor: default; text-decoration: none; }
|
|
514
531
|
.whoami .why { margin: 0 0 10px; font-size: var(--bc-fs-sm); line-height: 1.5; color: var(--bc-muted); }
|
|
515
532
|
.whoami .why strong { color: var(--bc-fg); font-weight: 620; word-break: break-all; }
|
|
@@ -526,18 +543,17 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
526
543
|
assistant asking one friendly follow-up, not as a form field that appeared. */
|
|
527
544
|
.refs {
|
|
528
545
|
position: relative;
|
|
529
|
-
margin-bottom:
|
|
546
|
+
margin-bottom: 14px; padding: 14px;
|
|
530
547
|
font-size: var(--bc-fs-sm); line-height: 1.45; color: var(--bc-muted);
|
|
531
|
-
background: var(--bc-
|
|
532
|
-
border: 1px solid var(--bc-
|
|
548
|
+
background: var(--bc-subtle);
|
|
549
|
+
border: 1px solid var(--bc-border); border-radius: var(--bc-r-lg);
|
|
533
550
|
animation: bc-item-in 280ms var(--bc-ease) both;
|
|
534
551
|
}
|
|
535
552
|
.refs .ask-head { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 11px; }
|
|
536
|
-
.refs .ask-head
|
|
537
|
-
.refs .ask-head strong { display: block; font-size: 13.5px; font-weight: 650; color: var(--bc-fg); margin-bottom: 1px; }
|
|
553
|
+
.refs .ask-head strong { display: block; font-size: 13.5px; font-weight: 600; color: var(--bc-fg); margin-bottom: 1px; }
|
|
538
554
|
.refs .why { margin: 0; font-size: var(--bc-fs-sm); line-height: 1.5; color: var(--bc-muted); }
|
|
539
555
|
.refs .row { display: flex; gap: 8px; align-items: stretch; }
|
|
540
|
-
.refs .row input { flex: 1; min-width: 0; background: var(--bc-bg); }
|
|
556
|
+
.refs .row input { flex: 1; min-width: 0; background: var(--bc-bg); border-color: var(--bc-border); }
|
|
541
557
|
.refs select {
|
|
542
558
|
flex: none; max-width: 45%; padding: 10px 10px; font-size: 13px;
|
|
543
559
|
color: var(--bc-fg); background: var(--bc-bg);
|
|
@@ -565,40 +581,44 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
565
581
|
.ref-found svg { width: 14px; height: 14px; flex: none; color: var(--bc-ok); }
|
|
566
582
|
.ref-found b { font-weight: 600; color: var(--bc-fg); }
|
|
567
583
|
|
|
568
|
-
/* ---------- severity ----------
|
|
569
|
-
|
|
584
|
+
/* ---------- severity ----------
|
|
585
|
+
The segmented control from the product: a stone track, the choice lifted out
|
|
586
|
+
of it on white. */
|
|
587
|
+
.seg { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; padding: 3px; background: var(--bc-stone); border-radius: 999px; }
|
|
570
588
|
.seg button {
|
|
571
589
|
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
572
|
-
padding:
|
|
573
|
-
color: var(--bc-muted); background: none; border: none; border-radius:
|
|
590
|
+
height: 30px; padding: 0 4px; font: inherit; font-size: var(--bc-fs-sm); font-weight: 520; line-height: 1;
|
|
591
|
+
color: var(--bc-muted); background: none; border: none; border-radius: 999px;
|
|
574
592
|
cursor: pointer; transition: background 180ms var(--bc-ease), color 180ms, box-shadow 180ms;
|
|
575
593
|
}
|
|
576
|
-
.seg button::before { content: ''; width:
|
|
577
|
-
.seg button[data-prio="LOW"] { --sev:
|
|
578
|
-
.seg button[data-prio="MEDIUM"] { --sev:
|
|
579
|
-
.seg button[data-prio="HIGH"] { --sev:
|
|
580
|
-
.seg button[data-prio="CRITICAL"] { --sev:
|
|
594
|
+
.seg button::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--sev, var(--bc-faint)); opacity: .5; transition: opacity 180ms; }
|
|
595
|
+
.seg button[data-prio="LOW"] { --sev: var(--bc-ok); }
|
|
596
|
+
.seg button[data-prio="MEDIUM"] { --sev: var(--bc-info); }
|
|
597
|
+
.seg button[data-prio="HIGH"] { --sev: var(--bc-warn); }
|
|
598
|
+
.seg button[data-prio="CRITICAL"] { --sev: var(--bc-danger); }
|
|
581
599
|
.seg button:hover { color: var(--bc-fg); }
|
|
582
600
|
.seg button[aria-pressed=true] {
|
|
583
|
-
background: var(--bc-raised); color: var(--bc-fg); font-weight:
|
|
584
|
-
box-shadow: 0 1px
|
|
601
|
+
background: var(--bc-raised); color: var(--bc-fg); font-weight: 600;
|
|
602
|
+
box-shadow: 0 1px 2px rgba(20,18,14,.10), 0 0 0 .5px rgba(20,18,14,.08);
|
|
585
603
|
}
|
|
586
604
|
.seg button[aria-pressed=true]::before { opacity: 1; }
|
|
587
605
|
.seg button:focus-visible { outline-offset: -2px; }
|
|
588
606
|
|
|
589
|
-
/* ---------- attachments ----------
|
|
590
|
-
|
|
607
|
+
/* ---------- attachments ----------
|
|
608
|
+
Three ring pills in a row: optional, so they take one line, not a band of
|
|
609
|
+
dashed drop zones. */
|
|
610
|
+
.tools { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
591
611
|
.tool {
|
|
592
|
-
display: inline-flex;
|
|
593
|
-
padding:
|
|
594
|
-
color: var(--bc-fg); background: var(--bc-
|
|
595
|
-
border: 1px
|
|
612
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
613
|
+
height: 32px; padding: 0 11px 0 9px; font: inherit; font-size: 12.5px; font-weight: 520; line-height: 1; white-space: nowrap;
|
|
614
|
+
color: var(--bc-fg); background: var(--bc-bg);
|
|
615
|
+
border: 1px solid var(--bc-border); border-radius: 999px; cursor: pointer;
|
|
596
616
|
transition: border-color 160ms, background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
597
617
|
}
|
|
598
|
-
.tool svg { font-size:
|
|
599
|
-
.tool:hover:not(:disabled) {
|
|
600
|
-
.tool:hover:not(:disabled) svg { color: var(--bc-
|
|
601
|
-
.tool:active:not(:disabled) { transform:
|
|
618
|
+
.tool svg { font-size: 15px; color: var(--bc-muted); transition: color 160ms; }
|
|
619
|
+
.tool:hover:not(:disabled) { background: var(--bc-subtle); border-color: color-mix(in srgb, var(--bc-fg) 20%, var(--bc-border)); }
|
|
620
|
+
.tool:hover:not(:disabled) svg { color: var(--bc-fg); }
|
|
621
|
+
.tool:active:not(:disabled) { transform: scale(.97); }
|
|
602
622
|
.tool:disabled { opacity: .45; cursor: not-allowed; }
|
|
603
623
|
.attach-hint { margin: 8px 0 0; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
604
624
|
|
|
@@ -649,7 +669,7 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
649
669
|
.foot {
|
|
650
670
|
flex: none;
|
|
651
671
|
display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
|
|
652
|
-
padding: 12px var(--bc-pad); border-top: 1px solid var(--bc-border);
|
|
672
|
+
padding: 12px 14px 12px var(--bc-pad); border-top: 1px solid var(--bc-border);
|
|
653
673
|
background: var(--bc-bg);
|
|
654
674
|
}
|
|
655
675
|
.foot .spacer { flex: 1; }
|
|
@@ -662,36 +682,39 @@ textarea { min-height: 88px; resize: vertical; }
|
|
|
662
682
|
size, and dimming it on top of that left it as a smudge in both themes. */
|
|
663
683
|
.powered {
|
|
664
684
|
flex: none; display: flex; align-items: center; justify-content: center; gap: 6px;
|
|
665
|
-
padding:
|
|
666
|
-
background: var(--bc-
|
|
685
|
+
padding: 0 var(--bc-pad) 10px; font-size: 10.5px; color: var(--bc-faint);
|
|
686
|
+
background: var(--bc-bg);
|
|
667
687
|
}
|
|
668
688
|
.brand-credit { display: flex; align-items: center; transition: color 0.15s; border-radius: 4px; }
|
|
669
|
-
.bc-brand { height:
|
|
689
|
+
.bc-brand { height: 15px; width: auto; display: block; color: var(--bc-brand-ink); }
|
|
670
690
|
.brand-credit:hover .bc-brand { color: var(--bc-fg); }
|
|
691
|
+
/* The product's two pills: ink for the one thing to do, a white ring for the
|
|
692
|
+
alternative. Flat — no glow, no lift. */
|
|
671
693
|
button.ghost, button.primary {
|
|
672
694
|
display: inline-flex; align-items: center; justify-content: center; gap: 7px;
|
|
673
|
-
height: 38px; padding: 0 15px; font: inherit; font-size:
|
|
695
|
+
height: 38px; padding: 0 15px; font: inherit; font-size: 13.5px; font-weight: 560; line-height: 1;
|
|
674
696
|
border-radius: 999px; cursor: pointer; white-space: nowrap;
|
|
675
697
|
transition: transform 160ms var(--bc-ease), filter 160ms, background 160ms, border-color 160ms, color 160ms, box-shadow 160ms;
|
|
676
698
|
}
|
|
677
|
-
button.ghost { background: var(--bc-bg); border:
|
|
678
|
-
button.ghost:hover:not(:disabled) { background: var(--bc-subtle);
|
|
699
|
+
button.ghost { background: var(--bc-bg); border: 0; color: var(--bc-fg); box-shadow: 0 0 0 1px var(--bc-border), 0 1px 2px rgba(20,18,14,.05); }
|
|
700
|
+
button.ghost:hover:not(:disabled) { background: var(--bc-subtle); }
|
|
679
701
|
button.ghost svg, button.primary svg { font-size: 15px; }
|
|
680
702
|
button.primary {
|
|
681
703
|
padding: 0 18px;
|
|
682
|
-
background: var(--bc-accent); border:
|
|
683
|
-
box-shadow: 0
|
|
704
|
+
background: var(--bc-accent); border: 0; color: var(--bc-on-accent);
|
|
705
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.14);
|
|
684
706
|
}
|
|
685
|
-
button.primary:hover:not(:disabled) {
|
|
686
|
-
button.primary:active:not(:disabled) { transform:
|
|
687
|
-
button:disabled { opacity: .
|
|
707
|
+
button.primary:hover:not(:disabled) { filter: brightness(1.12) contrast(.96); }
|
|
708
|
+
button.primary:active:not(:disabled) { transform: scale(.98); }
|
|
709
|
+
button:disabled { opacity: .45; cursor: not-allowed; }
|
|
688
710
|
button.primary:disabled { box-shadow: none; }
|
|
689
|
-
button.primary .spinner { border-color:
|
|
711
|
+
button.primary .spinner { border-color: color-mix(in srgb, var(--bc-on-accent) 40%, transparent); border-top-color: var(--bc-on-accent); width: 14px; height: 14px; }
|
|
690
712
|
button.quiet {
|
|
691
|
-
padding: 0 4px; height: 38px; font: inherit; font-size: 13px; font-weight:
|
|
713
|
+
padding: 0 4px; height: 38px; font: inherit; font-size: 13px; font-weight: 520;
|
|
692
714
|
border: none; background: none; color: var(--bc-muted); cursor: pointer; border-radius: 8px;
|
|
715
|
+
text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 3px;
|
|
693
716
|
}
|
|
694
|
-
button.quiet:hover { color: var(--bc-
|
|
717
|
+
button.quiet:hover { color: var(--bc-fg); text-decoration-color: color-mix(in srgb, var(--bc-fg) 35%, transparent); }
|
|
695
718
|
|
|
696
719
|
/* ---------- your reports ---------- */
|
|
697
720
|
.history {
|
|
@@ -711,13 +734,13 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
711
734
|
.history .row:last-child { border-bottom: 0; }
|
|
712
735
|
.history .who { flex: 1; min-width: 0; }
|
|
713
736
|
.history .ttl {
|
|
714
|
-
display: block; font-size: 13.5px; font-weight:
|
|
737
|
+
display: block; font-size: 13.5px; font-weight: 560; color: var(--bc-fg);
|
|
715
738
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
716
739
|
}
|
|
717
740
|
.history .sub { display: block; margin-top: 3px; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
718
741
|
.history .row-ico {
|
|
719
742
|
flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 10px;
|
|
720
|
-
background: var(--bc-
|
|
743
|
+
background: var(--bc-stone); color: var(--bc-muted); font-size: 16px;
|
|
721
744
|
}
|
|
722
745
|
.history .chev { flex: none; color: var(--bc-faint); font-size: 15px; transition: transform 160ms var(--bc-ease), color 160ms; }
|
|
723
746
|
.empty {
|
|
@@ -726,7 +749,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
726
749
|
}
|
|
727
750
|
.empty .empty-ico {
|
|
728
751
|
display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
|
|
729
|
-
background: var(--bc-
|
|
752
|
+
background: var(--bc-stone); color: var(--bc-fg); font-size: 20px;
|
|
730
753
|
}
|
|
731
754
|
.skel {
|
|
732
755
|
display: block; height: 12px; border-radius: 6px; margin: 6px 0;
|
|
@@ -742,7 +765,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
742
765
|
animation: bc-rise 260ms var(--bc-ease) both;
|
|
743
766
|
}
|
|
744
767
|
.history button.row:hover { background: var(--bc-subtle); }
|
|
745
|
-
.history button.row:hover .chev { transform: translateX(2px); color: var(--bc-
|
|
768
|
+
.history button.row:hover .chev { transform: translateX(2px); color: var(--bc-fg); }
|
|
746
769
|
.history button.row:focus-visible { outline-offset: -2px; }
|
|
747
770
|
|
|
748
771
|
/* ---------- one report, and what happened to it ---------- */
|
|
@@ -752,7 +775,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
752
775
|
padding: 10px var(--bc-pad); border-bottom: 1px solid var(--bc-border);
|
|
753
776
|
background: var(--bc-bg);
|
|
754
777
|
}
|
|
755
|
-
.report-head .ttl { font-size:
|
|
778
|
+
.report-head .ttl { font-size: 13.5px; font-weight: 600; color: var(--bc-fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
756
779
|
.report-head .sub { font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
757
780
|
.report-head .pill { grid-row: 1 / span 2; grid-column: 2; align-self: center; }
|
|
758
781
|
|
|
@@ -786,9 +809,9 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
786
809
|
border-radius: 50%; background: var(--bc-muted); vertical-align: middle;
|
|
787
810
|
}
|
|
788
811
|
.sys .t { color: var(--bc-faint); }
|
|
789
|
-
.sys.k-status .dot { background:
|
|
790
|
-
.sys.k-severity .dot { background:
|
|
791
|
-
.sys.k-assignment .dot { background:
|
|
812
|
+
.sys.k-status .dot { background: var(--bc-info); }
|
|
813
|
+
.sys.k-severity .dot { background: var(--bc-warn); }
|
|
814
|
+
.sys.k-assignment .dot { background: var(--bc-brand-mark); }
|
|
792
815
|
.sys.k-filed .dot { background: var(--bc-faint); }
|
|
793
816
|
|
|
794
817
|
/* ---------- the conversation ----------
|
|
@@ -821,24 +844,21 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
821
844
|
.msg-row.mine > * { grid-column: 1; }
|
|
822
845
|
.av {
|
|
823
846
|
display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
|
|
824
|
-
font-size: 11px; font-weight:
|
|
825
|
-
background:
|
|
847
|
+
font-size: 11px; font-weight: 650; letter-spacing: .02em;
|
|
848
|
+
background: var(--bc-stone); color: var(--bc-fg);
|
|
826
849
|
}
|
|
827
|
-
.av.bot {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
}
|
|
831
|
-
.msg-who { font-size: var(--bc-fs-xs); font-weight: 620; color: var(--bc-muted); padding: 0 4px 4px; }
|
|
832
|
-
.msg-who.auto { color: var(--bc-accent); display: inline-flex; align-items: center; gap: 5px; }
|
|
850
|
+
.av.bot { width: 28px; }
|
|
851
|
+
.msg-who { font-size: var(--bc-fs-xs); font-weight: 560; color: var(--bc-muted); padding: 0 4px 4px; }
|
|
852
|
+
.msg-who.auto { color: var(--bc-fg); display: inline-flex; align-items: center; gap: 5px; }
|
|
833
853
|
.msg-who .tag {
|
|
834
|
-
padding: 1px 6px; border-radius: 999px; font-size: 9.5px; font-weight:
|
|
835
|
-
text-transform: uppercase; background: var(--bc-
|
|
854
|
+
padding: 1px 6px; border-radius: 999px; font-size: 9.5px; font-weight: 650; letter-spacing: .05em;
|
|
855
|
+
text-transform: uppercase; background: var(--bc-stone); color: var(--bc-muted);
|
|
836
856
|
}
|
|
837
857
|
.bubble {
|
|
838
858
|
justify-self: start; max-width: 100%;
|
|
839
859
|
padding: 9px 13px; border-radius: 18px; font-size: 13.5px; line-height: 1.5;
|
|
840
|
-
background: var(--bc-
|
|
841
|
-
border: 1px solid
|
|
860
|
+
background: var(--bc-stone); color: var(--bc-fg);
|
|
861
|
+
border: 1px solid transparent;
|
|
842
862
|
border-bottom-left-radius: 6px;
|
|
843
863
|
}
|
|
844
864
|
/* pre-wrap belongs to the text, not the box — on the box it would also render
|
|
@@ -851,9 +871,10 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
851
871
|
}
|
|
852
872
|
.msg-row.cont.theirs .bubble { border-top-left-radius: 6px; }
|
|
853
873
|
.msg-row.cont.mine .bubble { border-top-right-radius: 6px; }
|
|
854
|
-
/* A reply nobody wrote:
|
|
855
|
-
it, so it reads the same to someone who cannot
|
|
856
|
-
|
|
874
|
+
/* A reply nobody wrote: drawn on white with a hairline, beside the orb and
|
|
875
|
+
labelled "Assistant" above it, so it reads the same to someone who cannot
|
|
876
|
+
see the difference at all. */
|
|
877
|
+
.msg-row.auto .bubble { background: var(--bc-bg); border-color: var(--bc-border); }
|
|
857
878
|
/* An attachment-only message has no text to wrap, so the bubble would be an
|
|
858
879
|
empty coloured box around it. */
|
|
859
880
|
.bubble.silent { padding: 0; background: none !important; border: 0; }
|
|
@@ -867,7 +888,7 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
867
888
|
/* The assistant, thinking. Three dots in a bubble where its next message will be. */
|
|
868
889
|
.typing { display: inline-flex; align-items: center; gap: 4px; padding: 12px 14px; justify-self: start; }
|
|
869
890
|
.typing i {
|
|
870
|
-
width:
|
|
891
|
+
width: 6px; height: 6px; border-radius: 50%; background: var(--bc-muted); opacity: .45;
|
|
871
892
|
animation: bc-typing 1.2s ease-in-out infinite;
|
|
872
893
|
}
|
|
873
894
|
.typing i:nth-child(2) { animation-delay: .15s; }
|
|
@@ -903,30 +924,29 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
903
924
|
background: var(--bc-subtle);
|
|
904
925
|
transition: background 400ms ease, border-color 400ms ease;
|
|
905
926
|
}
|
|
906
|
-
.assistant.
|
|
907
|
-
background: var(--bc-accent-soft); border-color: var(--bc-accent-line);
|
|
908
|
-
}
|
|
909
|
-
.assistant.resolved { background: color-mix(in srgb, var(--bc-ok) 9%, var(--bc-bg)); border-color: color-mix(in srgb, var(--bc-ok) 35%, var(--bc-border)); }
|
|
927
|
+
.assistant.resolved { background: color-mix(in srgb, var(--bc-ok) 7%, var(--bc-bg)); border-color: color-mix(in srgb, var(--bc-ok) 30%, var(--bc-border)); }
|
|
910
928
|
/* On a call: the call's own card is what they are watching. This one states
|
|
911
|
-
what is happening and stops moving — no
|
|
929
|
+
what is happening and stops moving — no breathing orb, no travelling bar. */
|
|
912
930
|
.assistant.calling { background: var(--bc-bg); }
|
|
913
931
|
.assistant.calling .as-progress i { transition: none; }
|
|
914
932
|
.as-body.entering { animation: bc-rise 360ms var(--bc-ease) both; }
|
|
915
933
|
.as-top { display: flex; gap: 11px; align-items: center; }
|
|
934
|
+
/* The orb, while the assistant is at work; a plain disc with a glyph once it
|
|
935
|
+
is on a call or has finished. */
|
|
916
936
|
.as-orb {
|
|
917
937
|
flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
|
|
918
|
-
color: var(--bc-on-accent); font-size: 15px;
|
|
919
|
-
background: linear-gradient(140deg, var(--bc-accent), color-mix(in srgb, var(--bc-accent) 60%, #fff));
|
|
938
|
+
color: var(--bc-on-accent); font-size: 15px; background: var(--bc-accent);
|
|
920
939
|
}
|
|
921
|
-
.
|
|
922
|
-
.assistant.
|
|
923
|
-
|
|
924
|
-
|
|
940
|
+
.as-orb.orb { background: var(--bc-o2); }
|
|
941
|
+
.assistant.analyzing .as-orb.orb { animation: as-breathe 2.4s ease-in-out infinite; }
|
|
942
|
+
@keyframes as-breathe { 50% { transform: scale(.88); } }
|
|
943
|
+
.assistant.resolved .as-orb { background: var(--bc-ok); color: #fff; }
|
|
944
|
+
.assistant.reviewing .as-orb.orb { filter: saturate(.35); }
|
|
925
945
|
.as-text { min-width: 0; flex: 1; }
|
|
926
|
-
.as-title { font-weight:
|
|
946
|
+
.as-title { font-weight: 600; font-size: 13.5px; letter-spacing: -.01em; color: var(--bc-fg); }
|
|
927
947
|
.as-detail { font-size: 12px; line-height: 1.45; color: var(--bc-muted); margin-top: 2px; }
|
|
928
948
|
.as-progress {
|
|
929
|
-
height:
|
|
949
|
+
height: 3px; margin: 12px 0 0; border-radius: 999px; overflow: hidden;
|
|
930
950
|
background: color-mix(in srgb, var(--bc-fg) 9%, transparent);
|
|
931
951
|
}
|
|
932
952
|
.as-progress i {
|
|
@@ -935,39 +955,42 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
935
955
|
}
|
|
936
956
|
.assistant.resolved .as-progress i { background: var(--bc-ok); }
|
|
937
957
|
.assistant.analyzing .as-progress i {
|
|
938
|
-
background: linear-gradient(90deg, var(--bc-accent) 0%, color-mix(in srgb, var(--bc-accent)
|
|
958
|
+
background: linear-gradient(90deg, var(--bc-accent) 0%, color-mix(in srgb, var(--bc-accent) 35%, var(--bc-bg)) 50%, var(--bc-accent) 100%);
|
|
939
959
|
background-size: 200% 100%; animation: bc-shimmer 1.6s linear infinite;
|
|
940
960
|
}
|
|
961
|
+
/* Four short labels under the bar. Allowed to wrap rather than be cut: at this
|
|
962
|
+
width "Report received" ellipsised to "Report recei…". */
|
|
941
963
|
.as-steps {
|
|
942
|
-
list-style: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px;
|
|
943
|
-
margin: 8px 0 0; padding: 0; font-size: 10.5px; color: var(--bc-faint);
|
|
964
|
+
list-style: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px 6px;
|
|
965
|
+
margin: 8px 0 0; padding: 0; font-size: 10.5px; line-height: 1.3; color: var(--bc-faint);
|
|
944
966
|
}
|
|
945
|
-
.as-steps li { display: flex; align-items:
|
|
946
|
-
.as-steps li .lbl { min-width: 0; overflow
|
|
947
|
-
.as-steps li .dot { flex: none; width:
|
|
967
|
+
.as-steps li { display: flex; align-items: flex-start; gap: 5px; min-width: 0; }
|
|
968
|
+
.as-steps li .lbl { min-width: 0; overflow-wrap: anywhere; }
|
|
969
|
+
.as-steps li .dot { flex: none; width: 7px; height: 7px; margin-top: 3px; border-radius: 50%; border: 1.5px solid currentColor; }
|
|
948
970
|
.as-steps li.done { color: var(--bc-muted); }
|
|
949
971
|
.as-steps li.done .dot { background: var(--bc-accent); border-color: var(--bc-accent); }
|
|
950
972
|
.assistant.resolved .as-steps li.done .dot { background: var(--bc-ok); border-color: var(--bc-ok); }
|
|
951
|
-
.as-steps li.active { color: var(--bc-fg); font-weight:
|
|
973
|
+
.as-steps li.active { color: var(--bc-fg); font-weight: 600; }
|
|
952
974
|
.as-steps li.active .dot { border-color: var(--bc-accent); background: var(--bc-bg); animation: as-pulse 1.2s ease-in-out infinite; }
|
|
953
|
-
@keyframes as-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bc-accent)
|
|
954
|
-
@media (prefers-reduced-motion: reduce) { .as-
|
|
975
|
+
@keyframes as-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bc-accent) 18%, transparent); } }
|
|
976
|
+
@media (prefers-reduced-motion: reduce) { .as-orb, .as-steps li.active .dot, .assistant.analyzing .as-progress i, .typing i { animation: none; } }
|
|
955
977
|
|
|
956
978
|
/* Quick answers under the confirm question — only on the latest message. */
|
|
957
979
|
.msg-row .quick { display: none; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
|
|
958
980
|
.msg-row:last-child .quick { display: flex; }
|
|
959
981
|
.quick button {
|
|
960
982
|
display: inline-flex; align-items: center; gap: 6px;
|
|
961
|
-
font: inherit; font-size: 13px; font-weight:
|
|
962
|
-
border:
|
|
983
|
+
font: inherit; font-size: 13px; font-weight: 560; height: 34px; padding: 0 14px; border-radius: 999px; cursor: pointer;
|
|
984
|
+
border: 0; background: var(--bc-bg); color: var(--bc-fg); box-shadow: 0 0 0 1px var(--bc-border);
|
|
963
985
|
transition: background 160ms, color 160ms, transform 160ms var(--bc-ease);
|
|
964
986
|
animation: bc-item-in 300ms var(--bc-ease) both;
|
|
965
987
|
}
|
|
966
|
-
.quick button:first-child { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
988
|
+
.quick button:first-child { background: var(--bc-accent); color: var(--bc-on-accent); box-shadow: none; }
|
|
967
989
|
.quick button:nth-child(2) { animation-delay: 60ms; }
|
|
968
990
|
.quick button svg { font-size: 13px; }
|
|
969
|
-
.quick button:hover {
|
|
970
|
-
.quick button:first-child:hover { background: var(--bc-accent); filter: brightness(1.
|
|
991
|
+
.quick button:hover { background: var(--bc-subtle); }
|
|
992
|
+
.quick button:first-child:hover { background: var(--bc-accent); filter: brightness(1.12) contrast(.96); }
|
|
993
|
+
.quick button:active { transform: scale(.97); }
|
|
971
994
|
|
|
972
995
|
/* ---------- the composer ---------- */
|
|
973
996
|
.composer {
|
|
@@ -984,10 +1007,10 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
984
1007
|
.composer .row {
|
|
985
1008
|
display: flex; align-items: flex-end; gap: 4px;
|
|
986
1009
|
padding: 5px; border-radius: 22px;
|
|
987
|
-
background: var(--bc-
|
|
988
|
-
transition: border-color 160ms, box-shadow 160ms;
|
|
1010
|
+
background: var(--bc-stone); border: 1px solid transparent;
|
|
1011
|
+
transition: border-color 160ms, box-shadow 160ms, background 160ms;
|
|
989
1012
|
}
|
|
990
|
-
.composer .row:focus-within { border-color: var(--bc-accent); box-shadow: var(--bc-ring); }
|
|
1013
|
+
.composer .row:focus-within { background: var(--bc-bg); border-color: var(--bc-accent); box-shadow: var(--bc-ring); }
|
|
991
1014
|
.composer textarea {
|
|
992
1015
|
flex: 1; min-width: 0; min-height: 34px; max-height: 120px; resize: none; padding: 7px 6px;
|
|
993
1016
|
font: inherit; font-size: 13.5px; line-height: 1.45;
|
|
@@ -1012,8 +1035,8 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
1012
1035
|
display: grid; place-items: center;
|
|
1013
1036
|
transition: transform 160ms var(--bc-ease), opacity 160ms, filter 160ms;
|
|
1014
1037
|
}
|
|
1015
|
-
.composer .send:hover:not(:disabled) { filter: brightness(1.
|
|
1016
|
-
.composer .send:disabled { opacity: .
|
|
1038
|
+
.composer .send:hover:not(:disabled) { filter: brightness(1.12) contrast(.96); transform: scale(1.04); }
|
|
1039
|
+
.composer .send:disabled { opacity: .3; cursor: default; background: var(--bc-faint); }
|
|
1017
1040
|
.composer .staged { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 0 8px; }
|
|
1018
1041
|
.composer .chip {
|
|
1019
1042
|
display: flex; align-items: center; gap: 6px; max-width: 200px;
|
|
@@ -1036,23 +1059,16 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
1036
1059
|
lands on — which is what someone opening this screen came to check. */
|
|
1037
1060
|
.pill {
|
|
1038
1061
|
flex: none; display: inline-flex; align-items: center; gap: 5px;
|
|
1039
|
-
font-size: 11px; font-weight:
|
|
1062
|
+
font-size: 11px; font-weight: 600;
|
|
1040
1063
|
padding: 3px 9px; border-radius: 999px;
|
|
1041
|
-
color: var(--bc-muted); background: var(--bc-
|
|
1064
|
+
color: var(--bc-muted); background: var(--bc-stone);
|
|
1042
1065
|
}
|
|
1043
1066
|
.pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
|
1044
|
-
|
|
1045
|
-
.pill.
|
|
1046
|
-
.pill.
|
|
1067
|
+
/* The theme's own status colours, which already have a dark cut. */
|
|
1068
|
+
.pill.open { color: var(--bc-warn); background: color-mix(in srgb, var(--bc-warn) 12%, var(--bc-bg)); }
|
|
1069
|
+
.pill.in_progress { color: var(--bc-info); background: color-mix(in srgb, var(--bc-info) 12%, var(--bc-bg)); }
|
|
1070
|
+
.pill.resolved { color: var(--bc-ok); background: color-mix(in srgb, var(--bc-ok) 12%, var(--bc-bg)); }
|
|
1047
1071
|
.pill.closed { color: var(--bc-muted); }
|
|
1048
|
-
:host(.bc-dark) .pill.open { color: #fbbf24; }
|
|
1049
|
-
:host(.bc-dark) .pill.in_progress { color: #7cb8ff; }
|
|
1050
|
-
:host(.bc-dark) .pill.resolved { color: #4ade9a; }
|
|
1051
|
-
@media (prefers-color-scheme: dark) {
|
|
1052
|
-
:host(.bc-auto) .pill.open { color: #fbbf24; }
|
|
1053
|
-
:host(.bc-auto) .pill.in_progress { color: #7cb8ff; }
|
|
1054
|
-
:host(.bc-auto) .pill.resolved { color: #4ade9a; }
|
|
1055
|
-
}
|
|
1056
1072
|
|
|
1057
1073
|
/* ---------- does the fix work ---------- */
|
|
1058
1074
|
.fix-verification {
|
|
@@ -1072,6 +1088,75 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
1072
1088
|
.fix-verification .feedback-status { margin: 6px 0 0; font-weight: 450; color: var(--bc-danger); font-size: var(--bc-fs-xs); }
|
|
1073
1089
|
.fix-verification .feedback-status:empty { display: none; }
|
|
1074
1090
|
|
|
1091
|
+
/* ---------- how did we do ----------
|
|
1092
|
+
Quieter than the card above it: that one asks whether the fix works, which
|
|
1093
|
+
the team acts on; this asks how it felt, which they learn from. The stars
|
|
1094
|
+
carry the only colour, so the one thing to do here is the thing you see. */
|
|
1095
|
+
.fix-rating {
|
|
1096
|
+
--bc-star: #f0a81c;
|
|
1097
|
+
flex: none; margin: 10px 12px 0; padding: 12px 14px;
|
|
1098
|
+
border-radius: var(--bc-r-lg); border: 1px solid var(--bc-border); background: var(--bc-bg);
|
|
1099
|
+
font-size: var(--bc-fs-sm); color: var(--bc-fg);
|
|
1100
|
+
animation: bc-rise 280ms var(--bc-ease) both;
|
|
1101
|
+
}
|
|
1102
|
+
.fix-rating .fr-q { margin: 0 0 6px; font-weight: 620; }
|
|
1103
|
+
.fix-rating .stars { display: flex; gap: 2px; margin: 0 0 2px -4px; }
|
|
1104
|
+
.fix-rating .stars button {
|
|
1105
|
+
display: inline-grid; place-items: center; width: 34px; height: 34px; padding: 0;
|
|
1106
|
+
border: 0; border-radius: 8px; background: transparent; cursor: pointer;
|
|
1107
|
+
color: color-mix(in srgb, var(--bc-fg) 18%, transparent);
|
|
1108
|
+
transition: color 120ms ease, transform 120ms var(--bc-ease);
|
|
1109
|
+
}
|
|
1110
|
+
.fix-rating .stars button svg { width: 24px; height: 24px; }
|
|
1111
|
+
.fix-rating .stars button.on { color: var(--bc-star); }
|
|
1112
|
+
.fix-rating .stars button:hover:not(:disabled) { transform: scale(1.08); }
|
|
1113
|
+
.fix-rating .stars button:focus-visible { outline: none; box-shadow: var(--bc-ring); }
|
|
1114
|
+
.fix-rating .stars button:disabled { cursor: default; }
|
|
1115
|
+
.fix-rating .fr-hint { margin: 2px 0 0; font-size: var(--bc-fs-xs); color: var(--bc-faint); }
|
|
1116
|
+
.fix-rating .fr-said { margin: 6px 0 0; font-size: 13px; color: var(--bc-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
1117
|
+
.fix-rating .fr-note { margin-top: 8px; }
|
|
1118
|
+
.fix-rating .fr-note textarea { min-height: 52px; margin-bottom: 8px; font-size: 13px; }
|
|
1119
|
+
.fix-rating .fr-note button {
|
|
1120
|
+
padding: 7px 13px; font: inherit; font-size: 12.5px; font-weight: 620; border-radius: 999px; cursor: pointer;
|
|
1121
|
+
border: 1px solid var(--bc-border); background: var(--bc-bg); color: var(--bc-fg);
|
|
1122
|
+
}
|
|
1123
|
+
.fix-rating .feedback-status { margin: 6px 0 0; color: var(--bc-danger); font-size: var(--bc-fs-xs); }
|
|
1124
|
+
.fix-rating .feedback-status:empty { display: none; }
|
|
1125
|
+
@media (prefers-reduced-motion: reduce) { .fix-rating .stars button { transition: none; } .fix-rating .stars button:hover { transform: none; } }
|
|
1126
|
+
|
|
1127
|
+
/* The rating on a history row: the score given, or a nudge to give one. */
|
|
1128
|
+
.history .sub .rated { display: inline-flex; align-items: center; gap: 2px; color: var(--bc-muted); font-weight: 600; }
|
|
1129
|
+
.history .sub .rated svg { width: 11px; height: 11px; color: #f0a81c; }
|
|
1130
|
+
.history .sub .rate-ask { color: var(--bc-fg); font-weight: 600; }
|
|
1131
|
+
|
|
1132
|
+
/* ---------- a settled report waiting for its rating ----------
|
|
1133
|
+
Above the form on the first screen: the same stars as under a report's
|
|
1134
|
+
conversation, with the report they are about named on top. */
|
|
1135
|
+
.rate-due { margin: 0 0 14px; }
|
|
1136
|
+
.rate-due:focus { outline: none; }
|
|
1137
|
+
.rate-due:focus-visible { box-shadow: var(--bc-ring); }
|
|
1138
|
+
.rate-due .rd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 8px; }
|
|
1139
|
+
.rate-due .rd-eyebrow {
|
|
1140
|
+
font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--bc-faint);
|
|
1141
|
+
}
|
|
1142
|
+
.rate-due.is-required .rd-eyebrow { color: var(--bc-fg); }
|
|
1143
|
+
.rate-due .rd-later { font-size: var(--bc-fs-xs); color: var(--bc-muted); }
|
|
1144
|
+
.rate-due .rd-report {
|
|
1145
|
+
display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 9px; align-items: center;
|
|
1146
|
+
margin: 0 0 10px; padding: 0 0 10px; border-bottom: 1px solid var(--bc-border);
|
|
1147
|
+
}
|
|
1148
|
+
.rate-due .rd-ico {
|
|
1149
|
+
grid-row: span 2; display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 999px;
|
|
1150
|
+
background: color-mix(in srgb, var(--bc-ok) 14%, transparent); color: var(--bc-ok);
|
|
1151
|
+
}
|
|
1152
|
+
.rate-due .rd-ico svg { width: 13px; height: 13px; }
|
|
1153
|
+
.rate-due .rd-ttl { font-weight: 620; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1154
|
+
.rate-due .rd-sub { font-size: var(--bc-fs-xs); color: var(--bc-muted); }
|
|
1155
|
+
|
|
1156
|
+
/* What a required rating is holding: still in sight, plainly not yet. */
|
|
1157
|
+
.held { opacity: .42; transition: opacity 200ms ease; }
|
|
1158
|
+
@media (prefers-reduced-motion: reduce) { .held { transition: none; } }
|
|
1159
|
+
|
|
1075
1160
|
/* A call in progress, in place of the form.
|
|
1076
1161
|
---------------------------------------------------------------------------
|
|
1077
1162
|
Deliberately not styled as a chat. Nothing arrives here to read — the
|
|
@@ -1121,13 +1206,13 @@ button.quiet:hover { color: var(--bc-accent); }
|
|
|
1121
1206
|
and this screen's padding was landing on every one of them. */
|
|
1122
1207
|
div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 240ms ease both; }
|
|
1123
1208
|
.done .tick {
|
|
1124
|
-
width:
|
|
1125
|
-
display: grid; place-items: center; font-size:
|
|
1126
|
-
background:
|
|
1127
|
-
box-shadow: 0 0 0
|
|
1209
|
+
width: 52px; height: 52px; margin: 0 auto 16px; border-radius: 50%;
|
|
1210
|
+
display: grid; place-items: center; font-size: 24px;
|
|
1211
|
+
background: var(--bc-ok); color: #fff;
|
|
1212
|
+
box-shadow: 0 0 0 7px color-mix(in srgb, var(--bc-ok) 12%, transparent);
|
|
1128
1213
|
animation: bc-pop 420ms var(--bc-ease) both;
|
|
1129
1214
|
}
|
|
1130
|
-
.done h3 { margin: 0 0 6px; font-size:
|
|
1215
|
+
.done h3 { margin: 0 0 6px; font-size: 18px; font-weight: 600; letter-spacing: -.02em; }
|
|
1131
1216
|
.done p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--bc-muted); }
|
|
1132
1217
|
.done code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; padding: 1px 5px; border-radius: 5px; background: var(--bc-subtle); color: var(--bc-fg); }
|
|
1133
1218
|
/* The likely wait. Set apart from the reference line above it by a rule rather
|
|
@@ -1191,7 +1276,7 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1191
1276
|
is open — the sheet has its own close button, and a launcher floating over
|
|
1192
1277
|
the send button would be in the way of the one thing that matters. */
|
|
1193
1278
|
@media (max-width: 480px) {
|
|
1194
|
-
.scrim { background: rgba(
|
|
1279
|
+
.scrim { background: rgba(14,14,16,.4); }
|
|
1195
1280
|
.panel, .scrim.at-right .panel, .scrim.at-left .panel, .scrim.at-bottom .panel, .scrim.at-top .panel {
|
|
1196
1281
|
inset: 0; width: 100%; max-width: none; height: 100%; max-height: none;
|
|
1197
1282
|
border-radius: 0; border: 0;
|
|
@@ -1206,6 +1291,16 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1206
1291
|
.foot:has(+ .powered) { padding-bottom: 12px; }
|
|
1207
1292
|
.recbar .hint { display: none; }
|
|
1208
1293
|
.msg-row, .typing-row { max-width: 92%; }
|
|
1294
|
+
/* The question chips are one row that scrolls sideways, edge to edge, rather
|
|
1295
|
+
than three stacked rows pushing the form down the screen. */
|
|
1296
|
+
.picks .picks-grid {
|
|
1297
|
+
flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
|
|
1298
|
+
margin: 0 calc(var(--bc-pad) * -1); padding: 0 var(--bc-pad) 2px;
|
|
1299
|
+
scroll-snap-type: x proximity; scroll-padding: 0 var(--bc-pad);
|
|
1300
|
+
}
|
|
1301
|
+
.picks .picks-grid::-webkit-scrollbar { display: none; }
|
|
1302
|
+
.picks .pick { flex: none; scroll-snap-align: start; }
|
|
1303
|
+
.picks .pick .t { white-space: nowrap; }
|
|
1209
1304
|
}
|
|
1210
1305
|
|
|
1211
1306
|
@media (pointer: coarse) {
|
|
@@ -1220,7 +1315,8 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1220
1315
|
under it, on the one surface in the product designed for someone who is
|
|
1221
1316
|
not an operator and gets no second attempt. */
|
|
1222
1317
|
.seg button { min-height: 44px; }
|
|
1223
|
-
.tool { min-height:
|
|
1318
|
+
.tool, .known .issue .join { min-height: 44px; }
|
|
1319
|
+
.picks .pick { min-height: 40px; }
|
|
1224
1320
|
button.primary, button.ghost { height: 44px; }
|
|
1225
1321
|
.composer .send, .composer .tool { width: 40px; height: 40px; min-height: 0; }
|
|
1226
1322
|
textarea { min-height: 104px; }
|
|
@@ -1229,7 +1325,7 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1229
1325
|
/* The close button and the thumbnails' remove buttons are small glyphs whose
|
|
1230
1326
|
boxes cannot grow without moving what is beside them, so each keeps its
|
|
1231
1327
|
size and gets an invisible target drawn around it instead. The theme
|
|
1232
|
-
|
|
1328
|
+
button in the header is one of these. */
|
|
1233
1329
|
.head .icon-btn, .thumb .drop, .brand-credit { position: relative; }
|
|
1234
1330
|
.thumb .drop { position: absolute; opacity: 1; }
|
|
1235
1331
|
.head .icon-btn::after, .thumb .drop::after, .brand-credit::after {
|
|
@@ -1243,26 +1339,28 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1243
1339
|
@media (hover: none) {
|
|
1244
1340
|
.tool:hover:not(:disabled) { transform: none; }
|
|
1245
1341
|
}
|
|
1246
|
-
`;function
|
|
1342
|
+
`;function st({title:e,sub:t,id:n="",back:o=!1,theme:a=""}){return`
|
|
1247
1343
|
<div class="head">
|
|
1248
|
-
${o?`<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${
|
|
1249
|
-
<
|
|
1344
|
+
${o?`<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${Ra}</button>`:""}
|
|
1345
|
+
<span class="orb mark" aria-hidden="true"></span>
|
|
1250
1346
|
<div class="titles">
|
|
1251
|
-
<h2${n?` id="${n}"`:""}>${E(
|
|
1252
|
-
<p>${E(
|
|
1347
|
+
<h2${n?` id="${n}"`:""}>${E(e)}</h2>
|
|
1348
|
+
<p>${E(t)}</p>
|
|
1253
1349
|
</div>
|
|
1254
|
-
|
|
1255
|
-
|
|
1350
|
+
${a?`<button class="icon-btn theme" type="button" data-act="theme" title="Theme: ${E(a)}"
|
|
1351
|
+
aria-label="Theme: ${E(a)}. Change theme"><span class="m-light">${kt}</span><span class="m-dark">${St}</span><span class="m-auto">${$t}</span></button>`:""}
|
|
1352
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${ge}</button>
|
|
1353
|
+
</div>`}function ct(e,t){return`<div class="empty"><span class="empty-ico" aria-hidden="true">${t}</span>${E(e)}</div>`}function Qa(e){return Array.from({length:e},()=>`
|
|
1256
1354
|
<div class="row" aria-hidden="true">
|
|
1257
1355
|
<span class="row-ico"></span>
|
|
1258
1356
|
<span class="who"><span class="skel" style="width:70%"></span><span class="skel" style="width:40%;height:9px"></span></span>
|
|
1259
|
-
</div>`).join("")+'<span class="sr-only">Loading…</span>'}function
|
|
1357
|
+
</div>`).join("")+'<span class="sr-only">Loading…</span>'}function Ha(){return`
|
|
1260
1358
|
<div aria-hidden="true" style="display:flex;flex-direction:column;gap:10px;padding-top:6px">
|
|
1261
1359
|
<span class="skel" style="width:42%;height:34px;border-radius:16px;align-self:center"></span>
|
|
1262
1360
|
<span class="skel" style="width:66%;height:52px;border-radius:18px"></span>
|
|
1263
1361
|
<span class="skel" style="width:48%;height:38px;border-radius:18px;align-self:flex-end"></span>
|
|
1264
1362
|
</div>
|
|
1265
|
-
<span class="sr-only">Loading…</span>`}function
|
|
1363
|
+
<span class="sr-only">Loading…</span>`}function Na(e){const t=String(e).trim().split(/\s+/).filter(Boolean);return t.length?(t[0][0]+(t.length>1?t[t.length-1][0]:"")).toUpperCase():"?"}function xe(e){const t=new Date(e);return Number.isFinite(t.getTime())?`${t.getFullYear()}-${t.getMonth()}-${t.getDate()}`:null}function Ua(e){const t=new Date(e),n=new Date,o=new Date(n.getFullYear(),n.getMonth(),n.getDate()-1);if(xe(t)===xe(n))return"Today";if(xe(t)===xe(o))return"Yesterday";try{return t.toLocaleDateString(void 0,{weekday:"short",day:"numeric",month:"short",...t.getFullYear()!==n.getFullYear()?{year:"numeric"}:{}})}catch{return Se(e)}}function pn(e){const t=new Date(e);if(!Number.isFinite(t.getTime()))return"";try{return t.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"})}catch{return""}}function hn(e){return e.scrollHeight-e.scrollTop-e.clientHeight<40}function ke(e,{smooth:t=!1}={}){const n=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;t&&!n&&e.scrollTo?e.scrollTo({top:e.scrollHeight,behavior:"smooth"}):e.scrollTop=e.scrollHeight}function lt(e){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[e]||String(e||"").toLowerCase()}function Se(e){const t=new Date(e).getTime();if(!Number.isFinite(t))return"";const n=Math.floor((Date.now()-t)/864e5);if(n<=0)return"today";if(n===1)return"yesterday";if(n<30)return`${n} days ago`;const o=Math.floor(n/30);return o===1?"a month ago":`${o} months ago`}function E(e){return String(e).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}const Pa=7*24*60*60*1e3;let De;function Ka(){return De||(De=new Promise((e,t)=>{const n=indexedDB.open("bugcatch-drafts",1);n.onupgradeneeded=()=>n.result.createObjectStore("drafts"),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error),n.onblocked=()=>t(new Error("Draft storage is blocked."))}).catch(e=>{throw De=null,e})),De}function _a(e,t){var n,o;return JSON.stringify([e.apiBase,e.projectId,t||((n=e.user)==null?void 0:n.email)||((o=e.user)==null?void 0:o.id)||"anonymous"])}async function Qe(e,t){const n=await Ka();return new Promise((o,a)=>{const r=n.transaction("drafts",t===void 0?"readonly":"readwrite"),i=r.objectStore("drafts"),s=t===void 0?i.get(e):t===null?i.delete(e):i.put({...t,savedAt:Date.now()},e);r.oncomplete=()=>o(s.result),r.onerror=()=>a(r.error),r.onabort=()=>a(r.error||new Error("Draft was not saved."))})}async function Va(e){const t=await Qe(e);return t&&Date.now()-t.savedAt>Pa?(await Qe(e,null),null):t||null}const fn=[{value:"LOW",label:"Low"},{value:"MEDIUM",label:"Medium"},{value:"HIGH",label:"High"},{value:"CRITICAL",label:"Critical"}],gn="MEDIUM";function Fa(e){const t=e.attachments!==!1,n=t&&ho(),o=t&&po();return`
|
|
1266
1364
|
<div class="compose">
|
|
1267
1365
|
<div class="field">
|
|
1268
1366
|
<label for="bc-title">What went wrong?</label>
|
|
@@ -1282,100 +1380,101 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1282
1380
|
<div class="field">
|
|
1283
1381
|
<label id="bc-prio-l">How much is it getting in your way?</label>
|
|
1284
1382
|
<div class="seg" role="group" aria-labelledby="bc-prio-l">
|
|
1285
|
-
${
|
|
1286
|
-
<button type="button" data-prio="${a.value}" aria-pressed="${a.value===
|
|
1383
|
+
${fn.map(a=>`
|
|
1384
|
+
<button type="button" data-prio="${a.value}" aria-pressed="${a.value===gn}">${a.label}</button>
|
|
1287
1385
|
`).join("")}
|
|
1288
1386
|
</div>
|
|
1289
1387
|
</div>
|
|
1290
|
-
${
|
|
1388
|
+
${t?`
|
|
1291
1389
|
<div class="field">
|
|
1292
1390
|
<div class="field-head">
|
|
1293
1391
|
<label id="bc-att-l">Show us <span class="opt">(optional)</span></label>
|
|
1294
1392
|
<span class="count" aria-live="polite"></span>
|
|
1295
1393
|
</div>
|
|
1296
1394
|
<div class="tools" role="group" aria-labelledby="bc-att-l">
|
|
1297
|
-
${n?`<button class="tool" type="button" data-act="shot">${
|
|
1298
|
-
${o?`<button class="tool" type="button" data-act="rec">${
|
|
1299
|
-
<button class="tool" type="button" data-act="file">${
|
|
1395
|
+
${n?`<button class="tool" type="button" data-act="shot">${Aa}Screenshot</button>`:""}
|
|
1396
|
+
${o?`<button class="tool" type="button" data-act="rec">${Ma}Record screen</button>`:""}
|
|
1397
|
+
<button class="tool" type="button" data-act="file">${cn}Upload file</button>
|
|
1300
1398
|
</div>
|
|
1301
1399
|
<div class="thumbs"></div>
|
|
1302
|
-
<input type="file" accept="${
|
|
1400
|
+
<input type="file" accept="${Ee.join(",")}" multiple hidden />
|
|
1303
1401
|
</div>`:""}
|
|
1304
|
-
</div>`}function
|
|
1305
|
-
${
|
|
1306
|
-
<span class="kind">${
|
|
1307
|
-
<button class="drop" type="button" data-act="drop" aria-label="Remove ${
|
|
1308
|
-
${
|
|
1402
|
+
</div>`}function Wa(e){var fe,de,ue,z;const{client:t,cfg:n,root:o,host:a,dock:r,scrim:i,$:s,say:d,titleInput:c,descInput:p,compose:f,sendBtn:u,note:h}=e,m=s(".thumbs"),C=i.querySelector("input[type=file]"),w=[];let g=gn,b=null;const l=document.createElement("div");l.setAttribute("role","status"),l.className="note",f.prepend(l);const S=_a(n,(fe=t.signedInAs())==null?void 0:fe.email);let y=n.drafts===!1,x=!1,v=Promise.resolve(),k;function T(){if(clearTimeout(k),!y||x||n.drafts===!1)return v;const $=c.value||p.value||w.length?{title:c.value,description:p.value,priority:g,items:w.map(({blob:A,mime:H,kind:N})=>({blob:A,mime:H,kind:N}))}:null;return v=v.catch(()=>{}).then(()=>Qe(S,$)).then(()=>{l.textContent=$?"Draft saved on this device":""}).catch(()=>{l.textContent="Draft could not be saved. Keep this tab open."}),v}function j(){clearTimeout(k),k=setTimeout(T,250)}f.addEventListener("input",j),f.addEventListener("change",j);const O=()=>{T()};window.addEventListener("pagehide",O);function _(){w.filter($=>$.status==="failed").forEach(J)}window.addEventListener("online",_),n.drafts!==!1&&(f.inert=!0,Va(S).then($=>{e.closed||!$||(l.innerHTML='<span>You have an unfinished report on this device.</span> <button type="button" data-resume>Resume report</button> <button type="button" data-discard>Discard</button>',l.querySelector("[data-resume]").onclick=()=>{c.value=$.title||"",p.value=$.description||"",g=fn.some(A=>A.value===$.priority)?$.priority:"MEDIUM",i.querySelectorAll("[data-prio]").forEach(A=>A.setAttribute("aria-pressed",String(A.dataset.prio===g)));for(const A of($.items||[]).slice(0,n.maxAttachments??5))te(A);y=!0,T()},l.querySelector("[data-discard]").onclick=()=>{y=!0,T()})}).catch(()=>{l.textContent="Draft storage is unavailable. Keep this tab open."}).finally(()=>{f.inert=e.mustRate(),l.querySelector("[data-resume]")||(y=!0)})),e.onDestroy(()=>{var $;T(),clearTimeout(k),window.removeEventListener("pagehide",O),window.removeEventListener("online",_),b==null||b.cancel(),w.forEach(A=>A.previewUrl&&URL.revokeObjectURL(A.previewUrl)),($=o.querySelector(".recbar"))==null||$.remove()}),i.querySelectorAll("[data-prio]").forEach($=>{$.addEventListener("click",()=>{g=$.dataset.prio,j(),i.querySelectorAll("[data-prio]").forEach(A=>{A.setAttribute("aria-pressed",String(A===$))})})});const Y=s("#bc-title-err");function L($){Y.hidden=!$,Y.innerHTML=$?`${se}<span>${E($)}</span>`:"",c.classList.toggle("invalid",!!$),c.setAttribute("aria-invalid",String(!!$))}c.addEventListener("input",()=>{c.value.trim()&&L("")});function D(){const $=w.some(P=>P.status==="uploading"),A=e.mustRate();u.disabled=e.sending||$||A||w.some(P=>P.status==="failed"),h.textContent=A?"Rate your last report to send a new one.":$?"Waiting for the upload to finish…":w.some(P=>P.status==="failed")?"Retry or remove failed attachments before sending.":"";const H=n.maxAttachments??5;i.querySelectorAll(".tool").forEach(P=>{P.disabled=e.sending||w.length>=H});const N=s(".field-head .count");N&&(N.textContent=w.length?`${w.length} of ${H}`:"")}e.refreshSendState=D;function R($){var ne;const A=$.el,H=$.kind==="VIDEO"?"Video":"Shot",N=$.kind==="VIDEO"?`<video src="${$.previewUrl}" muted playsinline preload="metadata"></video>`:`<img src="${$.previewUrl}" alt="" />`;let P="";$.status==="uploading"?P=`<div class="veil"><div class="spinner"></div><div class="bar"><i style="width:${Math.round($.progress*100)}%"></i></div></div>`:$.status==="failed"&&(P=`<div class="veil err"><button type="button" data-act="retry" aria-label="Retry upload">${ja}</button>Failed</div>`),A.innerHTML=`
|
|
1403
|
+
${N}
|
|
1404
|
+
<span class="kind">${H} · ${he($.size)}</span>
|
|
1405
|
+
<button class="drop" type="button" data-act="drop" aria-label="Remove ${H.toLowerCase()}">${ge}</button>
|
|
1406
|
+
${P}`,A.querySelector('[data-act="drop"]').addEventListener("click",()=>Q($)),(ne=A.querySelector('[data-act="retry"]'))==null||ne.addEventListener("click",()=>J($))}function Q($){const A=w.indexOf($);A>=0&&w.splice(A,1),$.previewUrl&&URL.revokeObjectURL($.previewUrl),$.el.remove(),T(),D()}async function J($){$.status="uploading",$.progress=0,R($),D();try{const{storageKey:A,mime:H}=await t.uploadAttachment($.blob,$.mime,N=>{$.progress=N;const P=$.el.querySelector(".bar i");P&&(P.style.width=`${Math.round(N*100)}%`)});$.storageKey=A,$.mime=H,$.status="ready"}catch(A){$.status="failed",d(A.message.replace("[BugCatch] ",""))}R($),D()}function te({blob:$,mime:A,kind:H}){const N=n.maxAttachmentBytes??26214400;if($.size>N){d(`That file is ${he($.size)} — the limit is ${he(N)}.`);return}const P=Ie(A||$.type,Ee);if(!P){d("Only PNG, JPEG, WebP, WebM and MP4 files can be attached to a report.");return}const ne={blob:$,kind:H,mime:P,size:$.size,previewUrl:URL.createObjectURL($),status:"uploading",progress:0,storageKey:null,el:document.createElement("div")};ne.el.className="thumb",w.push(ne),m.appendChild(ne.el),d(""),T(),J(ne)}async function le($){a.style.opacity="0",a.style.pointerEvents="none",await new Promise(A=>requestAnimationFrame(()=>requestAnimationFrame(A)));try{return await $()}finally{a.style.opacity="",a.style.pointerEvents=""}}(de=i.querySelector('[data-act="shot"]'))==null||de.addEventListener("click",async()=>{try{const $=await le(fo);te($)}catch($){($==null?void 0:$.name)!=="NotAllowedError"&&d(`Screenshot failed: ${$.message}`)}}),(ue=i.querySelector('[data-act="file"]'))==null||ue.addEventListener("click",()=>C.click()),C==null||C.addEventListener("change",()=>{const $=(n.maxAttachments??5)-w.length;[...C.files].slice(0,Math.max($,0)).forEach(A=>{te({blob:A,mime:A.type,kind:A.type.startsWith("video/")?"VIDEO":"SCREENSHOT"})}),C.value=""}),(z=i.querySelector('[data-act="rec"]'))==null||z.addEventListener("click",async()=>{const $=n.maxRecordingMs??12e4;let A;try{b=await go({maxMs:$,onTick:H=>{A&&(A.querySelector(".time").textContent=Le(H))},onAutoStop:()=>{b&&Z({keep:!0})}})}catch(H){(H==null?void 0:H.name)!=="NotAllowedError"&&d(`Recording failed: ${H.message}`);return}i.style.display="none",r.hidden=!0,A=document.createElement("div"),A.className="recbar",A.innerHTML=`
|
|
1309
1407
|
<span class="dot"></span>
|
|
1310
1408
|
<span class="time">0:00</span>
|
|
1311
|
-
<span class="hint">Recording — up to ${
|
|
1409
|
+
<span class="hint">Recording — up to ${Le(Math.round($/1e3))}</span>
|
|
1312
1410
|
<button class="stop" type="button">Stop</button>
|
|
1313
|
-
<button class="ghost" type="button">Discard</button>`,A.querySelector(".stop").addEventListener("click",()=>
|
|
1411
|
+
<button class="ghost" type="button">Discard</button>`,A.querySelector(".stop").addEventListener("click",()=>Z({keep:!0})),A.querySelector(".ghost").addEventListener("click",()=>Z({keep:!1})),o.appendChild(A),A.querySelector(".stop").focus()});async function Z({keep:$}){var H;const A=b;if(A){if(b=null,(H=o.querySelector(".recbar"))==null||H.remove(),i.style.display="",r.hidden=!1,!$){A.cancel(),c.focus();return}try{const N=await A.stop();N.blob.size?te(N):d("That recording came back empty — nothing was captured.")}catch(N){d(`Recording failed: ${N.message}`)}c.focus()}}e.isRecording=()=>!!b,e.stopRecording=Z,u.addEventListener("click",async()=>{var H;const $=c.value;if(!$.trim()){L("Add a few words about what went wrong — a short sentence is plenty."),c.focus();return}if(e.holdForReference())return;e.sending=!0,d(""),D();const A=u.innerHTML;u.innerHTML='<span class="spinner" aria-hidden="true"></span>Sending…';try{const N=await t.report({title:$,description:p.value,priority:g,references:e.answeredReference(),issue:((H=e.pickedIssue())==null?void 0:H.key)||null,attachments:w.filter(P=>P.status==="ready").map(P=>({type:P.kind,storageKey:P.storageKey,mime:P.mime}))});if(N!=null&&N.cancelled){e.sending=!1,u.innerHTML=A,D();return}x=!0,clearTimeout(k),await v,n.drafts!==!1&&await Qe(S,null).catch(()=>{}),e.succeed(N)}catch(N){e.sending=!1,u.innerHTML=A,d(N.message.replace("[BugCatch] ","")),D(),e.recheckSignIn()}})}function Ya(e){const{client:t,say:n,titleInput:o,descInput:a,sendBtn:r,refsBox:i}=e;let s={policy:"off",fields:[]},d=!1,c=null,p="",f="",u=[],h="ask",m=!1,C=!1;t.referenceFields().then(L=>{s=L,y()}).catch(()=>{});function w(){return s.policy==="off"||!s.fields.length?{found:[],conflicts:[],loose:[]}:oa(s.fields,[o.value,a.value])}function g(L=w()){return L.found.length>0&&L.conflicts.length===0}function b(){return!c||!p.trim()?[]:[{key:c,value:p.trim().slice(0,120)}]}const l=document.createElement("p");l.className="ref-found",l.setAttribute("aria-live","polite"),l.hidden=!0,a.closest(".field").after(l);let S;function y(){const L=w();if(g(L)){const D=L.found.slice(0,2).map(R=>`${E(R.label)} <b>${E(v(R.value))}</b>`).join(", ");l.innerHTML=`${oe}<span>Found your ${D} — no need to add it again.</span>`,l.hidden=!1,d&&!b().length&&(d=!1,j())}else l.hidden=!0,l.innerHTML=""}const x=()=>{clearTimeout(S),S=setTimeout(y,250)};o.addEventListener("input",x),a.addEventListener("input",x);function v(L){return L.length>20?`${L.slice(0,8)}…${L.slice(-4)}`:L}function k(L){const D=L.trim().toLowerCase();return u.find(R=>R.value.toLowerCase()===D)||null}function T(L){p=L.value,L.kinds.length===1?c=L.kinds[0].key:L.kinds.some(D=>D.key===c)||(c=null),f="",C=!1}function j(){var de,ue;if(!d){i.hidden=!0,i.innerHTML="";return}const L=s.fields.find(z=>z.key===c)||null,D=s.policy!=="required",R=k(p),Q=R&&R.kinds.length>1?s.fields.filter(z=>R.kinds.some($=>$.key===z.key)):s.fields,J=u.length>1&&u.every(z=>z.kinds.length===1&&z.kinds[0].key===u[0].kinds[0].key),te={confirm:u.length>1?["Which one is this about?","We found more than one ID in your message. Pick the one this problem is about."]:["Is this the right ID?","This could be more than one kind of ID. Tell us which it is."],suggest:["Is this your ID?","We spotted this in your message. Tell us what it is so we can find your record."],ask:D?["One more thing","So we can find your record — this helps us answer faster."]:["We need one detail","We need one of these to look this up."]}[h];i.hidden=!1;const le=Q.length>6;i.innerHTML=`
|
|
1314
1412
|
<div class="ask-head">
|
|
1315
|
-
<span class="avatar" aria-hidden="true"
|
|
1413
|
+
<span class="avatar orb" aria-hidden="true"></span>
|
|
1316
1414
|
<div>
|
|
1317
|
-
<strong>${E(
|
|
1318
|
-
<p class="why">${E(
|
|
1415
|
+
<strong>${E(te[0])}</strong>
|
|
1416
|
+
<p class="why">${E(te[1])}</p>
|
|
1319
1417
|
</div>
|
|
1320
1418
|
</div>
|
|
1321
1419
|
${u.length>1?`
|
|
1322
1420
|
<div class="chips cands" role="group" aria-label="IDs found in your message">
|
|
1323
1421
|
${u.map((z,$)=>`
|
|
1324
1422
|
<button type="button" data-ref-cand="${$}" title="${E(z.value)}"
|
|
1325
|
-
aria-pressed="${!!R&&R===z}">${E(
|
|
1423
|
+
aria-pressed="${!!R&&R===z}">${E(v(z.value))}</button>
|
|
1326
1424
|
`).join("")}
|
|
1327
1425
|
</div>`:""}
|
|
1328
|
-
${
|
|
1426
|
+
${Q.length>1&&!le&&!J?`
|
|
1329
1427
|
<div class="chips" role="group" aria-label="Which detail you are giving">
|
|
1330
|
-
${
|
|
1428
|
+
${Q.map(z=>`
|
|
1331
1429
|
<button type="button" data-ref-kind="${E(z.key)}" aria-pressed="${!!L&&z.key===L.key}">${E(z.label)}</button>
|
|
1332
1430
|
`).join("")}
|
|
1333
1431
|
</div>`:""}
|
|
1334
1432
|
<div class="row">
|
|
1335
|
-
${
|
|
1433
|
+
${le?`
|
|
1336
1434
|
<select class="ref-kind" aria-label="Which detail you are giving">
|
|
1337
1435
|
${L?"":'<option value="" selected disabled>What is it?</option>'}
|
|
1338
|
-
${
|
|
1436
|
+
${Q.map(z=>`
|
|
1339
1437
|
<option value="${E(z.key)}" ${L&&z.key===L.key?"selected":""}>${E(z.label)}</option>
|
|
1340
1438
|
`).join("")}
|
|
1341
1439
|
</select>`:""}
|
|
1342
|
-
<input class="ref-value${
|
|
1440
|
+
<input class="ref-value${f?" invalid":""}" type="${(L==null?void 0:L.inputMode)==="email"?"email":"text"}"
|
|
1343
1441
|
inputmode="${E((L==null?void 0:L.inputMode)==="numeric"||(L==null?void 0:L.inputMode)==="tel"?"numeric":"text")}"
|
|
1344
|
-
value="${E(
|
|
1442
|
+
value="${E(p)}"
|
|
1345
1443
|
placeholder="${E(L?L.placeholder||L.label:"Your ID")}"
|
|
1346
|
-
aria-label="${E(L?L.label:"Your ID")}" ${
|
|
1444
|
+
aria-label="${E(L?L.label:"Your ID")}" ${f?'aria-invalid="true"':""} />
|
|
1347
1445
|
</div>
|
|
1348
1446
|
${L!=null&&L.hint?`<p class="hint">${E(L.hint)}</p>`:""}
|
|
1349
|
-
${
|
|
1350
|
-
${
|
|
1447
|
+
${f?`<p class="field-err" role="alert">${se}<span>${E(f)}</span></p>`:""}
|
|
1448
|
+
${D?`<button type="button" class="link" data-act="ref-skip">${h==="ask"?"I don't have this — send without it":"Not sure — send as it is"}</button>`:""}`,i.querySelectorAll("[data-ref-cand]").forEach(z=>{z.addEventListener("click",()=>{T(u[Number(z.dataset.refCand)]),j()})}),i.querySelectorAll("[data-ref-kind]").forEach(z=>{z.addEventListener("click",()=>{c=z.dataset.refKind,f="",C=!1,j()})});const Z=i.querySelector(".ref-value");Z.addEventListener("input",()=>{p=Z.value,f="",C=!1}),Z.addEventListener("keydown",z=>{z.key==="Enter"&&(z.preventDefault(),r.click())}),(de=i.querySelector(".ref-kind"))==null||de.addEventListener("change",z=>{var $;c=z.target.value,f="",j(),($=i.querySelector(".ref-value"))==null||$.focus()}),(ue=i.querySelector('[data-act="ref-skip"]'))==null||ue.addEventListener("click",()=>{m=!0,d=!1,c=null,p="",f="",C=!1,j(),n("")}),((!L&&p?i.querySelector("[data-ref-kind], .ref-kind"):null)||Z).focus()}function O(L){if(u=L.conflicts.length?L.conflicts:L.loose.slice(0,4),h=L.conflicts.length?"confirm":L.loose.length?"suggest":"ask",d=!0,u.length)if(u.length===1)T(u[0]);else{p="";const[D]=u;c=u.every(Q=>Q.kinds.length===1&&Q.kinds[0].key===D.kinds[0].key)?D.kinds[0].key:null}else c=c||s.fields[0].key;j()}function _(){if(s.policy==="off"||!s.fields.length||b().length)return!1;const L=w();return g(L)||m&&s.policy!=="required"?!1:L}function Y(){if(d&&p.trim()&&!c)return f="Pick what this ID is.",j(),!0;const L=_();if(L)return d?j():O(L),n(""),!0;if(c&&p.trim()){const D=s.fields.find(R=>R.key===c);if(!C&&D&&!Yt(D,p))return f=`That does not look like a ${D.label.toLowerCase()}. Press Send again to use it anyway.`,C=!0,j(),!0}return!1}e.holdForReference=Y,e.answeredReference=b}const Xa=3;function Ja(e){const{client:t,cfg:n,notices:o}=e;let a=[];function r(){const s=a.slice(0,Xa);o.replaceChildren(...s.map(d=>Lt(d,{where:"panel",onDismiss:i}))),o.hidden=s.length===0}function i(s){t.dismissAnnouncement(s),a=a.filter(d=>d!==s),r(),e.titleInput.focus()}n.announcements!==!1&&typeof t.announcements=="function"&&t.announcements().then(s=>{e.closed||(a=s,r())}).catch(()=>{})}function Za(e){const{client:t,cfg:n,titleInput:o,known:a}=e;let r=[],i="",s=null,d=null;function c(){n.knownIssues!==!1&&t.knownIssues().then(m=>{r=m,u()}).catch(()=>{})}let p=null;function f(m){if(n.knownIssues===!1)return;clearTimeout(p),d==null||d.abort();const C=(m||"").trim();if(C.length<3){c();return}p=setTimeout(()=>{d=new AbortController,t.matchKnownIssues(C,{signal:d.signal}).then(w=>{w.length&&(r=w,u())}).catch(()=>{})},250)}function u(){if(!r.length){a.hidden=!0,a.innerHTML="";return}a.hidden=!1,a.innerHTML=`
|
|
1351
1449
|
<p class="known-h">Already reported</p>
|
|
1352
|
-
${r.map(
|
|
1353
|
-
<div class="issue ${
|
|
1450
|
+
${r.map(m=>`
|
|
1451
|
+
<div class="issue ${m.joined?"is-joined":""}">
|
|
1354
1452
|
<span class="who">
|
|
1355
|
-
<span class="t">${E(
|
|
1356
|
-
<span class="meta">${E(
|
|
1453
|
+
<span class="t">${E(m.title)}</span>
|
|
1454
|
+
<span class="meta">${E(h(m))}</span>
|
|
1357
1455
|
</span>
|
|
1358
|
-
<button class="join" type="button" data-join="${E(
|
|
1359
|
-
${
|
|
1456
|
+
<button class="join" type="button" data-join="${E(m.id)}"
|
|
1457
|
+
${m.joined?"disabled":""}>${m.joined?"Following":"Me too"}</button>
|
|
1360
1458
|
</div>
|
|
1361
|
-
${s===
|
|
1459
|
+
${s===m.id?`
|
|
1362
1460
|
<div class="ask">
|
|
1363
1461
|
<input type="email" class="join-email" placeholder="you@example.com"
|
|
1364
1462
|
aria-label="Your email, so we can tell you when this is fixed" />
|
|
1365
|
-
<button class="ghost" type="button" data-join-confirm="${E(
|
|
1463
|
+
<button class="ghost" type="button" data-join-confirm="${E(m.id)}">Follow</button>
|
|
1366
1464
|
</div>`:""}
|
|
1367
1465
|
`).join("")}
|
|
1368
|
-
${i?`<p class="err">${E(i)}</p>`:""}`}function
|
|
1466
|
+
${i?`<p class="err">${E(i)}</p>`:""}`}function h(m){const C=m.status==="IN_PROGRESS"?"Being worked on now":"Not fixed yet",w=m.affectedCount===0?"":` · ${m.affectedCount} ${m.affectedCount===1?"person has":"people have"} said this is happening to them`;return`${C} · reported ${Se(m.since)}${w}`}a.addEventListener("click",async m=>{var l,S,y,x,v;const C=m.target.closest("[data-join]"),w=m.target.closest("[data-join-confirm]");if(!C&&!w)return;const g=(w||C).getAttribute(w?"data-join-confirm":"data-join");i="";const b=((S=(l=a.querySelector(".join-email"))==null?void 0:l.value)==null?void 0:S.trim())||((y=t.signedInAs())==null?void 0:y.email)||((x=t.config.user)==null?void 0:x.email);if(!b){s=g,u(),(v=a.querySelector(".join-email"))==null||v.focus();return}try{const k=await t.meToo(g,{email:b});s=null,r=r.map(T=>T.id===g?{...T,joined:!0,affectedCount:k.affectedCount??T.affectedCount}:T),u()}catch(k){i=k.message.replace("[BugCatch] ",""),u()}}),c(),o.addEventListener("input",()=>f(o.value))}function Ga(e){const{client:t,cfg:n,titleInput:o,descInput:a,picks:r}=e;let i=[],s=null;function d(){if(!i.length){r.hidden=!0,r.innerHTML="";return}r.hidden=!1,r.innerHTML=`
|
|
1369
1467
|
<p class="picks-h">Get an answer right away</p>
|
|
1370
1468
|
<div class="picks-grid" role="group" aria-label="Common questions">
|
|
1371
|
-
${i.map(
|
|
1372
|
-
<button type="button" class="pick" data-pick="${E(
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1469
|
+
${i.map((c,p)=>`
|
|
1470
|
+
<button type="button" class="pick" data-pick="${E(c.key)}"
|
|
1471
|
+
${c.hint?`title="${E(c.hint)}" aria-describedby="bc-pick-h${p}"`:""}
|
|
1472
|
+
aria-pressed="${(s==null?void 0:s.key)===c.key}">
|
|
1473
|
+
<span class="t">${E(c.title)}</span>
|
|
1474
|
+
${c.hint?`<span class="h sr-only" id="bc-pick-h${p}">${E(c.hint)}</span>`:""}
|
|
1376
1475
|
</button>`).join("")}
|
|
1377
1476
|
</div>
|
|
1378
|
-
${s?`<p class="picks-note">${
|
|
1477
|
+
${s?`<p class="picks-note">${oe}<span>Our assistant will check your account and reply here. Add anything else below, then send.</span></p>`:""}`}r.addEventListener("click",c=>{const p=c.target.closest("[data-pick]");if(!p)return;const f=i.find(h=>h.key===p.dataset.pick);if(!f)return;const u=s&&o.value.trim()===s.title;(s==null?void 0:s.key)===f.key?(s=null,u&&(o.value="")):(s=f,(!o.value.trim()||u)&&(o.value=f.title)),o.dispatchEvent(new Event("input",{bubbles:!0})),d(),s&&a.focus()}),n.agentIssues!==!1&&typeof t.agentIssues=="function"&&t.agentIssues().then(c=>{i=c,d()}).catch(()=>{}),e.pickedIssue=()=>s}function er(e){const{client:t,scrim:n,say:o,callBtn:a,close:r}=e;let i=!1;function s(){t.callKind().then(p=>{p&&(i=!0,e.preloadCall(),a.hidden=e.mustSignIn()||e.mustRate())}).catch(()=>{})}s(),a.addEventListener("click",async()=>{e.sending=!0,o(""),e.refreshSendState(),a.disabled=!0,a.innerHTML='<span class="spinner"></span>Ringing…';try{const p=await t.startCall();d(p)}catch(p){e.sending=!1,a.disabled=!1,a.innerHTML=`${qe}Talk to the team`,e.refreshSendState(),p.filed?e.succeed(p.filed,{callFailed:p.reason||"The call could not be started."}):(o(p.message.replace("[BugCatch] ","")),e.recheckSignIn())}});function d(p){const f=n.querySelector(".panel"),u=p!=null&&p.bugId?String(p.bugId).slice(0,8):null;f.innerHTML=`
|
|
1379
1478
|
<div class="call">
|
|
1380
1479
|
<div class="call-head">
|
|
1381
1480
|
<span class="call-dot" aria-hidden="true"></span>
|
|
@@ -1388,126 +1487,151 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1388
1487
|
<span class="spacer"></span>
|
|
1389
1488
|
<button class="primary" type="button" data-act="hangup">Cancel</button>
|
|
1390
1489
|
</div>
|
|
1391
|
-
</div>`;const
|
|
1490
|
+
</div>`;const h=f.querySelector(".call-state"),m=f.querySelector(".call-dot"),C={ringing:"Ringing the team…",connecting:"Someone answered — connecting…",connected:"Connected",missed:"Nobody was free",ended:"Call ended",failed:"The call dropped"},w=["ended","failed","missed"],g=t.on("call",({state:b})=>{if(h.textContent=C[b]||b,m.classList.toggle("off",w.includes(b)),w.includes(b)&&(f.querySelector('[data-act="hangup"]').textContent="Close",b==="missed")){const l=f.querySelector(".call-note");l&&(l.textContent="Nobody was free to pick up just now. Your report is filed and the team will reply in the chat.")}});f.querySelector('[data-act="hangup"]').addEventListener("click",()=>{g(),t.endCall(),r()})}function c(p,f,u){const h=document.createElement("div");h.className="livecall",h.innerHTML=`
|
|
1392
1491
|
<span class="call-dot" aria-hidden="true"></span>
|
|
1393
1492
|
<span class="who" role="status" aria-live="polite">Calling the team…</span>
|
|
1394
1493
|
<span class="secs" hidden></span>
|
|
1395
1494
|
${u!=null&&u.recorded?'<span class="call-kept">This call is recorded.</span>':""}
|
|
1396
1495
|
<button class="act" type="button" data-act="mute" hidden>Mute</button>
|
|
1397
|
-
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,
|
|
1496
|
+
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,p.insertBefore(h,f);const m=h.querySelector(".who"),C=h.querySelector(".secs"),w=h.querySelector(".call-dot"),g=h.querySelector('[data-act="mute"]'),b=h.querySelector('[data-act="hangup"]');let l=null;const S=()=>{l&&(clearInterval(l),l=null)},y=v=>{S(),w.classList.add("off"),h.classList.add("over"),m.textContent=v,C.hidden=!0,g.hidden=!0,b.textContent="Dismiss",b.classList.remove("danger")},x=t.on("call",({state:v})=>{if(v==="ringing"&&(m.textContent="Calling the team…"),v==="connecting"&&(m.textContent="Someone answered — connecting…"),v==="connected"){m.textContent="You're on a call with the team",g.hidden=!1,C.hidden=!1;const k=Date.now();S(),l=setInterval(()=>{C.textContent=Le(Math.floor((Date.now()-k)/1e3))},1e3),C.textContent="0s"}v==="missed"&&y("Nobody was free. Send a message instead and the team will pick it up."),v==="ended"&&y("Call ended."),v==="failed"&&y("The call dropped.")});g.addEventListener("click",()=>{const v=u.setMuted(!u.isMuted());g.textContent=v?"Unmute":"Mute",m.textContent=v?"You're muted":"You're on a call with the team"}),b.addEventListener("click",()=>{x(),S(),t.endCall(),h.remove(),e.refreshThread(e.openReportId())})}e.offerCall=s,e.callOffered=()=>i,e.showLiveCall=c}function tr(e){var x;const{client:t,say:n,compose:o,sendBtn:a,historyBtn:r,callBtn:i,whoami:s}=e;let d={mode:t.lastLoginMode||"off",signedIn:null},c="idle",p=((x=t.config.user)==null?void 0:x.email)||"",f="",u=!1,h="";const m=()=>d.mode==="required"&&!d.signedIn;function C(){const v=m();o.hidden=v,a.hidden=v,r&&(r.hidden=v),v?i.hidden=!0:e.callOffered()&&!e.mustRate()&&(i.hidden=!1)}function w(){var k;if(d.mode==="off"){s.hidden=!0,s.innerHTML="";return}s.hidden=!1,s.classList.toggle("asking",c!=="idle");const v=h?`<div class="after err">${E(h)}</div>`:"";if(c==="idle"){if(d.signedIn){s.innerHTML=`<span class="who">Signed in as <strong>${E(d.signedIn.email)}</strong></span><button type="button" class="link" data-act="signout">Sign out</button>`;return}const T=(k=t.config.user)==null?void 0:k.email;s.innerHTML=`<span class="who">${d.mode==="required"?"Sign in to report a bug here.":T?`Reporting as <strong>${E(T)}</strong>.`:"Reporting anonymously — sign in and we can tell you what happens next."}</span><button type="button" class="link" data-act="signin">Sign in</button>`;return}if(c==="email"){s.innerHTML=`
|
|
1398
1497
|
<p class="why">Sign in with any email address — we'll send you a code.
|
|
1399
|
-
It's how you hear back about this report${
|
|
1498
|
+
It's how you hear back about this report${d.mode==="required"?", and this project asks for it":""}.</p>
|
|
1400
1499
|
<div class="row">
|
|
1401
|
-
<input type="email" data-fld="email" value="${E(
|
|
1500
|
+
<input type="email" data-fld="email" value="${E(p)}"
|
|
1402
1501
|
placeholder="you@example.com" autocomplete="email" spellcheck="false"
|
|
1403
1502
|
aria-label="Your email address" ${u?"disabled":""} />
|
|
1404
1503
|
<button type="button" class="primary" data-act="code" ${u?"disabled":""}>
|
|
1405
1504
|
${u?"Sending…":"Send code"}
|
|
1406
1505
|
</button>
|
|
1407
1506
|
</div>
|
|
1408
|
-
${
|
|
1409
|
-
${
|
|
1410
|
-
<p class="why">We sent a code to <strong>${E(
|
|
1507
|
+
${v}
|
|
1508
|
+
${d.mode==="optional"?'<div class="after"><button type="button" class="link" data-act="skip">Not now</button></div>':""}`;return}s.innerHTML=`
|
|
1509
|
+
<p class="why">We sent a code to <strong>${E(p)}</strong>. It expires in ten minutes.</p>
|
|
1411
1510
|
<div class="row">
|
|
1412
|
-
<input type="text" class="code" data-fld="code" value="${E(
|
|
1511
|
+
<input type="text" class="code" data-fld="code" value="${E(f)}"
|
|
1413
1512
|
placeholder="123456" inputmode="numeric" autocomplete="one-time-code"
|
|
1414
1513
|
maxlength="8" aria-label="The code we emailed you" ${u?"disabled":""} />
|
|
1415
1514
|
<button type="button" class="primary" data-act="confirm" ${u?"disabled":""}>
|
|
1416
1515
|
${u?"Checking…":"Sign in"}
|
|
1417
1516
|
</button>
|
|
1418
1517
|
</div>
|
|
1419
|
-
${
|
|
1518
|
+
${v}
|
|
1420
1519
|
<div class="after">
|
|
1421
1520
|
<button type="button" class="link" data-act="resend" ${u?"disabled":""}>Send it again</button>
|
|
1422
1521
|
<button type="button" class="link" data-act="signin-back" ${u?"disabled":""}>Use another address</button>
|
|
1423
|
-
</div>`}function
|
|
1424
|
-
<div class="sys k-${E(
|
|
1425
|
-
<span class="dot" aria-hidden="true"></span>${E(
|
|
1426
|
-
<span class="t">· ${E(
|
|
1427
|
-
</div>`}function
|
|
1428
|
-
<button type="button" data-quick="Yes, this is the problem">${
|
|
1522
|
+
</div>`}function g({focus:v=!1}={}){var T;if(w(),C(),!v||u)return;const k=s.querySelector("[data-fld]");k&&(k.focus(),(T=k.setSelectionRange)==null||T.call(k,k.value.length,k.value.length))}s.addEventListener("input",v=>{const k=v.target.closest("[data-fld]");k&&(k.dataset.fld==="email"?p=k.value:f=k.value)}),s.addEventListener("keydown",v=>{v.key!=="Enter"||!v.target.closest("[data-fld]")||(v.preventDefault(),c==="email"?b():l())});async function b({resent:v=!1}={}){const k=p.trim();if(!k){h="Enter the address to send the code to.",g({focus:!0});return}u=!0,h="",g();try{await t.signIn(k),p=k,v||(f=""),c="code"}catch(T){h=T.message}finally{u=!1,g({focus:!0})}}async function l(){const v=f.trim();if(!v){h="Enter the code we emailed you.",g({focus:!0});return}u=!0,h="",g();try{const k=await t.confirmSignIn(p.trim(),v);d.signedIn=k,c="idle",f="",n(""),e.offerCall()}catch(k){h=k.message}finally{u=!1,g({focus:c!=="idle"})}}s.addEventListener("click",async v=>{const k=v.target.closest("button[data-act]");if(!k)return;const T=k.dataset.act;if(T==="signin"){c="email",h="",g({focus:!0});return}if(T==="skip"){c="idle",h="",g();return}if(T==="signin-back"){c="email",h="",f="",g({focus:!0});return}if(T==="code"){b();return}if(T==="resend"){b({resent:!0});return}if(T==="confirm"){l();return}if(T==="signout"){u=!0,g();try{await t.signOut()}finally{d.signedIn=null,u=!1,c=d.mode==="required"?"email":"idle",g({focus:c!=="idle"})}}});async function S({announce:v=!1}={}){const k=await t.loginState();d={mode:k.mode,signedIn:k.signedIn},t.lastLoginMode=k.mode,m()&&c==="idle"&&(c="email"),d.signedIn&&(c="idle"),v&&k.signedOutReason&&n(k.signedOutReason,"info"),g()}S({announce:!0}).catch(()=>{});function y(){d.mode!=="off"&&S().catch(()=>{})}e.mustSignIn=m,e.recheckSignIn=y}function bn(e){const t=e||[];if(!t.length)return"";let n=null,o=null;return t.map(a=>{var p,f,u,h;const r=xe(a.at),i=r&&r!==n?`<div class="day-sep" role="separator">${E(Ua(a.at))}</div>`:"";if(i&&(n=r,o=null),!a.from)return o=null,i+or(a);const s={from:a.from,author:(p=a.reply)==null?void 0:p.author,automated:(f=a.reply)==null?void 0:f.automated,body:(u=a.reply)==null?void 0:u.body,at:a.at,attachments:(h=a.reply)==null?void 0:h.attachments},d=nr(s),c=o&&o.who===d&&Math.abs(new Date(a.at).getTime()-new Date(o.at).getTime())<5*6e4;return o={who:d,at:a.at},i+mn(s,c?"cont":"")}).join("")}function nr(e){return e.from==="reporter"?"me":e.automated?"assistant":`team:${e.author||""}`}function or(e){const t=pn(e.at);return`
|
|
1523
|
+
<div class="sys k-${E(e.kind)}">
|
|
1524
|
+
<span class="dot" aria-hidden="true"></span>${E(e.summary||"")}${t?`
|
|
1525
|
+
<span class="t">· ${E(t)}</span>`:""}
|
|
1526
|
+
</div>`}function mn(e,t=""){const n=e.from==="reporter",o=e.body||"",a=e.attachments||[],r=!n&&!!e.automated,i=o?`<span class="msg-text">${E(o)}</span>`:"",s=a.length?`<div class="att">${a.map(rr).join("")}</div>`:"";let d="",c="";if(r)d='<span class="msg-who auto">Assistant <span class="tag">AI</span></span>',c='<span class="av bot orb" aria-hidden="true"></span>';else if(!n){const f=e.author||"Support team";d=`<span class="msg-who">${E(f)}</span>`,c=`<span class="av" aria-hidden="true">${E(Na(f))}</span>`}t.includes("cont")&&(d="");const p=r&&/it goes to the same person/i.test(o)?`<div class="quick" role="group" aria-label="Answer">
|
|
1527
|
+
<button type="button" data-quick="Yes, this is the problem">${oe}That's right</button>
|
|
1429
1528
|
<button type="button" data-quick="No, that is not the problem">That's not it</button>
|
|
1430
|
-
</div>`:r&&
|
|
1431
|
-
<button type="button" data-quick="Yes, that answers it">${
|
|
1529
|
+
</div>`:r&&ra.test(o)?`<div class="quick" role="group" aria-label="Did this answer your question?">
|
|
1530
|
+
<button type="button" data-quick="Yes, that answers it">${oe}Yes, that answers it</button>
|
|
1432
1531
|
<button type="button" data-quick="No, I still need help">No, I still need help</button>
|
|
1433
1532
|
</div>`:"";return`
|
|
1434
|
-
<div class="msg-row ${n?"mine":"theirs"} ${r?"auto":""} ${
|
|
1435
|
-
${l}
|
|
1533
|
+
<div class="msg-row ${n?"mine":"theirs"} ${r?"auto":""} ${t}">
|
|
1436
1534
|
${c}
|
|
1535
|
+
${d}
|
|
1437
1536
|
<div class="bubble ${o?"":"silent"}">${i}${s}</div>
|
|
1438
|
-
${
|
|
1439
|
-
<span class="msg-when">${E(
|
|
1440
|
-
</div>`}function
|
|
1537
|
+
${p}
|
|
1538
|
+
<span class="msg-when">${E(pn(e.at)||Se(e.at))}</span>
|
|
1539
|
+
</div>`}function ar(){return`
|
|
1441
1540
|
<div class="typing-row">
|
|
1442
|
-
<span class="av bot" aria-hidden="true"
|
|
1541
|
+
<span class="av bot orb" aria-hidden="true"></span>
|
|
1443
1542
|
<span class="msg-who auto">Assistant <span class="tag">AI</span></span>
|
|
1444
1543
|
<div class="bubble typing" role="img" aria-label="The assistant is working on it"><i></i><i></i><i></i></div>
|
|
1445
|
-
</div>`}function
|
|
1544
|
+
</div>`}function rr(e){const t=E(e.name||"attachment");if(!e.url)return`<span class="file"><span class="nm">${t}</span></span>`;const n=E(e.url);return e.type==="SCREENSHOT"?`<a href="${n}" target="_blank" rel="noopener noreferrer"><img src="${n}" alt="${t}" loading="lazy"></a>`:e.type==="AUDIO"?`<audio controls preload="metadata" src="${n}"></audio>`:e.type==="VIDEO"?`<video controls preload="metadata" src="${n}"></video>`:`
|
|
1446
1545
|
<a class="file" href="${n}" target="_blank" rel="noopener noreferrer" download>
|
|
1447
|
-
<span class="nm">${
|
|
1448
|
-
${
|
|
1449
|
-
</a>`}function
|
|
1546
|
+
<span class="nm">${t}</span>
|
|
1547
|
+
${e.size?`<span class="sz">${E(he(e.size))}</span>`:""}
|
|
1548
|
+
</a>`}function ir(e,t,n,o){var y;const{client:a,cfg:r}=e,i=document.createElement("div");i.className="composer",i.innerHTML=`
|
|
1450
1549
|
<div class="staged" hidden></div>
|
|
1451
1550
|
<div class="row">
|
|
1452
1551
|
<div class="tools">
|
|
1453
1552
|
${r.attachments===!1?"":`
|
|
1454
|
-
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${
|
|
1455
|
-
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${
|
|
1456
|
-
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${
|
|
1553
|
+
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${cn}</button>
|
|
1554
|
+
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${ln}</button>`}
|
|
1555
|
+
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${qe}</button>
|
|
1457
1556
|
</div>
|
|
1458
1557
|
<textarea rows="1" placeholder="Write a reply…" aria-label="Write a reply"></textarea>
|
|
1459
|
-
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${
|
|
1558
|
+
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${dn}</button>
|
|
1460
1559
|
</div>
|
|
1461
1560
|
<div class="note" hidden></div>
|
|
1462
|
-
<input type="file" hidden multiple accept="${
|
|
1463
|
-
<span class="chip ${
|
|
1464
|
-
<span class="nm">${E(
|
|
1465
|
-
<span class="sz">${
|
|
1466
|
-
<button type="button" data-drop="${
|
|
1467
|
-
</span>`).join("");for(const
|
|
1561
|
+
<input type="file" hidden multiple accept="${Ot.join(",")}">`,t.appendChild(i);const s=i.querySelector(".staged"),d=i.querySelector("textarea"),c=i.querySelector('[data-act="send"]'),p=i.querySelector('[data-act="voice"]'),f=i.querySelector('[data-act="livecall"]'),u=i.querySelector("input[type=file]"),h=i.querySelector(".note"),m=[];let C=null,w=!1;function g(x,v=""){h.hidden=!x,h.className=`note ${v}`,h.textContent=x||""}function b(){const x=m.filter(v=>v.storageKey);c.disabled=w||!d.value.trim()&&!x.length,s.hidden=!m.length,s.innerHTML=m.map((v,k)=>`
|
|
1562
|
+
<span class="chip ${v.storageKey?"":"uploading"}">
|
|
1563
|
+
<span class="nm">${E(v.name)}</span>
|
|
1564
|
+
<span class="sz">${v.storageKey?he(v.size):"sending…"}</span>
|
|
1565
|
+
<button type="button" data-drop="${k}" aria-label="Remove ${E(v.name)}">${ge}</button>
|
|
1566
|
+
</span>`).join("");for(const v of s.querySelectorAll("[data-drop]"))v.addEventListener("click",()=>{m.splice(Number(v.dataset.drop),1),b()})}async function l(x,v,k){const T={name:k,size:x.size,storageKey:null};m.push(T),b();try{const{storageKey:j,mime:O}=await a.uploadAttachment(x,v);T.storageKey=j,T.mime=O}catch(j){m.splice(m.indexOf(T),1),g(j.message||"That file could not be sent.","err")}b()}d.addEventListener("input",()=>{d.style.height="auto",d.style.height=`${Math.min(d.scrollHeight,120)}px`,b()}),d.addEventListener("keydown",x=>{x.key==="Enter"&&!x.shiftKey&&!x.isComposing&&(x.preventDefault(),S())}),(y=i.querySelector('[data-act="attach"]'))==null||y.addEventListener("click",()=>u.click()),u.addEventListener("change",()=>{g("");for(const x of u.files){if(x.size>a.config.maxAttachmentBytes){g(`${x.name} is larger than ${he(a.config.maxAttachmentBytes)}.`,"err");continue}l(x,x.type,x.name)}u.value=""}),p&&!uo()&&(p.disabled=!0,p.title="This browser cannot record audio"),p==null||p.addEventListener("click",async()=>{if(C){const x=C;C=null,p.classList.remove("recording"),p.innerHTML=ln,g("");const{blob:v,mime:k}=await x.stop();v.size&&l(v,k,"Voice note");return}try{g(""),C=await bo({maxMs:a.config.maxRecordingMs,onTick:x=>g(`Recording — ${Le(x)}. Tap the mic to stop.`),onAutoStop:()=>p.click()}),p.classList.add("recording"),p.innerHTML=Ba}catch{C=null,g("The microphone is not available — check the browser permission.","err")}}),a.canCallTeam(o).then(x=>{x&&(f.hidden=!1,e.preloadCall())}).catch(()=>{}),f.addEventListener("click",async()=>{f.disabled=!0,g("");try{const x=await a.startLiveCall(o);e.showLiveCall(t,n,x)}catch(x){g(x.message.replace("[BugCatch] ",""),"err")}finally{f.disabled=!1}}),c.addEventListener("click",S),n.addEventListener("click",x=>{var k,T;const v=(T=(k=x.target).closest)==null?void 0:T.call(k,"[data-quick]");!v||w||(d.value=v.dataset.quick,S())});async function S(){var k;const x=d.value.trim(),v=m.filter(T=>T.storageKey);if(!(w||!x&&!v.length)){w=!0,b(),g(""),n.insertAdjacentHTML("beforeend",mn({from:"reporter",body:x,at:new Date().toISOString(),attachments:v.map(T=>({type:"FILE",name:T.name,size:T.size}))},"pending")),ke(n,{smooth:!0});try{await a.replyToReport(o,{body:x,attachments:v.map(T=>({storageKey:T.storageKey,mime:T.mime,name:T.name,size:T.size}))}),d.value="",d.style.height="auto",m.length=0,await e.refreshThread(o)}catch(T){(k=n.querySelector(".msg-row.pending"))==null||k.classList.replace("pending","failed"),g(T.message||"That could not be sent — try again.","err")}finally{w=!1,b()}}}b()}function yn(e){return JSON.stringify(e?[e.score,e.current,e.comment||null]:null)}function dt(e,{client:t,report:n,rating:o,justRated:a=!1,question:r=null,onRated:i=null,onError:s=null}){var w;e.dataset.key=yn(o);const d=o!=null&&o.current?o.score:0,c=o?o.current?a?"Thanks — the team will see that.":`You rated this ${o.score} out of 5.`:`You rated an earlier fix ${o.score} out of 5. How did this one go?`:r||"How did we do?",p=a&&(o==null?void 0:o.current)&&!o.comment;e.innerHTML=`
|
|
1567
|
+
<p class="fr-q">${E(c)}</p>
|
|
1568
|
+
<div class="stars" role="group" aria-label="Rate how this was handled, 1 to 5">${[1,2,3,4,5].map(g=>`
|
|
1569
|
+
<button type="button" data-score="${g}" aria-pressed="${g===d}" aria-label="${g} out of 5${g===1?", poor":g===5?", great":""}" class="${g<=d?"on":""}">${un}</button>`).join("")}
|
|
1570
|
+
</div>
|
|
1571
|
+
${o!=null&&o.current&&o.comment?`<p class="fr-said">“${E(o.comment)}”</p>`:""}
|
|
1572
|
+
${p?`
|
|
1573
|
+
<div class="fr-note">
|
|
1574
|
+
<textarea maxlength="2000" aria-label="Add a note to your rating" placeholder="${o.score<=2?"What went wrong? (optional)":"Anything to add? (optional)"}"></textarea>
|
|
1575
|
+
<button type="button" data-act="rating-note">Add note</button>
|
|
1576
|
+
</div>`:""}
|
|
1577
|
+
${o?"":'<p class="fr-hint">1 is poor, 5 is great.</p>'}
|
|
1578
|
+
<p class="feedback-status" role="status"></p>`;const f=[...e.querySelectorAll("[data-score]")],u=g=>f.forEach(b=>b.classList.toggle("on",Number(b.dataset.score)<=g)),h=g=>e.querySelectorAll("button, textarea").forEach(b=>{b.disabled=g}),m=e.querySelector(".feedback-status");async function C(g,b){var l;h(!0),m.textContent="";try{const S=await t.rate(n.id,{score:g,comment:b});dt(e,{client:t,report:n,rating:S,justRated:!0,question:r,onRated:i,onError:s}),(l=e.querySelector(".fr-note textarea"))==null||l.focus(),i==null||i(S)}catch(S){m.textContent=S.message,h(!1),u(d),s==null||s(S)}}for(const g of f){const b=Number(g.dataset.score);g.addEventListener("mouseenter",()=>u(b)),g.addEventListener("focus",()=>u(b)),g.addEventListener("blur",()=>u(d)),g.addEventListener("click",()=>C(b))}e.querySelector(".stars").addEventListener("mouseleave",()=>u(d)),(w=e.querySelector('[data-act="rating-note"]'))==null||w.addEventListener("click",()=>{var b;const g=e.querySelector(".fr-note textarea").value.trim();if(!g){(b=e.querySelector(".fr-note"))==null||b.remove();return}C(o.score,g)})}const ut=new WeakMap;function sr(e){return e.rating?` · <span class="rated" aria-label="You rated this ${Number(e.rating)} out of 5">${un}${Number(e.rating)}</span>`:e.ratingAsked?' · <span class="rate-ask">Rate it</span>':""}function cr(e){var C;const{client:t,scrim:n,close:o}=e;let a=null;function r(w,{callFailed:g=null}={}){if(w!=null&&w.id&&!g){d(w.id,{fresh:!0}).then(b=>{b||i(w,{callFailed:g})});return}i(w,{callFailed:g})}function i(w,{callFailed:g=null}={}){var y;const b=w!=null&&w.id?String(w.id).slice(0,8):null,l=(y=w==null?void 0:w.estimate)!=null&&y.label?String(w.estimate.label):null,S=g?`<p class="eta">${E(g)} Your report is filed, and the team will reply in the chat.</p>`:"";n.querySelector(".panel").innerHTML=`
|
|
1468
1579
|
<div class="done">
|
|
1469
|
-
<div class="tick">${
|
|
1580
|
+
<div class="tick">${oe}</div>
|
|
1470
1581
|
<h3>Thanks — that's on its way.</h3>
|
|
1471
|
-
<p>${
|
|
1472
|
-
${
|
|
1473
|
-
${
|
|
1474
|
-
</div>`,setTimeout(o,
|
|
1475
|
-
${
|
|
1476
|
-
<div class="history" aria-busy="true">${
|
|
1477
|
-
<button class="row" type="button" data-report="${E(
|
|
1478
|
-
<span class="row-ico" aria-hidden="true">${
|
|
1582
|
+
<p>${b?`Filed as <code>${E(b)}</code>.`:"The team has what they need to reproduce it."}</p>
|
|
1583
|
+
${S}
|
|
1584
|
+
${l?`<p class="eta">Reports like this usually take <strong>${E(l)}</strong>. We'll let you know when it moves.</p>`:""}
|
|
1585
|
+
</div>`,setTimeout(o,S?6e3:l?4e3:2e3)}async function s(){const w=n.querySelector(".panel");clearTimeout(c),a=null,w.classList.remove("is-chat"),w.innerHTML=`
|
|
1586
|
+
${st({title:"Your reports",sub:"Where each one has got to.",theme:e.themeLabel()})}
|
|
1587
|
+
<div class="history" aria-busy="true">${Qa(3)}</div>`,w.querySelector('[data-act="close"]').addEventListener("click",o);let g=[];try{({reports:g}=await t.myReports())}catch{const l=w.querySelector(".history");l&&(l.innerHTML=ct("Couldn't load your reports just now.",se));return}const b=w.querySelector(".history");if(b){b.removeAttribute("aria-busy"),b.innerHTML=g.length?g.map((l,S)=>`
|
|
1588
|
+
<button class="row" type="button" data-report="${E(l.id)}" style="animation-delay:${Math.min(S,8)*30}ms">
|
|
1589
|
+
<span class="row-ico" aria-hidden="true">${Xn}</span>
|
|
1479
1590
|
<span class="who">
|
|
1480
|
-
<span class="ttl">${E(
|
|
1481
|
-
<span class="sub">${E(
|
|
1591
|
+
<span class="ttl">${E(l.title)}</span>
|
|
1592
|
+
<span class="sub">${E(l.reference)} · ${E(Se(l.createdAt))}${sr(l)}</span>
|
|
1482
1593
|
</span>
|
|
1483
|
-
<span class="pill ${E(String(
|
|
1484
|
-
<span class="chev" aria-hidden="true">${
|
|
1485
|
-
</button>`).join(""):
|
|
1486
|
-
${
|
|
1487
|
-
<div class="history chatting" aria-busy="true"><div class="thread">${
|
|
1594
|
+
<span class="pill ${E(String(l.status).toLowerCase())}">${E(lt(l.status))}</span>
|
|
1595
|
+
<span class="chev" aria-hidden="true">${Oa}</span>
|
|
1596
|
+
</button>`).join(""):ct("You haven't reported anything yet.",za);for(const l of b.querySelectorAll("[data-report]"))l.addEventListener("click",()=>d(l.dataset.report))}}async function d(w,{fresh:g=!1}={}){var v;const b=n.querySelector(".panel");clearTimeout(c),b.classList.add("is-chat"),b.innerHTML=`
|
|
1597
|
+
${st({back:!0,title:g?"Looking into it":"Your report",sub:g?"It may ask you a question here.":"Updates, and a way to reply.",theme:e.themeLabel()})}
|
|
1598
|
+
<div class="history chatting" aria-busy="true"><div class="thread">${Ha()}</div></div>`,b.querySelector('[data-act="close"]').addEventListener("click",o),b.querySelector('[data-act="back"]').addEventListener("click",s);let l=null;try{l=await t.myReport(w)}catch{l=null}const S=b.querySelector(".history");if(!S||!b.querySelector('[data-act="back"]'))return!1;if(!l)return g?(b.classList.remove("is-chat"),!1):(S.removeAttribute("aria-busy"),S.innerHTML=ct("Couldn't load that report just now.",se),!1);a=w,t.markReportRead(w);const y=bn(l.timeline);S.classList.add("chatting"),S.removeAttribute("aria-busy"),S.innerHTML=`
|
|
1488
1599
|
<div class="report-head">
|
|
1489
|
-
<span class="ttl">${E(
|
|
1490
|
-
<span class="sub">${E(
|
|
1491
|
-
<span class="pill ${E(String(
|
|
1492
|
-
${(
|
|
1600
|
+
<span class="ttl">${E(l.title)}</span>
|
|
1601
|
+
<span class="sub">${E(l.reference)} · ${E(l.project||"")}</span>
|
|
1602
|
+
<span class="pill ${E(String(l.status).toLowerCase())}">${E(lt(l.status))}</span>
|
|
1603
|
+
${(v=l.estimate)!=null&&v.label?`<span class="eta-line">Usually takes ${E(String(l.estimate.label))}</span>`:""}
|
|
1493
1604
|
</div>
|
|
1494
|
-
<div class="thread" role="log" aria-live="polite" aria-label="Conversation">${
|
|
1495
|
-
<div class="as-body${
|
|
1605
|
+
<div class="thread" role="log" aria-live="polite" aria-label="Conversation">${y}</div>`;const x=S.querySelector(".thread");return ut.set(x,y),ke(x),f(S,l),u(S,l),l.canReply&&ir(e,S,x,w),p(S,l,w),ke(x),!0}let c=null;function p(w,g,b){var Y,L,D;clearTimeout(c);const l=g.assistant,S=w.querySelector(".thread");let y=w.querySelector(".assistant");if(!l){y==null||y.remove(),(Y=S==null?void 0:S.querySelector(".typing-row"))==null||Y.remove();return}const x=(y==null?void 0:y.dataset.phase)||null;y||(y=document.createElement("div"),y.setAttribute("role","status"),y.setAttribute("aria-live","polite"),(L=w.querySelector(".report-head"))==null||L.after(y)),y.className=`assistant ${E(l.phase)}`,y.dataset.phase=l.phase;const v=l.steps||[],k=v.filter(R=>R.state==="done").length,T=v.some(R=>R.state==="active")?.5:0,j=v.length?Math.round((k+T)/v.length*100):0,O=`
|
|
1606
|
+
<div class="as-body${x&&x!==l.phase?" entering":""}">
|
|
1496
1607
|
<div class="as-top">
|
|
1497
|
-
<span class="as-orb"
|
|
1608
|
+
<span class="as-orb${l.phase==="calling"||l.phase==="resolved"?"":" orb"}" aria-hidden="true">${l.phase==="calling"?qe:l.phase==="resolved"?oe:""}</span>
|
|
1498
1609
|
<div class="as-text">
|
|
1499
|
-
<div class="as-title">${E(
|
|
1500
|
-
<div class="as-detail">${E(
|
|
1610
|
+
<div class="as-title">${E(l.title)}</div>
|
|
1611
|
+
<div class="as-detail">${E(l.detail)}</div>
|
|
1501
1612
|
</div>
|
|
1502
1613
|
</div>
|
|
1503
1614
|
</div>
|
|
1504
|
-
${
|
|
1505
|
-
<div class="as-progress" role="progressbar" aria-label="Progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${
|
|
1506
|
-
<ol class="as-steps">${
|
|
1615
|
+
${v.length?`
|
|
1616
|
+
<div class="as-progress" role="progressbar" aria-label="Progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${j}"><i style="width:${j}%"></i></div>
|
|
1617
|
+
<ol class="as-steps">${v.map(R=>`<li class="${E(R.state)}"${R.state==="active"?' aria-current="step"':""}><span class="dot"></span><span class="lbl">${E(R.label)}</span></li>`).join("")}</ol>`:""}`,_=JSON.stringify([l.phase,l.title,l.detail,v]);if(y.dataset.key!==_){const R=y.querySelector(".as-progress i"),Q=R==null?void 0:R.style.width;y.innerHTML=O,y.dataset.key=_;const J=y.querySelector(".as-progress i");J&&Q&&(J.style.width=Q,requestAnimationFrame(()=>{J.style.width=`${j}%`}))}if(S){const R=hn(S),Q=S.querySelector(".typing-row");l.phase!=="analyzing"?Q==null||Q.remove():(!Q||Q!==S.lastElementChild)&&(Q==null||Q.remove(),S.insertAdjacentHTML("beforeend",ar()),R&&ke(S))}l.phase==="analyzing"?c=setTimeout(()=>h(b),3e3):l.phase==="calling"?c=setTimeout(()=>h(b),1e4):l.phase==="needs_info"&&x!=="needs_info"&&((D=w.querySelector(".composer textarea"))==null||D.focus())}function f(w,g){var l,S;if((l=w.querySelector(".fix-verification"))==null||l.remove(),!g.resolvedAt||!["RESOLVED","CLOSED"].includes(g.status))return;const b=document.createElement("div");b.className="fix-verification",g.verification?b.textContent=g.verification==="CONFIRMED"?"You confirmed that this fix works.":"Your feedback was recorded.":(b.innerHTML='<p>Does the fix work for you?</p><textarea maxlength="4000" aria-label="Fix feedback" placeholder="What happens when you try again? (optional)"></textarea><button type="button" data-result="CONFIRMED">It works now</button> <button type="button" data-result="STILL_HAPPENING">Still happening</button><p class="feedback-status" role="status"></p>',b.querySelectorAll("[data-result]").forEach(y=>{y.onclick=async()=>{b.querySelectorAll("button").forEach(x=>{x.disabled=!0});try{await t.verifyFix(g.id,{result:y.dataset.result,resolvedAt:g.resolvedAt,note:b.querySelector("textarea").value}),await d(g.id)}catch(x){b.querySelector(".feedback-status").textContent=x.message,b.querySelectorAll("button").forEach(v=>{v.disabled=!1})}}})),(S=w.querySelector(".report-head"))==null||S.after(b)}function u(w,g){var S;let b=w.querySelector(".fix-rating");if(!["RESOLVED","CLOSED"].includes(g.status)||!g.ratingAsked){b==null||b.remove();return}b&&b.dataset.key===yn(g.rating)||(b||(b=document.createElement("div"),b.className="fix-rating",(S=w.querySelector(".fix-verification")||w.querySelector(".report-head"))==null||S.after(b)),dt(b,{client:t,report:g,rating:g.rating||null}))}async function h(w){const g=n.querySelector(".history.chatting"),b=g==null?void 0:g.querySelector(".thread");if(!b||a!==w)return;let l=null;try{l=await t.myReport(w)}catch{}if(e.closed||!l||a!==w)return;f(g,l),u(g,l);const S=hn(b),y=bn(l.timeline);ut.get(b)!==y&&(b.innerHTML=y,ut.set(b,y)),p(g,l,w),S&&ke(b);const x=g.querySelector(".report-head .pill");x&&(x.className=`pill ${String(l.status).toLowerCase()}`,x.textContent=lt(l.status))}const m=t.on("update",w=>{!a||(w==null?void 0:w.bugId)!==a||(t.markReportRead(a),h(a))});e.onDestroy(()=>{m(),clearTimeout(c)}),(C=n.querySelector('[data-act="history"]'))==null||C.addEventListener("click",s),e.succeed=r,e.refreshThread=h,e.openReportId=()=>a}const wn="bugcatch.rateLater",lr=50;function vn(){try{const e=JSON.parse(window.localStorage.getItem(wn)||"[]");return Array.isArray(e)?e:[]}catch{return[]}}function dr(e){try{const t=vn().filter(n=>n!==e);t.push(e),window.localStorage.setItem(wn,JSON.stringify(t.slice(-lr)))}catch{}}function ur(e,t=vn()){const n=new Set(t),o=(e||[]).filter(r=>r.ratingDue==="require"||r.ratingDue==="ask"&&!n.has(r.id));if(!o.length)return null;const a=r=>new Date(r.resolvedAt||r.updatedAt||0).getTime()||0;return o.reduce((r,i)=>a(i)>a(r)?i:r)}function pr(e){const{client:t,rateDue:n,compose:o,picks:a,known:r,callBtn:i,titleInput:s,scrim:d}=e;let c=!1;e.mustRate=()=>c;function p(m){c=m;for(const C of[o,a,r])C.classList.toggle("held",m),C.inert=m;m?i.hidden=!0:e.callOffered()&&!e.mustSignIn()&&(i.hidden=!1),e.refreshSendState()}function f(){c&&p(!1)}function u(){n.hidden=!0,n.replaceChildren(),f(),s.focus()}function h(m){var b;const C=m.ratingDue==="require",w=m.resolvedAt?Se(m.resolvedAt):"",g=m.status==="CLOSED"?"closed":"fixed";if(n.hidden=!1,n.classList.toggle("is-required",C),n.innerHTML=`
|
|
1618
|
+
<div class="rd-head">
|
|
1619
|
+
<span class="rd-eyebrow">${C?"Before you report something new":`Your report was ${g}`}</span>
|
|
1620
|
+
${C?"":'<button type="button" class="link rd-later" data-act="rate-later">Not now</button>'}
|
|
1621
|
+
</div>
|
|
1622
|
+
<p class="rd-report">
|
|
1623
|
+
<span class="rd-ico" aria-hidden="true">${oe}</span>
|
|
1624
|
+
<span class="rd-ttl">${E(m.title)}</span>
|
|
1625
|
+
<span class="rd-sub">${E(m.reference)}${w?` · ${g} ${E(w)}`:""}</span>
|
|
1626
|
+
</p>
|
|
1627
|
+
<div class="rd-stars"></div>`,(b=n.querySelector('[data-act="rate-later"]'))==null||b.addEventListener("click",()=>{dr(m.id),u()}),dt(n.querySelector(".rd-stars"),{client:t,report:m,rating:null,question:C?"How did we handle it? Rate it to send a new one.":"How did we do?",onRated:()=>{var l;n.querySelector(".rd-eyebrow").textContent=`Your report was ${g}`,(l=n.querySelector('[data-act="skip"]'))==null||l.remove(),n.classList.remove("is-required"),f()},onError:()=>{if(!c||n.querySelector('[data-act="skip"]'))return;const l=document.createElement("button");l.type="button",l.className="link rd-later",l.dataset.act="skip",l.textContent="Skip for now",l.addEventListener("click",u),n.querySelector(".rd-head").append(l)}}),C){p(!0);const l=d.getRootNode().activeElement;(!l||!n.contains(l))&&n.focus()}}t.hasReports()&&t.myReports().then(({reports:m})=>{if(e.closed)return;const C=ur(m);C&&h(C)}).catch(()=>{})}function hr({root:e,host:t,dock:n,client:o,onClose:a,preloadCall:r=()=>{},themeControls:i=null}){fr(e);const s=o.config,d=()=>(i==null?void 0:i.label())||"",c=document.createElement("div");c.className=`scrim ${n.classList.contains("at-left")?"at-left":"at-right"} ${n.classList.contains("at-top")?"at-top":"at-bottom"}`,c.style.setProperty("--bc-dock-h",`${Math.round(n.getBoundingClientRect().height)}px`),c.innerHTML=`
|
|
1507
1628
|
<div class="panel" role="dialog" aria-modal="true" aria-labelledby="bc-h">
|
|
1508
|
-
${
|
|
1629
|
+
${st({id:"bc-h",title:"Report a bug",sub:"We attach the page details for you.",theme:d()})}
|
|
1509
1630
|
<div class="body">
|
|
1510
1631
|
<div class="slot" role="alert"></div>
|
|
1632
|
+
<!-- A settled report still waiting for its rating. Drawn only when the
|
|
1633
|
+
project asks for one here; see rate-due.js. -->
|
|
1634
|
+
<div class="rate-due fix-rating" tabindex="-1" hidden></div>
|
|
1511
1635
|
<!-- What the project's team is telling visitors. Drawn only when it
|
|
1512
1636
|
has published something. -->
|
|
1513
1637
|
<div class="notices" hidden></div>
|
|
@@ -1516,7 +1640,7 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1516
1640
|
close by itself. Drawn only when the project offers any. -->
|
|
1517
1641
|
<div class="picks" hidden></div>
|
|
1518
1642
|
<div class="known" hidden></div>
|
|
1519
|
-
${
|
|
1643
|
+
${Fa(s)}
|
|
1520
1644
|
</div>
|
|
1521
1645
|
<div class="foot">
|
|
1522
1646
|
<span class="note" aria-live="polite"></span>
|
|
@@ -1526,11 +1650,11 @@ div.done { padding: 44px 26px 44px; text-align: center; animation: bc-fade-in 24
|
|
|
1526
1650
|
most cannot. Drawn here rather than as a second launcher because it
|
|
1527
1651
|
is the same errand as Send report — the difference is only whether
|
|
1528
1652
|
the reporter would rather say it than type it. -->
|
|
1529
|
-
<button class="ghost" type="button" data-act="call" hidden>${
|
|
1530
|
-
<button class="primary" type="button" data-act="send">Send report ${
|
|
1653
|
+
<button class="ghost" type="button" data-act="call" hidden>${qe}Talk to the team</button>
|
|
1654
|
+
<button class="primary" type="button" data-act="send">Send report ${dn}</button>
|
|
1531
1655
|
</div>
|
|
1532
1656
|
<div class="powered">Powered by
|
|
1533
|
-
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${
|
|
1657
|
+
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${qa}</a>
|
|
1534
1658
|
</div>
|
|
1535
|
-
</div>`;const c=b=>s.querySelector(b),l=c(".slot"),f=[],d={client:o,cfg:i,root:t,host:e,dock:n,scrim:s,$:c,titleInput:c("#bc-title"),descInput:c("#bc-desc"),compose:c(".compose"),sendBtn:c('[data-act="send"]'),callBtn:c('[data-act="call"]'),historyBtn:c('[data-act="history"]'),note:c(".foot .note"),whoami:c(".whoami"),refsBox:c(".refs"),notices:c(".notices"),known:c(".known"),picks:c(".picks"),sending:!1,closed:!1,say:h,close:w,preloadCall:r,onDestroy:b=>{f.push(b)},refreshSendState:null,isRecording:null,stopRecording:null,holdForReference:null,answeredReference:null,pickedIssue:null,offerCall:null,callOffered:null,showLiveCall:null,mustSignIn:null,recheckSignIn:null,succeed:null,refreshThread:null,openReportId:null};Qa(d),Ha(d),Da(d),Na(d),Ua(d),_a(d),Pa(d),Xa(d);const u=document.activeElement,g=document.documentElement.style,y=g.overflow;g.overflow="hidden";function m(){d.closed||(f.forEach(b=>b()),d.closed=!0,g.overflow=y,document.removeEventListener("keydown",p,!0),s.remove(),n.hidden=!1,e.style.opacity="",a==null||a())}function w(){var b;if(!d.closed){s.classList.add("closing"),setTimeout(m,160);try{(b=u==null?void 0:u.focus)==null||b.call(u)}catch{}}}function p(b){if(b.key==="Escape"){if(b.stopPropagation(),d.isRecording()){d.stopRecording({keep:!1});return}d.sending||w();return}if(b.key!=="Tab"||d.isRecording())return;const T=[...s.querySelectorAll("button:not(:disabled), input:not([hidden]), textarea, select, [href]")].filter(v=>v.offsetParent!==null||v===document.activeElement);if(!T.length)return;const C=T[0],S=T[T.length-1],x=s.getRootNode().activeElement;b.shiftKey&&x===C?(b.preventDefault(),S.focus()):!b.shiftKey&&x===S&&(b.preventDefault(),C.focus())}document.addEventListener("keydown",p,!0),s.addEventListener("click",b=>{b.target===s&&!d.sending&&w()}),c('[data-act="close"]').addEventListener("click",w);function h(b,T="err"){l.innerHTML=b?`<div class="msg ${T}">${T==="err"?re:""}<span>${E(b)}</span></div>`:""}return t.appendChild(s),d.refreshSendState(),d.titleInput.focus(),{destroy:m,close:w}}function Za(t){if(t.querySelector("style[data-panel]"))return;const e=document.createElement("style");e.setAttribute("data-panel",""),e.textContent=Ea;const n=t.querySelector("style");n?n.after(e):t.prepend(e)}const Ga=Object.freeze(Object.defineProperty({__proto__:null,openPanel:Ja},Symbol.toStringTag,{value:"Module"})),dn=8e3;function er(t=dn){const e=window.AudioContext||window.webkitAudioContext;try{return new e({sampleRate:t})}catch{return new e}}async function tr(t){if(t.state==="suspended")try{await t.resume()}catch{}}function nr(t,e,n){const o=e/n,a=new Float32Array(Math.floor(t.length/o));for(let r=0;r<a.length;r++){const i=Math.floor(r*o),s=Math.min(Math.floor((r+1)*o),t.length);let c=0;for(let l=i;l<s;l++)c+=t[l];a[r]=s>i?c/(s-i):0}return a}const or=132,un=32635;function ar(t){const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++){const o=Math.max(-1,Math.min(1,t[n]));let a=Math.round(o*32767);const r=a<0?128:0;r&&(a=-a),a>un&&(a=un),a+=or;let i=7;for(let c=16384;!(a&c)&&i>0;i--,c>>=1);const s=a>>i+3&15;e[n]=~(r|i<<4|s)&255}return e}const rr=512;function ir(t,e,n,o=dn){const a=t.createMediaStreamSource(e),r=t.createScriptProcessor(rr,1,1);r.onaudioprocess=s=>{const c=s.inputBuffer.getChannelData(0),l=t.sampleRate===o?c:nr(c,t.sampleRate,o);n(ar(l))},a.connect(r);const i=t.createGain();return i.gain.value=0,r.connect(i),i.connect(t.destination),{stop(){r.onaudioprocess=null;try{a.disconnect()}catch{}try{r.disconnect()}catch{}try{i.disconnect()}catch{}}}}const sr="voiceai.realtime.v1",cr=[{urls:"stun:stun.l.google.com:19302"}];function pn(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function hn(){var t;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((t=navigator.mediaDevices)!=null&&t.getUserMedia)}async function lr({realtimeUrl:t,stream:e,ringsUntil:n,onState:o,onAudioBlocked:a,onMicrophone:r}){const i=(I,M)=>{try{o==null||o(I,M)}catch{}},s=I=>{try{a==null||a(I)}catch{}},c=I=>{try{r==null||r(I)}catch{}};if(!hn()){const I=new Error("[BugCatch] this browser cannot make live calls.");throw i("failed",{reason:"unsupported"}),I}let l=e;if(!l)try{l=await pn()}catch(I){throw i("failed",{reason:"microphone",error:String((I==null?void 0:I.name)||I)}),I}let f;try{f=await dr(t)}catch(I){throw gn(l),i("failed",{reason:"connect"}),I}let d=null,u=null,g=!1,y=null,m=null,w=null,p=!1,h=null,b=null,T=!1;const C=[];let S=!1,x=!1,v=!1,k=null,O=null,F=0;const Z=2e3,Y=5e3,L=3e4,j=4,R=(I,M)=>{if(!g){g=!0,y&&(clearTimeout(y),y=null),A(),b==null||b(),b=null,G(),h==null||h(),h=null;try{d==null||d.close()}catch{}gn(l),u&&(u.srcObject=null,u.remove(),u=null);try{f.readyState===WebSocket.OPEN&&f.close(1e3,"call over")}catch{}i(I,M)}},N=I=>{f.readyState===WebSocket.OPEN&&f.send(JSON.stringify(I))},ne=async()=>{if(T||w||g||!m||!m.audio&&!m.transcript)return;T=!0;const I=m.encoding||"mulaw";if(I!=="mulaw"){fn(`this call is kept as ${I}, which this SDK cannot produce.`);return}const M=Number(m.sample_rate)||8e3;try{const D=er(M);if(await tr(D),g){try{D.close()}catch{}return}const X=ir(D,l,V=>{f.readyState===WebSocket.OPEN&&f.send(V)},M);w={context:D,tap:X}}catch(D){fn(`could not send the copy this call is keeping: ${String((D==null?void 0:D.message)||D)}`)}};function G(){if(T=!1,!w)return;const{context:I,tap:M}=w;w=null;try{M.stop()}catch{}try{I.close()}catch{}}function ce(){var M;if(!u||g)return;let I;try{I=(M=u.play)==null?void 0:M.call(u)}catch{he();return}if(!I||typeof I.then!="function"){W();return}I.then(W,he)}function W(){h==null||h(),h=null,p&&(p=!1,s(!1))}function he(){g||(p||(p=!0,s(!0)),le())}function le(){if(h||typeof window>"u"||typeof window.addEventListener!="function")return;const I=()=>ce(),M=["pointerdown","keydown","touchstart"];for(const D of M)window.addEventListener(D,I,{capture:!0,passive:!0});h=()=>{for(const D of M)try{window.removeEventListener(D,I,{capture:!0})}catch{}}}const de=I=>{d=new RTCPeerConnection({iceServers:I!=null&&I.length?I:cr});for(const M of l.getAudioTracks())d.addTrack(M,l);b=_(),d.onicecandidate=M=>{M.candidate&&N({type:"signal",signal:{kind:"candidate",payload:M.candidate.toJSON()}})},d.ontrack=M=>{var X;const[D]=M.streams;D&&(u||(u=document.createElement("audio"),u.autoplay=!0,u.playsInline=!0,(X=u.setAttribute)==null||X.call(u,"playsinline",""),u.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(u)),u.srcObject=D,ce())},d.onconnectionstatechange=z,d.oniceconnectionstatechange=z};function z(){if(!d||g)return;const I=d.connectionState||d.iceConnectionState;if(I==="connected"||I==="completed"){x=!0,F=0,A(),v=!1,i("connected");return}if(I==="disconnected"){if(!x)return;$(Z);return}if(I==="failed"){if(!x){R("failed",{reason:"ice"});return}$(0)}}function $(I){g||(v||(v=!0,i("reconnecting"),O=setTimeout(()=>R("failed",{reason:"network"}),L)),!k&&(k=setTimeout(q,I)))}function A(){k&&(clearTimeout(k),k=null),O&&(clearTimeout(O),O=null)}async function q(){if(k=null,g||!d)return;const I=d.connectionState||d.iceConnectionState;if(!(I==="connected"||I==="completed")){if(!S){N({type:"signal",signal:{kind:"restart",payload:{}}}),k=setTimeout(q,Y);return}F>=j||(F+=1,await Q(),k=setTimeout(q,Y))}}async function Q(){if(!(g||!d))try{const I=await d.createOffer({iceRestart:!0});await d.setLocalDescription(I),N({type:"signal",signal:{kind:"offer",payload:d.localDescription.toJSON()}})}catch{}}function _(){let M=null,D=!1;const X=V=>{if(M&&(clearTimeout(M),M=null),V){if(!D)return;D=!1,c(!0);return}D||(M=setTimeout(()=>{M=null,!g&&(D=!0,c(!1))},600))};for(const V of l.getAudioTracks())V.onmute=()=>X(!1),V.onunmute=()=>X(!0),V.onended=()=>{M&&(clearTimeout(M),M=null),!D&&(D=!0,c(!1))};return()=>{M&&(clearTimeout(M),M=null);for(const V of l.getAudioTracks())V.onmute=null,V.onunmute=null,V.onended=null}}const ee=async()=>{try{const I=await d.createOffer();await d.setLocalDescription(I),N({type:"signal",signal:{kind:"offer",payload:d.localDescription.toJSON()}})}catch{R("failed",{reason:"negotiation"})}},br=async I=>{try{await d.setRemoteDescription(new RTCSessionDescription(I));const M=await d.createAnswer();await d.setLocalDescription(M),N({type:"signal",signal:{kind:"answer",payload:d.localDescription.toJSON()}}),await mn()}catch{R("failed",{reason:"negotiation"})}},mn=async()=>{for(;C.length;){const I=C.shift();try{await d.addIceCandidate(new RTCIceCandidate(I))}catch{}}};let yn=Promise.resolve();f.onmessage=I=>{yn=yn.then(()=>mr(I)).catch(()=>{})};const mr=async I=>{var D,X,V,wn,vn;if(typeof I.data!="string")return;let M;try{M=JSON.parse(I.data)}catch{return}switch(M.type){case"session.created":{if(de((D=M.data)==null?void 0:D.ice_servers),m=((X=M.data)==null?void 0:X.capture)||null,(V=M.data)!=null&&V.peer_present){i("connecting"),ne();break}i("ringing"),yr();break}case"peer.joined":{y&&(clearTimeout(y),y=null),i("connecting"),S=!!((wn=M.data)!=null&&wn.should_offer),S&&await ee(),ne();break}case"signal":{if(!d)break;const{kind:He,payload:qe}=M.data||{};if(He==="offer")await br(qe);else if(He==="answer")try{await d.setRemoteDescription(new RTCSessionDescription(qe)),await mn()}catch{R("failed",{reason:"negotiation"})}else if(He==="candidate")if(d.remoteDescription)try{await d.addIceCandidate(new RTCIceCandidate(qe))}catch{}else C.push(qe);else He==="restart"&&S&&await Q();break}case"peer.left":R("ended",{reason:"peer_left"});break;case"error":R("failed",{reason:"server",detail:(vn=M.error)==null?void 0:vn.detail});break;case"session.ended":R("ended",{reason:"server"});break}};f.onclose=()=>R("ended",{reason:"disconnected"}),f.onerror=()=>R("failed",{reason:"socket"});function yr(){if(!n)return;const I=new Date(n).getTime()-Date.now();Number.isFinite(I)&&(y=setTimeout(()=>R("missed"),Math.max(0,I)))}return{hangUp(){N({type:"session.end"}),R("ended",{reason:"hung_up"})},setMuted(I){for(const M of l.getAudioTracks())M.enabled=!I;return I},isMuted(){return l.getAudioTracks().every(I=>!I.enabled)}}}function dr(t){return new Promise((e,n)=>{let o;try{o=new WebSocket(t,sr)}catch(a){n(a);return}o.onopen=()=>{o.onopen=null,o.onerror=null,e(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function fn(t){try{console.warn(`[BugCatch] ${t}`)}catch{}}function gn(t){var e;for(const n of((e=t==null?void 0:t.getTracks)==null?void 0:e.call(t))??[])try{n.stop()}catch{}}const Qe={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};function ur(){var t;try{return!!((t=navigator.userActivation)!=null&&t.hasBeenActive)}catch{return!1}}function pr(t){if(!t()&&!ur())return()=>{};const e=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!e)return()=>{};let n;try{n=new e}catch{return()=>{}}let o=!1,a=null;const r=[],i=({at:l,seconds:f,hz:d})=>{const u=n.currentTime+l,g=n.createGain();g.connect(n.destination),g.gain.setValueAtTime(0,u),g.gain.linearRampToValueAtTime(Qe.peak,u+.02),g.gain.setValueAtTime(Qe.peak,u+f-.06),g.gain.linearRampToValueAtTime(0,u+f);for(const y of d){const m=n.createOscillator();m.type="sine",m.frequency.value=y,m.connect(g),m.start(u),m.stop(u+f+.02),r.push(m)}},s=()=>{if(!o)try{Qe.bursts.forEach(i)}catch{}},c=()=>{o||(s(),a=setInterval(s,Qe.cycleMs))};return n.state==="running"?c():n.resume().then(c).catch(()=>{}),()=>{o=!0,a&&clearInterval(a);for(const l of r)try{l.stop()}catch{}try{n.close()}catch{}}}function hr(t){const e=Date.parse(t||"");return Number.isNaN(e)?0:Math.max(0,Math.round((e-Date.now())/1e3))}const bn=["flex:1","padding:9px 12px","border:0","border-radius:8px","font:600 13px/1.4 inherit","cursor:pointer"].join(";");function fr({call:t,accent:e="#5b6ef5",position:n="bottom-right",onAnswer:o,onDecline:a,onExpire:r,touched:i=()=>!1}){if(typeof document>"u"||!document.body)return()=>{};const[s,c]=String(n).split("-"),l=document.createElement("div");l.setAttribute("role","alertdialog"),l.setAttribute("aria-live","assertive"),l.setAttribute("aria-label",`${t.from||"Support"} is calling about ${t.reference}`),l.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${c==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:14px","border-radius:12px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 18px 44px rgba(0,0,0,0.5)",`border:1px solid ${e}`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const f=document.createElement("div");f.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",f.textContent=`${t.from||"Support"} is calling`;const d=document.createElement("div");d.style.cssText="color:#a4abba;margin-bottom:10px",d.textContent=t.project?`About your report ${t.reference} · ${t.project}`:`About your report ${t.reference}`;const u=document.createElement("div");u.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px";const g=document.createElement("button");g.type="button",g.textContent="Answer",g.style.cssText=`${bn};background:${e};color:#fff`;const y=document.createElement("button");y.type="button",y.textContent="Not now",y.style.cssText=`${bn};background:#2b2f3a;color:#c8cedb`;const m=document.createElement("div");if(m.style.cssText="display:flex;gap:8px",m.append(g,y),l.append(f,d,u),t.recorded){const C=document.createElement("div");C.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px",C.textContent="This call will be recorded.",l.append(C)}l.append(m),document.body.appendChild(l);const w=pr(i);let p=!1,h=null;const b=()=>{p||(p=!0,h&&clearInterval(h),w(),l.style.opacity="0",l.style.transform="translateY(8px)",setTimeout(()=>l.remove(),250))},T=()=>{const C=hr(t.ringsUntil);if(u.textContent=C?`Ringing — ${C}s`:"The call has stopped ringing.",!C){b();try{r==null||r()}catch{}}};return T(),h=setInterval(T,1e3),g.addEventListener("click",()=>{b();try{o==null||o()}catch{}}),y.addEventListener("click",()=>{b();try{a==null||a()}catch{}}),requestAnimationFrame(()=>{l.style.opacity="1",l.style.transform="translateY(0)"}),b}const gr=Object.freeze(Object.defineProperty({__proto__:null,joinLiveCall:lr,liveCallSupported:hn,openMicrophone:pn,showIncomingCall:fr},Symbol.toStringTag,{value:"Module"}));return nt});
|
|
1659
|
+
</div>`;const p=y=>c.querySelector(y),f=p(".slot"),u=[],h={client:o,cfg:s,root:e,host:t,dock:n,scrim:c,$:p,titleInput:p("#bc-title"),descInput:p("#bc-desc"),compose:p(".compose"),sendBtn:p('[data-act="send"]'),callBtn:p('[data-act="call"]'),historyBtn:p('[data-act="history"]'),note:p(".foot .note"),whoami:p(".whoami"),refsBox:p(".refs"),notices:p(".notices"),known:p(".known"),picks:p(".picks"),rateDue:p(".rate-due"),sending:!1,closed:!1,say:S,close:b,preloadCall:r,themeLabel:d,onDestroy:y=>{u.push(y)},refreshSendState:null,isRecording:null,stopRecording:null,holdForReference:null,answeredReference:null,pickedIssue:null,offerCall:null,callOffered:null,showLiveCall:null,mustSignIn:null,recheckSignIn:null,mustRate:()=>!1,succeed:null,refreshThread:null,openReportId:null};Wa(h),Ya(h),Ja(h),Za(h),Ga(h),er(h),tr(h),cr(h),pr(h);const m=document.activeElement,C=document.documentElement.style,w=C.overflow;C.overflow="hidden";function g(){h.closed||(u.forEach(y=>y()),h.closed=!0,C.overflow=w,document.removeEventListener("keydown",l,!0),c.remove(),n.hidden=!1,t.style.opacity="",a==null||a())}function b(){var y;if(!h.closed){c.classList.add("closing"),setTimeout(g,160);try{(y=m==null?void 0:m.focus)==null||y.call(m)}catch{}}}function l(y){if(y.key==="Escape"){if(y.stopPropagation(),h.isRecording()){h.stopRecording({keep:!1});return}h.sending||b();return}if(y.key!=="Tab"||h.isRecording())return;const x=[...c.querySelectorAll("button:not(:disabled), input:not([hidden]), textarea, select, [href]")].filter(j=>j.offsetParent!==null||j===document.activeElement);if(!x.length)return;const v=x[0],k=x[x.length-1],T=c.getRootNode().activeElement;y.shiftKey&&T===v?(y.preventDefault(),k.focus()):!y.shiftKey&&T===k&&(y.preventDefault(),v.focus())}document.addEventListener("keydown",l,!0),c.addEventListener("click",y=>{y.target===c&&!h.sending&&b()}),p('[data-act="close"]').addEventListener("click",b),c.addEventListener("click",y=>{const x=y.target.closest('[data-act="theme"]');if(!x||!i)return;const v=i.cycle();x.title=`Theme: ${v.label}`,x.setAttribute("aria-label",`Theme: ${v.label}. Change theme`)});function S(y,x="err"){f.innerHTML=y?`<div class="msg ${x}">${x==="err"?se:""}<span>${E(y)}</span></div>`:""}return e.appendChild(c),h.refreshSendState(),h.titleInput.focus(),{destroy:g,close:b}}function fr(e){if(e.querySelector("style[data-panel]"))return;const t=document.createElement("style");t.setAttribute("data-panel",""),t.textContent=Da;const n=e.querySelector("style");n?n.after(t):e.prepend(t)}const gr=Object.freeze(Object.defineProperty({__proto__:null,openPanel:hr},Symbol.toStringTag,{value:"Module"})),xn=8e3;function br(e=xn){const t=window.AudioContext||window.webkitAudioContext;try{return new t({sampleRate:e})}catch{return new t}}async function mr(e){if(e.state==="suspended")try{await e.resume()}catch{}}function yr(e,t,n){const o=t/n,a=new Float32Array(Math.floor(e.length/o));for(let r=0;r<a.length;r++){const i=Math.floor(r*o),s=Math.min(Math.floor((r+1)*o),e.length);let d=0;for(let c=i;c<s;c++)d+=e[c];a[r]=s>i?d/(s-i):0}return a}const wr=132,kn=32635;function vr(e){const t=new Uint8Array(e.length);for(let n=0;n<e.length;n++){const o=Math.max(-1,Math.min(1,e[n]));let a=Math.round(o*32767);const r=a<0?128:0;r&&(a=-a),a>kn&&(a=kn),a+=wr;let i=7;for(let d=16384;!(a&d)&&i>0;i--,d>>=1);const s=a>>i+3&15;t[n]=~(r|i<<4|s)&255}return t}const xr=512;function kr(e,t,n,o=xn){const a=e.createMediaStreamSource(t),r=e.createScriptProcessor(xr,1,1);r.onaudioprocess=s=>{const d=s.inputBuffer.getChannelData(0),c=e.sampleRate===o?d:yr(d,e.sampleRate,o);n(vr(c))},a.connect(r);const i=e.createGain();return i.gain.value=0,r.connect(i),i.connect(e.destination),{stop(){r.onaudioprocess=null;try{a.disconnect()}catch{}try{r.disconnect()}catch{}try{i.disconnect()}catch{}}}}const Sr="voiceai.realtime.v1",$r=[{urls:"stun:stun.l.google.com:19302"}];function Sn(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function $n(){var e;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((e=navigator.mediaDevices)!=null&&e.getUserMedia)}async function Cr({realtimeUrl:e,stream:t,ringsUntil:n,onState:o,onAudioBlocked:a,onMicrophone:r}){const i=(I,M)=>{try{o==null||o(I,M)}catch{}},s=I=>{try{a==null||a(I)}catch{}},d=I=>{try{r==null||r(I)}catch{}};if(!$n()){const I=new Error("[BugCatch] this browser cannot make live calls.");throw i("failed",{reason:"unsupported"}),I}let c=t;if(!c)try{c=await Sn()}catch(I){throw i("failed",{reason:"microphone",error:String((I==null?void 0:I.name)||I)}),I}let p;try{p=await Tr(e)}catch(I){throw Tn(c),i("failed",{reason:"connect"}),I}let f=null,u=null,h=!1,m=null,C=null,w=null,g=!1,b=null,l=null,S=!1;const y=[];let x=!1,v=!1,k=!1,T=null,j=null,O=0;const _=2e3,Y=5e3,L=3e4,D=4,R=(I,M)=>{if(!h){h=!0,m&&(clearTimeout(m),m=null),A(),l==null||l(),l=null,te(),b==null||b(),b=null;try{f==null||f.close()}catch{}Tn(c),u&&(u.srcObject=null,u.remove(),u=null);try{p.readyState===WebSocket.OPEN&&p.close(1e3,"call over")}catch{}i(I,M)}},Q=I=>{p.readyState===WebSocket.OPEN&&p.send(JSON.stringify(I))},J=async()=>{if(S||w||h||!C||!C.audio&&!C.transcript)return;S=!0;const I=C.encoding||"mulaw";if(I!=="mulaw"){Cn(`this call is kept as ${I}, which this SDK cannot produce.`);return}const M=Number(C.sample_rate)||8e3;try{const U=br(M);if(await mr(U),h){try{U.close()}catch{}return}const G=kr(U,c,W=>{p.readyState===WebSocket.OPEN&&p.send(W)},M);w={context:U,tap:G}}catch(U){Cn(`could not send the copy this call is keeping: ${String((U==null?void 0:U.message)||U)}`)}};function te(){if(S=!1,!w)return;const{context:I,tap:M}=w;w=null;try{M.stop()}catch{}try{I.close()}catch{}}function le(){var M;if(!u||h)return;let I;try{I=(M=u.play)==null?void 0:M.call(u)}catch{fe();return}if(!I||typeof I.then!="function"){Z();return}I.then(Z,fe)}function Z(){b==null||b(),b=null,g&&(g=!1,s(!1))}function fe(){h||(g||(g=!0,s(!0)),de())}function de(){if(b||typeof window>"u"||typeof window.addEventListener!="function")return;const I=()=>le(),M=["pointerdown","keydown","touchstart"];for(const U of M)window.addEventListener(U,I,{capture:!0,passive:!0});b=()=>{for(const U of M)try{window.removeEventListener(U,I,{capture:!0})}catch{}}}const ue=I=>{f=new RTCPeerConnection({iceServers:I!=null&&I.length?I:$r});for(const M of c.getAudioTracks())f.addTrack(M,c);l=P(),f.onicecandidate=M=>{M.candidate&&Q({type:"signal",signal:{kind:"candidate",payload:M.candidate.toJSON()}})},f.ontrack=M=>{var G;const[U]=M.streams;U&&(u||(u=document.createElement("audio"),u.autoplay=!0,u.playsInline=!0,(G=u.setAttribute)==null||G.call(u,"playsinline",""),u.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(u)),u.srcObject=U,le())},f.onconnectionstatechange=z,f.oniceconnectionstatechange=z};function z(){if(!f||h)return;const I=f.connectionState||f.iceConnectionState;if(I==="connected"||I==="completed"){v=!0,O=0,A(),k=!1,i("connected");return}if(I==="disconnected"){if(!v)return;$(_);return}if(I==="failed"){if(!v){R("failed",{reason:"ice"});return}$(0)}}function $(I){h||(k||(k=!0,i("reconnecting"),j=setTimeout(()=>R("failed",{reason:"network"}),L)),!T&&(T=setTimeout(H,I)))}function A(){T&&(clearTimeout(T),T=null),j&&(clearTimeout(j),j=null)}async function H(){if(T=null,h||!f)return;const I=f.connectionState||f.iceConnectionState;if(!(I==="connected"||I==="completed")){if(!x){Q({type:"signal",signal:{kind:"restart",payload:{}}}),T=setTimeout(H,Y);return}O>=D||(O+=1,await N(),T=setTimeout(H,Y))}}async function N(){if(!(h||!f))try{const I=await f.createOffer({iceRestart:!0});await f.setLocalDescription(I),Q({type:"signal",signal:{kind:"offer",payload:f.localDescription.toJSON()}})}catch{}}function P(){let M=null,U=!1;const G=W=>{if(M&&(clearTimeout(M),M=null),W){if(!U)return;U=!1,d(!0);return}U||(M=setTimeout(()=>{M=null,!h&&(U=!0,d(!1))},600))};for(const W of c.getAudioTracks())W.onmute=()=>G(!1),W.onunmute=()=>G(!0),W.onended=()=>{M&&(clearTimeout(M),M=null),!U&&(U=!0,d(!1))};return()=>{M&&(clearTimeout(M),M=null);for(const W of c.getAudioTracks())W.onmute=null,W.onunmute=null,W.onended=null}}const ne=async()=>{try{const I=await f.createOffer();await f.setLocalDescription(I),Q({type:"signal",signal:{kind:"offer",payload:f.localDescription.toJSON()}})}catch{R("failed",{reason:"negotiation"})}},Br=async I=>{try{await f.setRemoteDescription(new RTCSessionDescription(I));const M=await f.createAnswer();await f.setLocalDescription(M),Q({type:"signal",signal:{kind:"answer",payload:f.localDescription.toJSON()}}),await In()}catch{R("failed",{reason:"negotiation"})}},In=async()=>{for(;y.length;){const I=y.shift();try{await f.addIceCandidate(new RTCIceCandidate(I))}catch{}}};let Ln=Promise.resolve();p.onmessage=I=>{Ln=Ln.then(()=>Rr(I)).catch(()=>{})};const Rr=async I=>{var U,G,W,An,Mn;if(typeof I.data!="string")return;let M;try{M=JSON.parse(I.data)}catch{return}switch(M.type){case"session.created":{if(ue((U=M.data)==null?void 0:U.ice_servers),C=((G=M.data)==null?void 0:G.capture)||null,(W=M.data)!=null&&W.peer_present){i("connecting"),J();break}i("ringing"),jr();break}case"peer.joined":{m&&(clearTimeout(m),m=null),i("connecting"),x=!!((An=M.data)!=null&&An.should_offer),x&&await ne(),J();break}case"signal":{if(!f)break;const{kind:Ne,payload:Ue}=M.data||{};if(Ne==="offer")await Br(Ue);else if(Ne==="answer")try{await f.setRemoteDescription(new RTCSessionDescription(Ue)),await In()}catch{R("failed",{reason:"negotiation"})}else if(Ne==="candidate")if(f.remoteDescription)try{await f.addIceCandidate(new RTCIceCandidate(Ue))}catch{}else y.push(Ue);else Ne==="restart"&&x&&await N();break}case"peer.left":R("ended",{reason:"peer_left"});break;case"error":R("failed",{reason:"server",detail:(Mn=M.error)==null?void 0:Mn.detail});break;case"session.ended":R("ended",{reason:"server"});break}};p.onclose=()=>R("ended",{reason:"disconnected"}),p.onerror=()=>R("failed",{reason:"socket"});function jr(){if(!n)return;const I=new Date(n).getTime()-Date.now();Number.isFinite(I)&&(m=setTimeout(()=>R("missed"),Math.max(0,I)))}return{hangUp(){Q({type:"session.end"}),R("ended",{reason:"hung_up"})},setMuted(I){for(const M of c.getAudioTracks())M.enabled=!I;return I},isMuted(){return c.getAudioTracks().every(I=>!I.enabled)}}}function Tr(e){return new Promise((t,n)=>{let o;try{o=new WebSocket(e,Sr)}catch(a){n(a);return}o.onopen=()=>{o.onopen=null,o.onerror=null,t(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function Cn(e){try{console.warn(`[BugCatch] ${e}`)}catch{}}function Tn(e){var t;for(const n of((t=e==null?void 0:e.getTracks)==null?void 0:t.call(e))??[])try{n.stop()}catch{}}const He={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};function Er(){var e;try{return!!((e=navigator.userActivation)!=null&&e.hasBeenActive)}catch{return!1}}function Ir(e){if(!e()&&!Er())return()=>{};const t=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!t)return()=>{};let n;try{n=new t}catch{return()=>{}}let o=!1,a=null;const r=[],i=({at:c,seconds:p,hz:f})=>{const u=n.currentTime+c,h=n.createGain();h.connect(n.destination),h.gain.setValueAtTime(0,u),h.gain.linearRampToValueAtTime(He.peak,u+.02),h.gain.setValueAtTime(He.peak,u+p-.06),h.gain.linearRampToValueAtTime(0,u+p);for(const m of f){const C=n.createOscillator();C.type="sine",C.frequency.value=m,C.connect(h),C.start(u),C.stop(u+p+.02),r.push(C)}},s=()=>{if(!o)try{He.bursts.forEach(i)}catch{}},d=()=>{o||(s(),a=setInterval(s,He.cycleMs))};return n.state==="running"?d():n.resume().then(d).catch(()=>{}),()=>{o=!0,a&&clearInterval(a);for(const c of r)try{c.stop()}catch{}try{n.close()}catch{}}}function Lr(e){const t=Date.parse(e||"");return Number.isNaN(t)?0:Math.max(0,Math.round((t-Date.now())/1e3))}const En=["flex:1","padding:9px 12px","border:0","border-radius:999px","font:560 13px/1.4 inherit","cursor:pointer"].join(";");function Ar({call:e,accent:t=null,position:n="bottom-right",onAnswer:o,onDecline:a,onExpire:r,touched:i=()=>!1}){if(typeof document>"u"||!document.body)return()=>{};const[s,d]=String(n).split("-"),c=document.createElement("div");c.setAttribute("role","alertdialog"),c.setAttribute("aria-live","assertive"),c.setAttribute("aria-label",`${e.from||"Support"} is calling about ${e.reference}`),c.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${d==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:16px","border-radius:16px","background:#111113","color:#f3f2ef",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',`box-shadow:0 0 0 1px ${t?`color-mix(in srgb, ${t} 55%, transparent)`:"rgba(255,255,255,.12)"},0 24px 50px -12px rgba(0,0,0,.6)`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const p=document.createElement("div");p.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",p.textContent=`${e.from||"Support"} is calling`;const f=document.createElement("div");f.style.cssText="color:#b3b0aa;margin-bottom:10px",f.textContent=e.project?`About your report ${e.reference} · ${e.project}`:`About your report ${e.reference}`;const u=document.createElement("div");u.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px";const h=document.createElement("button");h.type="button",h.textContent="Answer",h.style.cssText=`${En};background:${t||Te};color:${t?Xe(t):Ye}`;const m=document.createElement("button");m.type="button",m.textContent="Not now",m.style.cssText=`${En};background:rgba(255,255,255,.08);color:#f3f2ef`;const C=document.createElement("div");if(C.style.cssText="display:flex;gap:8px",C.append(h,m),c.append(p,f,u),e.recorded){const y=document.createElement("div");y.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px",y.textContent="This call will be recorded.",c.append(y)}c.append(C),document.body.appendChild(c);const w=Ir(i);let g=!1,b=null;const l=()=>{g||(g=!0,b&&clearInterval(b),w(),c.style.opacity="0",c.style.transform="translateY(8px)",setTimeout(()=>c.remove(),250))},S=()=>{const y=Lr(e.ringsUntil);if(u.textContent=y?`Ringing — ${y}s`:"The call has stopped ringing.",!y){l();try{r==null||r()}catch{}}};return S(),b=setInterval(S,1e3),h.addEventListener("click",()=>{l();try{o==null||o()}catch{}}),m.addEventListener("click",()=>{l();try{a==null||a()}catch{}}),requestAnimationFrame(()=>{c.style.opacity="1",c.style.transform="translateY(0)"}),l}const Mr=Object.freeze(Object.defineProperty({__proto__:null,joinLiveCall:Cr,liveCallSupported:$n,openMicrophone:Sn,showIncomingCall:Ar},Symbol.toStringTag,{value:"Module"}));return it});
|
|
1536
1660
|
//# sourceMappingURL=bugcatch.standalone.umd.js.map
|