@sparkvault/sdk 1.1.6 → 1.8.3

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.
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).SparkVault={})}(this,function(e){"use strict";class t extends Error{constructor(e,n,i,s){super(e),this.name="SparkVaultError",this.code=n,this.statusCode=i,this.details=s,Object.setPrototypeOf(this,t.prototype)}}class n extends t{constructor(e,t){super(e,"authentication_error",401,t),this.name="AuthenticationError",Object.setPrototypeOf(this,n.prototype)}}class i extends t{constructor(e,t){super(e,"authorization_error",403,t),this.name="AuthorizationError",Object.setPrototypeOf(this,i.prototype)}}class s extends t{constructor(e,t){super(e,"validation_error",400,t),this.name="ValidationError",Object.setPrototypeOf(this,s.prototype)}}class o extends t{constructor(e,t){super(e,"network_error",void 0,t),this.name="NetworkError",Object.setPrototypeOf(this,o.prototype)}}class r extends t{constructor(e="Request timed out"){super(e,"timeout_error"),this.name="TimeoutError",Object.setPrototypeOf(this,r.prototype)}}class a extends t{constructor(e="User cancelled the operation"){super(e,"user_cancelled"),this.name="UserCancelledError",Object.setPrototypeOf(this,a.prototype)}}class l extends t{constructor(){super("Popup was blocked. Please allow popups for this site.","popup_blocked"),this.name="PopupBlockedError",Object.setPrototypeOf(this,l.prototype)}}const d={maxAttempts:3,baseDelayMs:200,maxDelayMs:5e3,jitterFactor:.2,isRetryable:function(e){if(e instanceof TypeError)return!0;if(e instanceof DOMException&&"AbortError"===e.name)return!0;if("object"==typeof e&&null!==e&&"statusCode"in e){const t=e.statusCode;return t>=500||429===t}return!1}};function c(e,t,n,i){const s=t*Math.pow(2,e),o=Math.min(s,n);return o+o*i*Math.random()}function h(e){return new Promise(t=>setTimeout(t,e))}async function p(e,t={}){const n={...d,...t};let i;for(let t=0;t<n.maxAttempts;t++)try{return await e()}catch(e){i=e;if(t===n.maxAttempts-1||!n.isRetryable(e))throw e;const s=c(t,n.baseDelayMs,n.maxDelayMs,n.jitterFactor);await h(s)}throw i}class u{constructor(e){this.config=e}async request(e,t={}){const{retry:n}=t;if(n){return p(()=>this.executeRequest(e,t),{..."object"==typeof n?n:{},isRetryable:e=>this.isRetryableError(e)})}return this.executeRequest(e,t)}async executeRequest(e,n){const{method:i="GET",headers:s={},body:a,timeout:l=this.config.timeout}=n,d=`${this.config.apiBaseUrl}${e}`,c={"Content-Type":"application/json",Accept:"application/json",...s},h=new AbortController,p=setTimeout(()=>h.abort(),l);try{const e=await fetch(d,{method:i,headers:c,body:a?JSON.stringify(a):void 0,signal:h.signal});clearTimeout(p);const t=await this.parseResponse(e);if(!e.ok)throw this.createErrorFromResponse(e.status,t);return{data:t,status:e.status,headers:e.headers}}catch(e){if(clearTimeout(p),e instanceof t)throw e;if(e instanceof DOMException&&"AbortError"===e.name)throw new r;if(e instanceof TypeError)throw new o("Network request failed. Please check your connection.");throw new t(e instanceof Error?e.message:"Unknown error","unknown_error")}}isRetryableError(e){return e instanceof o||e instanceof r||e instanceof t&&void 0!==e.statusCode&&(e.statusCode>=500||429===e.statusCode)}async parseResponse(e){const n=e.headers.get("content-length");if(204===e.status||"0"===n)return null;const i=e.headers.get("content-type");if(i?.includes("application/json")){return await e.json()}const s=await e.text();throw new t(`Unexpected response format: expected JSON but received ${i??"unknown content type"}`,"invalid_response_format",e.status,{body:s.slice(0,500)})}createErrorFromResponse(e,o){const r="object"==typeof o&&null!==o?o:{},a=("string"==typeof r.message?r.message:null)??("string"==typeof r.error?r.error:null)??"Request failed",l="string"==typeof r.code?r.code:"api_error",d="object"==typeof r.details&&null!==r.details?r.details:void 0;switch(e){case 400:return new s(a,d);case 401:return new n(a,d);case 403:return new i(a,d);default:return new t(a,l,e,d)}}get(e,t){return this.request(e,{...t,method:"GET"})}post(e,t,n){return this.request(e,{...n,method:"POST",body:t})}put(e,t,n){return this.request(e,{...n,method:"PUT",body:t})}patch(e,t,n){return this.request(e,{...n,method:"PATCH",body:t})}delete(e,t){return this.request(e,{...t,method:"DELETE"})}async requestRaw(e,t={}){const{retry:n}=t;if(n){return p(()=>this.executeRequestRaw(e,t),{..."object"==typeof n?n:{},isRetryable:e=>this.isRetryableError(e)})}return this.executeRequestRaw(e,t)}async executeRequestRaw(e,n){const{method:i="GET",headers:s={},body:a,timeout:l=this.config.timeout}=n,d=`${this.config.apiBaseUrl}${e}`,c={"Content-Type":"application/json",...s},h=new AbortController,p=setTimeout(()=>h.abort(),l);try{const e=await fetch(d,{method:i,headers:c,body:a?JSON.stringify(a):void 0,signal:h.signal});if(clearTimeout(p),!e.ok){const t=await e.json().catch(()=>({}));throw this.createErrorFromResponse(e.status,t)}return e.blob()}catch(e){if(clearTimeout(p),e instanceof t)throw e;if(e instanceof DOMException&&"AbortError"===e.name)throw new r;if(e instanceof TypeError)throw new o("Network request failed. Please check your connection.");throw new t(e instanceof Error?e.message:"Unknown error","unknown_error")}}}class m{constructor(e){this.intervalId=null,this.secondsRemaining=e.duration,this.onTick=e.onTick,this.onComplete=e.onComplete}start(){this.stop(),this.onTick(this.secondsRemaining),this.intervalId=setInterval(()=>{this.secondsRemaining--,this.onTick(this.secondsRemaining),this.secondsRemaining<=0&&(this.stop(),this.onComplete())},1e3)}stop(){null!==this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}isRunning(){return null!==this.intervalId}getRemainingSeconds(){return this.secondsRemaining}}class g{constructor(e){this.intervalId=null,Number.isFinite(e.expiresAt)?this.expiresAt=e.expiresAt:(console.warn("[ExpirationTimer] Invalid expiresAt:",e.expiresAt),this.expiresAt=0),this.onTick=e.onTick,this.onExpired=e.onExpired}calculateRemaining(){const e=Math.floor(Date.now()/1e3),t=this.expiresAt-e;return!Number.isFinite(t)||t<0?0:Math.ceil(t)}start(){this.stop();const e=this.calculateRemaining();this.onTick(e),e<=0?this.onExpired():this.intervalId=setInterval(()=>{const e=this.calculateRemaining();this.onTick(e),e<=0&&(this.stop(),this.onExpired())},1e3)}stop(){null!==this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}isRunning(){return null!==this.intervalId}}function b(e){let t="";for(let n=0;n<e.byteLength;n++)t+=String.fromCharCode(e[n]);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function y(e){return b(new Uint8Array(e))}function f(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t+"=".repeat((4-t.length%4)%4),i=atob(n),s=new Uint8Array(i.length);for(let e=0;e<i.length;e++)s[e]=i.charCodeAt(e);return s}function k(e){const t=f(e),n=new ArrayBuffer(t.length);return new Uint8Array(n).set(t),n}function v(e){const t=f(e);return Array.from(t)}class w{constructor(e,t=3e4){this.configCache=null,this.config=e,this.timeoutMs=t}get baseUrl(){return`${this.config.identityBaseUrl}/${this.config.accountId}`}async request(e,t,n){const i=`${this.baseUrl}${t}`,s={"Content-Type":"application/json",Accept:"application/json"},o=new AbortController,r=setTimeout(()=>o.abort(),this.timeoutMs);try{const t=await fetch(i,{method:e,headers:s,body:n?JSON.stringify(n):void 0,signal:o.signal}),r=await t.json();if(!t.ok){const e=r.error||{},n=e.message||r.message||"Request failed",i=e.code||r.code||"api_error";throw new x(n,i,t.status)}return r.data??r}catch(e){if(e instanceof Error&&"AbortError"===e.name)throw new x("Request timed out","timeout",0);throw e}finally{clearTimeout(r)}}async getConfig(){return this.configCache||(this.configCache=this.request("GET","/config")),this.configCache}preloadConfig(){this.configCache||(this.configCache=this.request("GET","/config"))}isConfigPreloaded(){return null!==this.configCache}async checkPasskey(e){return this.request("POST","/passkey/check",{email:e})}async sendTotp(e){return this.request("POST","/totp/send",{recipient:e.recipient,method:e.method})}async verifyTotp(e){return this.request("POST","/totp/verify",{kindling:e.kindling,pin:e.pin,recipient:e.recipient})}async startPasskeyRegister(e){const t=await this.request("POST","/passkey/register",{email:e});return{challenge:t.options.challenge,rpId:t.options.rp.id,rpName:t.options.rp.name,userId:t.options.user.id,userName:t.options.user.name,timeout:t.options.timeout,session:t.session}}async completePasskeyRegister(e){const t=e.credential.response;return this.request("POST","/passkey/register/complete",{session:e.session,credential:{id:e.credential.id,rawId:y(e.credential.rawId),type:e.credential.type,response:{clientDataJSON:y(t.clientDataJSON),attestationObject:y(t.attestationObject)}}})}async startPasskeyVerify(e){const t=await this.request("POST","/passkey/verify",{email:e});return{challenge:t.options.challenge,rpId:t.options.rpId,rpName:"SparkVault Identity",timeout:t.options.timeout,allowCredentials:t.options.allowCredentials,session:t.session}}async completePasskeyVerify(e){const t=e.credential.response;return this.request("POST","/passkey/verify/complete",{session:e.session,credential:{id:e.credential.id,rawId:y(e.credential.rawId),type:e.credential.type,response:{clientDataJSON:y(t.clientDataJSON),authenticatorData:y(t.authenticatorData),signature:y(t.signature),userHandle:t.userHandle?y(t.userHandle):null}}})}getSocialAuthUrl(e,t,n){const i=new URLSearchParams({redirect_uri:t,state:n});return`${this.baseUrl}/social/${e}?${i}`}getEnterpriseAuthUrl(e,t,n){const i=new URLSearchParams({redirect_uri:t,state:n});return`${this.baseUrl}/saml/${e}?${i}`}async sendSparkLink(e){return this.request("POST","/sparklink/send",{email:e,type:"verify_identity",openerOrigin:"undefined"!=typeof window?window.location.origin:void 0})}async checkSparkLinkStatus(e){return this.request("GET",`/sparklink/status/${e}`)}}class x extends Error{constructor(e,t,n){super(e),this.name="IdentityApiError",this.code=t,this.statusCode=n}}const C={totp_email:{id:"totp_email",type:"totp",identityType:"email",name:"Email code",description:"Get a one-time code via email",icon:"email"},totp_sms:{id:"totp_sms",type:"totp",identityType:"phone",name:"Text message",description:"Get a one-time code via SMS",icon:"sms"},totp_voice:{id:"totp_voice",type:"totp",identityType:"phone",name:"Voice call",description:"Get a one-time code via phone call",icon:"phone"},passkey:{id:"passkey",type:"passkey",identityType:"email",name:"Passkey",description:"Use biometrics or security key",icon:"passkey"},sparklink:{id:"sparklink",type:"magic_link",identityType:"email",name:"SparkLink",description:"Get an instant sign-in magic link via email",icon:"link"},social_google:{id:"social_google",type:"social",identityType:"email",name:"Google",description:"Sign in with Google",icon:"google",provider:"google"},social_apple:{id:"social_apple",type:"social",identityType:"email",name:"Apple",description:"Sign in with Apple",icon:"apple",provider:"apple"},social_microsoft:{id:"social_microsoft",type:"social",identityType:"email",name:"Microsoft",description:"Sign in with Microsoft",icon:"microsoft",provider:"microsoft"},social_github:{id:"social_github",type:"social",identityType:"email",name:"GitHub",description:"Sign in with GitHub",icon:"github",provider:"github"},social_facebook:{id:"social_facebook",type:"social",identityType:"email",name:"Facebook",description:"Sign in with Facebook",icon:"facebook",provider:"facebook"},social_linkedin:{id:"social_linkedin",type:"social",identityType:"email",name:"LinkedIn",description:"Sign in with LinkedIn",icon:"linkedin",provider:"linkedin"},enterprise_okta:{id:"enterprise_okta",type:"enterprise",identityType:"email",name:"Okta",description:"Sign in with Okta SSO",icon:"okta",provider:"okta"},enterprise_entra:{id:"enterprise_entra",type:"enterprise",identityType:"email",name:"Microsoft Entra",description:"Sign in with Microsoft Entra ID",icon:"microsoft",provider:"entra"},enterprise_onelogin:{id:"enterprise_onelogin",type:"enterprise",identityType:"email",name:"OneLogin",description:"Sign in with OneLogin SSO",icon:"onelogin",provider:"onelogin"},enterprise_ping:{id:"enterprise_ping",type:"enterprise",identityType:"email",name:"Ping Identity",description:"Sign in with Ping Identity",icon:"ping",provider:"ping"},enterprise_jumpcloud:{id:"enterprise_jumpcloud",type:"enterprise",identityType:"email",name:"JumpCloud",description:"Sign in with JumpCloud SSO",icon:"jumpcloud",provider:"jumpcloud"},hris_bamboohr:{id:"hris_bamboohr",type:"hris",identityType:"email",name:"BambooHR",description:"Sign in with BambooHR",icon:"bamboohr",provider:"bamboohr"},hris_workday:{id:"hris_workday",type:"hris",identityType:"email",name:"Workday",description:"Sign in with Workday",icon:"workday",provider:"workday"},hris_adp:{id:"hris_adp",type:"hris",identityType:"email",name:"ADP",description:"Sign in with ADP",icon:"adp",provider:"adp"},hris_gusto:{id:"hris_gusto",type:"hris",identityType:"email",name:"Gusto",description:"Sign in with Gusto",icon:"gusto",provider:"gusto"},hris_rippling:{id:"hris_rippling",type:"hris",identityType:"email",name:"Rippling",description:"Sign in with Rippling",icon:"rippling",provider:"rippling"}};function E(e){return e.map(e=>C[e]).filter(e=>void 0!==e)}class S{constructor(){this._sdkConfig=null,this._viewState={view:"loading"},this._recipient="",this._identityType="email",this._passkey={hasPasskey:null,isFallbackMode:!1,pendingResult:null},this._totp={kindling:"",method:null},this.listeners=new Set}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(const e of this.listeners)e(this._viewState)}get sdkConfig(){return this._sdkConfig}setConfig(e){this._sdkConfig=e}get accountId(){return this._sdkConfig?.accountId??""}getAvailableMethods(){if(!this._sdkConfig)return[];let e=E(this._sdkConfig.methods??[]);return e="phone"===this._identityType?e.filter(e=>"totp"===e.type&&"totp_sms"===e.id):e.filter(e=>"email"===e.identityType),e}isPasskeyEnabled(){return this._sdkConfig?.methods?.includes("passkey")??!1}get viewState(){return this._viewState}setViewState(e){this._viewState=e,this.notify()}get recipient(){return this._recipient}get identityType(){return this._identityType}setIdentity(e,t){this._recipient=e,this._identityType=t}getAllowedIdentityTypes(){return this._sdkConfig?.allowedIdentityTypes??["email"]}get passkey(){return this._passkey}setPasskeyStatus(e){this._passkey.hasPasskey=e}enablePasskeyFallback(){this._passkey.isFallbackMode=!0}setPendingResult(e){this._passkey.pendingResult=e}shouldShowPasskeyPrompt(){return"email"===this._identityType&&(!!this.isPasskeyEnabled()&&(!this.isPasskeyPromptDismissed()&&!0!==this._passkey.hasPasskey))}isPasskeyPromptDismissed(){return null!==function(e){const t=document.cookie.match(new RegExp(`(^| )${e}=([^;]+)`));return t?t[2]:null}(`sv_passkey_prompt_dismissed_${this.accountId}`)}dismissPasskeyPrompt(){!function(e,t,n){const i=new Date;i.setTime(i.getTime()+24*n*60*60*1e3);const s=`expires=${i.toUTCString()}`;document.cookie=`${e}=${t}; ${s}; path=/; SameSite=Lax`}(`sv_passkey_prompt_dismissed_${this.accountId}`,"1",30)}get totp(){return this._totp}setKindling(e){this._totp.kindling=e}setTotpMethod(e){this._totp.method=e}reset(){this._viewState={view:"loading"},this._recipient="",this._identityType="email",this._passkey.hasPasskey=null,this._passkey.isFallbackMode=!1,this._passkey.pendingResult=null,this._totp.kindling="",this._totp.method=null}}class T{constructor(e,t){this.api=e,this.state=t}async checkPasskey(){try{const e=await this.api.checkPasskey(this.state.recipient);return this.state.setPasskeyStatus(e.hasPasskey),{emailValid:e.email_valid,hasPasskey:e.hasPasskey}}catch(e){return console.warn("Passkey check failed:",e),this.state.setPasskeyStatus(null),null}}async register(){try{const e=await this.api.startPasskeyRegister(this.state.recipient),t={challenge:k(e.challenge),rp:{id:e.rpId,name:e.rpName},user:{id:k(e.userId??this.state.recipient),name:this.state.recipient,displayName:this.state.recipient},pubKeyCredParams:[{type:"public-key",alg:-7},{type:"public-key",alg:-257}],timeout:e.timeout,authenticatorSelection:{residentKey:"preferred",userVerification:"preferred"},attestation:"none"},n=await navigator.credentials.create({publicKey:t});if(!n)return{success:!1,error:"Failed to create passkey",errorType:"unknown"};const i=await this.api.completePasskeyRegister({session:e.session,credential:n});return this.state.setPasskeyStatus(!0),{success:!0,result:{token:i.token,identity:i.identity,identityType:i.identity_type}}}catch(e){return this.handleError(e)}}async verify(){try{const e=await this.api.startPasskeyVerify(this.state.recipient),t={challenge:k(e.challenge),rpId:e.rpId,timeout:e.timeout,userVerification:"preferred",allowCredentials:e.allowCredentials?.map(e=>({id:k(e.id),type:e.type,transports:["internal","hybrid","usb","ble","nfc"]}))},n=await navigator.credentials.get({publicKey:t});if(!n)return{success:!1,error:"Failed to verify passkey",errorType:"unknown"};const i=await this.api.completePasskeyVerify({session:e.session,credential:n});return{success:!0,result:{token:i.token,identity:i.identity,identityType:i.identity_type}}}catch(e){return this.handleError(e)}}handleError(e){const t=e instanceof Error?e.message:String(e);return t.includes("not allowed")||t.includes("cancelled")?{success:!1,error:"Authentication was cancelled. Please try again.",errorType:"cancelled"}:t.includes("No credentials")?{success:!1,error:"No passkey found. Create one to continue.",errorType:"not_found"}:{success:!1,error:t||"Passkey authentication failed",errorType:"unknown"}}}class B{constructor(e,t){this.api=e,this.state=t}async send(e){try{const t=await this.api.sendTotp({recipient:this.state.recipient,method:e});return this.state.setKindling(t.kindling),this.state.setTotpMethod(e),{success:!0,kindling:t.kindling,expiresAt:t.expires_at}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to send code"}}}async resend(){const e=this.state.totp.method;if(!e)return{success:!1,error:"No TOTP method set"};try{const t=await this.api.sendTotp({recipient:this.state.recipient,method:e});return this.state.setKindling(t.kindling),{success:!0,kindling:t.kindling,expiresAt:t.expires_at}}catch(e){return{success:!1,error:`Failed to resend: ${e instanceof Error?e.message:"Failed to resend code"}`}}}async verify(e){const t=this.state.totp.kindling;if(!t)return{success:!1,error:"No kindling available"};try{const n=await this.api.verifyTotp({kindling:t,pin:e,recipient:this.state.recipient});return n.verified&&n.token?{success:!0,result:{token:n.token,identity:n.identity??this.state.recipient,identityType:n.identity_type??this.state.identityType}}:(n.kindling&&this.state.setKindling(n.kindling),{success:!1,newKindling:n.kindling,retryAfter:n.retry_after,backoffExpires:n.expires_at,error:"Invalid code. Please try again."})}catch(e){return{success:!1,error:e instanceof Error?e.message:"Verification failed"}}}}class L{constructor(e,t){this.api=e,this.state=t}async send(){try{const e=await this.api.sendSparkLink(this.state.recipient);return{success:!0,sparkId:e.sparkId,expiresAt:e.expiresAt}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to send SparkLink"}}}async checkStatus(e){try{const t=await this.api.checkSparkLinkStatus(e);return{verified:t.verified,token:t.token,identity:t.identity,identityType:t.identityType}}catch{return{verified:!1}}}}const A="sparkvault-identity-styles";function P(e){if(document.getElementById(A))return e.branding,void function(e){const t=document.getElementById("sparkvault-identity-overlay");t&&(!1!==e?t.classList.add("sv-blur"):t.classList.remove("sv-blur"))}(e.backdropBlur);const t=document.createElement("style");t.id=A,t.textContent=function(e){const{branding:t,backdropBlur:n}=e,i="dark"===_(t),s=!1!==n,o={primary:"#4F46E5",primaryHover:"#4338CA",primaryLight:i?"rgba(99, 102, 241, 0.15)":"rgba(79, 70, 229, 0.08)",error:"#DC2626",errorLight:i?"rgba(220, 38, 38, 0.15)":"#FEF2F2",errorBorder:i?"rgba(220, 38, 38, 0.3)":"#FECACA",bg:i?"#0F0F0F":"#FFFFFF",bgSubtle:i?"#171717":"#FAFAFA",bgHover:i?"#1A1A1A":"#F5F5F5",bgInput:i?"#0F0F0F":"#FFFFFF",border:i?"#262626":"#E5E5E5",borderHover:i?"#404040":"#D4D4D4",borderFocus:"#4F46E5",textPrimary:i?"#FAFAFA":"#0A0A0A",textSecondary:i?"#A3A3A3":"#525252",textMuted:"#737373",textOnPrimary:"#FFFFFF",shadowSm:i?"0 1px 2px rgba(0, 0, 0, 0.4)":"0 1px 2px rgba(0, 0, 0, 0.04)",shadowLg:i?"0 8px 24px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05)":"0 8px 24px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04)"};return`\n /* ========================================\n OVERLAY & MODAL CONTAINER\n ======================================== */\n\n .sv-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, ${i?"0.7":"0.5"});\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n padding: 16px;\n box-sizing: border-box;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n .sv-overlay.sv-blur {\n backdrop-filter: blur(${s?"8px":"0"});\n -webkit-backdrop-filter: blur(${s?"8px":"0"});\n }\n\n .sv-modal {\n background: ${o.bg};\n border-radius: 16px;\n box-shadow: ${o.shadowLg};\n width: 100%;\n max-width: 400px;\n max-height: calc(100vh - 32px);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n color: ${o.textPrimary};\n }\n\n /* ========================================\n HEADER\n ======================================== */\n\n .sv-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid ${o.border};\n background: ${o.bg};\n flex-shrink: 0;\n }\n\n .sv-header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n }\n\n .sv-logo {\n height: 28px;\n width: auto;\n max-width: 140px;\n object-fit: contain;\n flex-shrink: 0;\n }\n\n .sv-company-name {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sv-close-btn {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n color: ${o.textMuted};\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .sv-close-btn:hover {\n background: ${o.bgHover};\n color: ${o.textPrimary};\n }\n\n .sv-close-btn:focus-visible {\n outline: 2px solid ${o.borderFocus};\n outline-offset: 2px;\n }\n\n .sv-close-btn:active {\n transform: scale(0.96);\n }\n\n /* ========================================\n BODY\n ======================================== */\n\n .sv-body {\n padding: 24px;\n overflow-y: auto;\n flex: 1;\n }\n\n /* ========================================\n TYPOGRAPHY\n ======================================== */\n\n .sv-title {\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.02em;\n line-height: 1.3;\n margin: 0 0 6px 0;\n text-align: center;\n color: ${o.textPrimary};\n }\n\n .sv-subtitle {\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n color: ${o.textSecondary};\n margin: 0 0 16px 0;\n text-align: center;\n }\n\n .sv-subtitle strong {\n color: ${o.textPrimary};\n font-weight: 500;\n }\n\n /* ========================================\n FORM ELEMENTS\n ======================================== */\n\n .sv-form-group {\n margin-bottom: 16px;\n }\n\n .sv-label {\n display: block;\n font-size: 13px;\n font-weight: 500;\n letter-spacing: -0.005em;\n margin-bottom: 6px;\n color: ${o.textPrimary};\n }\n\n .sv-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.4;\n border: 1px solid ${o.border};\n border-radius: 8px;\n background: ${o.bgInput};\n color: ${o.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-input:hover:not(:focus):not(:disabled) {\n border-color: ${o.borderHover};\n }\n\n .sv-input:focus {\n outline: none;\n border-color: ${o.borderFocus};\n box-shadow: 0 0 0 3px ${o.primaryLight};\n }\n\n .sv-input::placeholder {\n color: ${o.textMuted};\n }\n\n .sv-input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-input.sv-input-error,\n .sv-input.sv-email-input-error {\n border-color: ${o.error};\n }\n\n .sv-input.sv-input-error:focus,\n .sv-input.sv-email-input-error:focus {\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\n }\n\n /* ========================================\n BUTTONS\n ======================================== */\n\n .sv-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n letter-spacing: -0.005em;\n line-height: 1.4;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n\n .sv-btn:focus-visible {\n outline: 2px solid ${o.borderFocus};\n outline-offset: 2px;\n }\n\n .sv-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-btn:active:not(:disabled) {\n transform: scale(0.98);\n }\n\n /* Primary Button */\n .sv-btn-primary,\n .sv-btn-email-primary {\n background: ${o.primary};\n color: ${o.textOnPrimary};\n box-shadow: ${o.shadowSm};\n }\n\n .sv-btn-primary:hover:not(:disabled),\n .sv-btn-email-primary:hover:not(:disabled) {\n background: ${o.primaryHover};\n }\n\n /* Secondary Button */\n .sv-btn-secondary {\n background: ${o.bgSubtle};\n color: ${o.textPrimary};\n border: 1px solid ${o.border};\n }\n\n .sv-btn-secondary:hover:not(:disabled) {\n background: ${o.bgHover};\n border-color: ${o.borderHover};\n }\n\n /* Method Button */\n .sv-btn-method {\n background: ${o.bg};\n border: 1px solid ${o.border};\n color: ${o.textPrimary};\n text-align: left;\n padding: 12px 14px;\n margin-bottom: 8px;\n }\n\n .sv-btn-method:hover:not(:disabled) {\n background: ${o.bgSubtle};\n border-color: ${o.borderHover};\n }\n\n .sv-btn-method:last-child {\n margin-bottom: 0;\n }\n\n /* Error Buttons */\n .sv-btn-error-primary {\n background: ${o.error};\n color: ${o.textOnPrimary};\n box-shadow: ${o.shadowSm};\n }\n\n .sv-btn-error-primary:hover:not(:disabled) {\n background: #B91C1C;\n }\n\n .sv-btn-error-secondary {\n background: ${o.bgSubtle};\n color: ${o.textSecondary};\n border: 1px solid ${o.border};\n }\n\n .sv-btn-error-secondary:hover:not(:disabled) {\n background: ${o.bgHover};\n color: ${o.textPrimary};\n }\n\n /* ========================================\n METHOD SELECTION\n ======================================== */\n\n .sv-method-content {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n }\n\n .sv-method-icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: ${o.textSecondary};\n }\n\n .sv-method-icon svg {\n width: 20px;\n height: 20px;\n }\n\n .sv-method-text {\n flex: 1;\n min-width: 0;\n }\n\n .sv-method-name {\n font-weight: 500;\n font-size: 14px;\n color: ${o.textPrimary};\n }\n\n .sv-method-description {\n font-size: 12px;\n color: ${o.textMuted};\n margin-top: 1px;\n }\n\n /* ========================================\n TOTP INPUT\n ======================================== */\n\n .sv-totp-input-group {\n display: flex;\n gap: 8px;\n justify-content: center;\n margin-bottom: 16px;\n }\n\n .sv-totp-digit {\n width: 44px;\n height: 52px;\n text-align: center;\n font-size: 20px;\n font-weight: 600;\n letter-spacing: 0;\n border: 1px solid ${o.border};\n border-radius: 8px;\n background: ${o.bgInput};\n color: ${o.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-totp-digit:hover:not(:focus):not(:disabled) {\n border-color: ${o.borderHover};\n }\n\n .sv-totp-digit:focus {\n outline: none;\n border-color: ${o.borderFocus};\n box-shadow: 0 0 0 3px ${o.primaryLight};\n }\n\n .sv-totp-digit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* ========================================\n BACK LINK\n ======================================== */\n\n .sv-back-link {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: ${o.textSecondary};\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n margin-bottom: 16px;\n transition: color 0.15s ease;\n }\n\n .sv-back-link:hover:not(:disabled) {\n color: ${o.primary};\n }\n\n .sv-back-link:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-back-link svg {\n width: 14px;\n height: 14px;\n }\n\n /* ========================================\n ERROR MESSAGE\n ======================================== */\n\n .sv-error {\n background: ${o.errorLight};\n border: 1px solid ${o.errorBorder};\n color: ${o.error};\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 450;\n margin-bottom: 16px;\n }\n\n /* ========================================\n LOADING STATE\n ======================================== */\n\n .sv-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n gap: 16px;\n }\n\n .sv-spinner {\n width: 28px;\n height: 28px;\n border: 2.5px solid ${o.border};\n border-top-color: ${o.primary};\n border-radius: 50%;\n animation: sv-spin 0.7s linear infinite;\n }\n\n .sv-loading-text {\n font-size: 14px;\n color: ${o.textSecondary};\n margin: 0;\n }\n\n @keyframes sv-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ========================================\n FOOTER\n ======================================== */\n\n .sv-footer {\n padding: 10px 20px;\n border-top: 1px solid ${o.border};\n text-align: center;\n background: ${o.bgSubtle};\n flex-shrink: 0;\n }\n\n .sv-footer-text {\n font-size: 10px;\n color: ${o.textMuted};\n letter-spacing: 0.02em;\n }\n\n .sv-footer-link {\n color: ${o.textSecondary};\n text-decoration: none;\n font-weight: 500;\n transition: color 0.15s ease;\n }\n\n .sv-footer-link:hover {\n color: ${o.primary};\n }\n\n /* ========================================\n IDENTITY INPUT VIEW\n ======================================== */\n\n .sv-email-view {\n display: flex;\n flex-direction: column;\n }\n\n .sv-email-header {\n margin-bottom: 16px;\n }\n\n .sv-email-subtitle {\n font-size: 14px;\n font-weight: 500;\n line-height: 1.4;\n color: ${o.textSecondary};\n margin: 0;\n }\n\n .sv-email-error-container {\n width: 100%;\n }\n\n .sv-email-form {\n width: 100%;\n }\n\n .sv-email-input-wrapper {\n margin-bottom: 14px;\n }\n\n .sv-email-label {\n display: block;\n font-size: 13px;\n font-weight: 500;\n letter-spacing: -0.005em;\n margin-bottom: 6px;\n color: ${o.textPrimary};\n }\n\n .sv-email-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.4;\n border: 1px solid ${o.border};\n border-radius: 8px;\n background: ${o.bgInput};\n color: ${o.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-email-input:hover:not(:focus):not(:disabled) {\n border-color: ${o.borderHover};\n }\n\n .sv-email-input:focus {\n outline: none;\n border-color: ${o.borderFocus};\n box-shadow: 0 0 0 3px ${o.primaryLight};\n }\n\n .sv-email-input::placeholder {\n color: ${o.textMuted};\n }\n\n .sv-email-input-error {\n border-color: ${o.error};\n }\n\n .sv-email-input-error:focus {\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\n }\n\n /* ========================================\n ERROR VIEW\n ======================================== */\n\n .sv-error-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n }\n\n .sv-error-icon-container {\n margin-bottom: 16px;\n }\n\n .sv-error-icon {\n width: 48px;\n height: 48px;\n }\n\n .sv-error-content {\n margin-bottom: 24px;\n }\n\n .sv-error-title {\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.02em;\n margin: 0 0 8px 0;\n color: ${o.textPrimary};\n }\n\n .sv-error-message {\n font-size: 14px;\n line-height: 1.5;\n color: ${o.textSecondary};\n margin: 0 0 16px 0;\n }\n\n .sv-error-code-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n background: ${o.errorLight};\n border: 1px solid ${o.errorBorder};\n border-radius: 6px;\n }\n\n .sv-error-code-label {\n font-size: 10px;\n font-weight: 600;\n color: ${i?"#F87171":"#991B1B"};\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .sv-error-code-value {\n font-size: 11px;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', monospace;\n color: ${o.error};\n font-weight: 500;\n }\n\n .sv-error-actions {\n display: flex;\n gap: 10px;\n width: 100%;\n }\n\n .sv-error-actions .sv-btn {\n flex: 1;\n }\n\n /* ========================================\n TOTP VIEW\n ======================================== */\n\n .sv-resend-container {\n text-align: center;\n margin-top: 16px;\n }\n\n /* ========================================\n PASSKEY VIEW\n ======================================== */\n\n .sv-passkey-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n display: block;\n }\n\n .sv-passkey-description {\n font-size: 13px;\n color: ${o.textMuted};\n text-align: center;\n margin: 0 0 16px 0;\n line-height: 1.4;\n }\n\n .sv-fallback-link {\n display: block;\n width: 100%;\n text-align: center;\n color: ${o.textSecondary};\n font-size: 13px;\n font-weight: 400;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 12px 0 0 0;\n margin-top: 8px;\n transition: color 0.15s ease;\n }\n\n .sv-fallback-link:hover {\n color: ${o.primary};\n text-decoration: underline;\n }\n\n /* ========================================\n PASSKEY PROMPT VIEW\n ======================================== */\n\n .sv-passkey-prompt-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n display: block;\n color: ${o.primary};\n }\n\n .sv-passkey-prompt-benefits {\n background: ${o.bgSubtle};\n border-radius: 8px;\n padding: 10px 14px;\n margin-bottom: 16px;\n }\n\n .sv-passkey-prompt-benefits ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .sv-passkey-prompt-benefits li {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 13px;\n color: ${o.textSecondary};\n padding: 6px 0;\n }\n\n .sv-passkey-prompt-benefits li svg {\n width: 16px;\n height: 16px;\n color: ${o.primary};\n flex-shrink: 0;\n }\n\n .sv-skip-link {\n display: block;\n width: 100%;\n text-align: center;\n color: ${o.textMuted};\n font-size: 13px;\n font-weight: 400;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 12px 0 0 0;\n transition: color 0.15s ease;\n }\n\n .sv-skip-link:hover {\n color: ${o.textSecondary};\n text-decoration: underline;\n }\n\n /* ========================================\n SPARKLINK WAITING VIEW\n ======================================== */\n\n .sv-sparklink-icon-container {\n display: flex;\n justify-content: center;\n margin-bottom: 16px;\n }\n\n .sv-sparklink-icon {\n width: 56px;\n height: 56px;\n color: ${o.primary};\n background: ${o.primaryLight};\n padding: 14px;\n border-radius: 50%;\n box-sizing: content-box;\n }\n\n .sv-sparklink-waiting {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n background: ${o.bgSubtle};\n border-radius: 10px;\n padding: 14px 18px;\n margin: 16px 0;\n }\n\n .sv-spinner-small {\n width: 18px;\n height: 18px;\n border: 2px solid ${o.border};\n border-top-color: ${o.primary};\n border-radius: 50%;\n animation: sv-spin 0.7s linear infinite;\n flex-shrink: 0;\n }\n\n .sv-sparklink-waiting-text {\n font-size: 13px;\n font-weight: 450;\n color: ${o.textSecondary};\n }\n\n .sv-sparklink-countdown {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 13px;\n color: ${o.textMuted};\n margin-bottom: 20px;\n }\n\n .sv-sparklink-countdown-time {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', monospace;\n font-weight: 600;\n font-size: 14px;\n color: ${o.textPrimary};\n min-width: 40px;\n }\n\n .sv-sparklink-fallback {\n text-align: center;\n margin-top: 12px;\n padding-top: 16px;\n border-top: 1px solid ${o.border};\n }\n\n .sv-sparklink-fallback .sv-back-link {\n margin-bottom: 0;\n font-size: 12px;\n color: ${o.textMuted};\n }\n\n .sv-sparklink-fallback .sv-back-link:hover:not(:disabled) {\n color: ${o.textSecondary};\n }\n\n /* SparkLink Expired State */\n .sv-sparklink-expired {\n flex-direction: column;\n gap: 12px;\n background: ${o.bgSubtle};\n border: 1px solid ${o.border};\n }\n\n .sv-sparklink-expired-icon {\n display: flex;\n justify-content: center;\n }\n\n .sv-sparklink-expired-icon svg {\n width: 48px;\n height: 48px;\n }\n\n .sv-sparklink-expired-text {\n font-size: 14px;\n font-weight: 500;\n color: ${o.textSecondary};\n text-align: center;\n }\n\n .sv-expired-icon {\n width: 48px;\n height: 48px;\n }\n\n /* ========================================\n DIVIDER\n ======================================== */\n\n .sv-divider {\n display: flex;\n align-items: center;\n margin: 20px 0;\n }\n\n .sv-divider::before,\n .sv-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: ${o.border};\n }\n\n .sv-divider-text {\n padding: 0 12px;\n font-size: 12px;\n color: ${o.textMuted};\n }\n\n /* ========================================\n ACCESSIBILITY\n ======================================== */\n\n .sv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ========================================\n INLINE CONTAINER\n ======================================== */\n\n .sv-inline-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: ${o.bg};\n color: ${o.textPrimary};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n border-radius: 12px;\n border: 1px solid ${o.border};\n overflow: hidden;\n }\n\n .sv-inline-header {\n border-bottom: 1px solid ${o.border};\n }\n\n .sv-inline-body {\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-height: 200px;\n flex: 1;\n }\n\n /* ========================================\n RESPONSIVE\n ======================================== */\n\n @media (max-width: 480px) {\n .sv-modal {\n max-width: 100%;\n max-height: 100%;\n border-radius: 0;\n }\n\n .sv-overlay {\n padding: 0;\n }\n\n .sv-body {\n padding: 24px;\n }\n\n .sv-totp-digit {\n width: 40px;\n height: 48px;\n font-size: 18px;\n }\n\n .sv-error-actions {\n flex-direction: column;\n }\n }\n\n @media (max-width: 360px) {\n .sv-totp-input-group {\n gap: 6px;\n }\n\n .sv-totp-digit {\n width: 36px;\n height: 44px;\n font-size: 16px;\n }\n }\n `}(e),document.head.appendChild(t)}function _(e){return e?.themeMode??"light"}function I(e,t=16,n=16){const i=document.createElementNS("http://www.w3.org/2000/svg","svg");return i.setAttribute("viewBox",e),i.setAttribute("width",String(t)),i.setAttribute("height",String(n)),i.setAttribute("fill","none"),i.setAttribute("xmlns","http://www.w3.org/2000/svg"),i}function $(e,t={}){const n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d",e);for(const[e,i]of Object.entries(t))n.setAttribute(e,i);return n}function F(e,t,n,i={}){const s=document.createElementNS("http://www.w3.org/2000/svg","circle");s.setAttribute("cx",String(e)),s.setAttribute("cy",String(t)),s.setAttribute("r",String(n));for(const[e,t]of Object.entries(i))s.setAttribute(e,t);return s}function H(){const e=I("0 0 16 16");return e.appendChild($("M13.25 4.75L6 12 2.75 8.75",{stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})),e}function M(){const e=I("0 0 16 16");return e.appendChild($("M10 12L6 8L10 4",{stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})),e}function N(){const e=I("0 0 20 20",20,20);return e.appendChild($("M15 5L5 15M5 5L15 15",{stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"})),e}function R(){const e=I("0 0 56 56",56,56);e.classList.add("sv-passkey-icon"),e.appendChild(F(28,28,26,{fill:"#EEF2FF",stroke:"#E0E7FF","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.setAttribute("transform","translate(16, 16)"),t.appendChild($("M12 8c-2.21 0-4 1.79-4 4 0 1.56.9 2.93 2.21 3.6L10 20v2h4v-2l-.21-4.4C15.1 14.93 16 13.56 16 12c0-2.21-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z",{fill:"#4F46E5"})),e.appendChild(t),e}function O(e){switch(e){case"email":default:return z();case"phone":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M18 14v2.5a1.5 1.5 0 01-1.64 1.5 14.85 14.85 0 01-6.47-2.3 14.63 14.63 0 01-4.5-4.5A14.85 14.85 0 013.1 4.64 1.5 1.5 0 014.59 3H7.1a1.5 1.5 0 011.5 1.29 9.63 9.63 0 00.52 2.11 1.5 1.5 0 01-.34 1.58l-.95.95a12 12 0 004.5 4.5l.95-.95a1.5 1.5 0 011.58-.34 9.63 9.63 0 002.11.52A1.5 1.5 0 0118 14z")),e}();case"fingerprint":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M2 10c0-4.42 3.58-8 8-8 2.65 0 5 1.29 6.47 3.28")),e.appendChild($("M4 16.58c.42-.35.79-.76 1.1-1.22")),e.appendChild($("M14.41 17.51c.09-.45.32-1.73.38-2.26")),e.appendChild($("M10 8.33a1.5 1.5 0 00-1.5 1.5c0 .77-.08 1.88-.2 3")),e.appendChild($("M7.21 18.33c.16-.5.34-1 .43-1.5")),e.appendChild($("M11.67 10.93c0 1.79 0 4.79-.75 6.65")),e.appendChild($("M17.33 13.33c.15-1.5.1-4.02 0-4.5")),e.appendChild($("M7.5 5.67a4.5 4.5 0 016.75 3.9c0 .35 0 .88-.02 1.5")),e}();case"link":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M8.33 10.83a3.75 3.75 0 005.66.41l2.25-2.25a3.75 3.75 0 00-5.3-5.3l-1.29 1.28")),e.appendChild($("M11.67 9.17a3.75 3.75 0 00-5.66-.41l-2.25 2.25a3.75 3.75 0 005.3 5.3l1.28-1.28")),e}();case"google":return function(){const e=I("0 0 20 20",20,20);return e.appendChild($("M18.8 10.21c0-.65-.06-1.28-.17-1.88H10v3.55h4.93c-.21 1.14-.87 2.11-1.84 2.76v2.3h2.98c1.73-1.6 2.73-3.96 2.73-6.73z",{fill:"#4285F4"})),e.appendChild($("M10 19.17c2.48 0 4.55-.82 6.07-2.23l-2.98-2.3c-.82.55-1.86.88-3.09.88-2.38 0-4.4-1.6-5.13-3.77H1.82v2.37c1.52 3.02 4.6 5.05 8.18 5.05z",{fill:"#34A853"})),e.appendChild($("M4.87 11.74c-.18-.55-.29-1.14-.29-1.74s.1-1.19.29-1.74V5.89H1.82c-.6 1.23-.94 2.6-.94 4.11s.34 2.88.94 4.11l3.05-2.37z",{fill:"#FBBC05"})),e.appendChild($("M10 4.48c1.35 0 2.55.47 3.5 1.37l2.63-2.63C14.53 1.74 12.47.83 10 .83c-3.58 0-6.66 2.03-8.18 5.05l3.05 2.37c.72-2.17 2.75-3.77 5.13-3.77z",{fill:"#EA4335"})),e}();case"apple":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("fill","currentColor"),e.appendChild($("M14.21 16.9c-.82.79-1.71.67-2.57.29-.91-.38-1.74-.4-2.7 0-1.2.51-1.83.37-2.55-.29C2.7 12.71 3.3 6.33 7.54 6.09c1.13.06 1.91.61 2.57.66.98-.2 1.92-.78 2.97-.7 1.26.1 2.21.6 2.83 1.5-2.6 1.56-1.98 4.99.4 5.94-.48 1.25-1.09 2.49-2.11 3.41h.01zM10.02 6.04c-.12-1.86 1.38-3.39 3.11-3.54.24 2.15-1.95 3.75-3.11 3.54z")),e}();case"microsoft":return function(){const e=I("0 0 20 20",20,20);return e.appendChild($("M1 1h8.33v8.33H1z",{fill:"#F25022"})),e.appendChild($("M1 10.67h8.33V19H1z",{fill:"#00A4EF"})),e.appendChild($("M10.67 1H19v8.33h-8.33z",{fill:"#7FBA00"})),e.appendChild($("M10.67 10.67H19V19h-8.33z",{fill:"#FFB900"})),e}();case"github":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("fill","currentColor"),e.appendChild($("M10 0C4.48 0 0 4.48 0 10c0 4.42 2.86 8.17 6.84 9.49.5.09.68-.22.68-.48 0-.24-.01-1.02-.01-1.86-2.51.46-3.16-.61-3.36-1.18-.11-.29-.6-1.18-1.02-1.41-.35-.19-.85-.65-.01-.66.79-.01 1.35.72 1.54 1.02.9 1.51 2.34 1.09 2.91.83.09-.65.35-1.09.64-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.99 1.02-2.69-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02.8-.22 1.65-.33 2.5-.33s1.7.11 2.5.33c1.91-1.3 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.02 1.59 1.02 2.69 0 3.84-2.34 4.69-4.57 4.94.36.31.67.91.67 1.85 0 1.34-.01 2.41-.01 2.75 0 .27.18.58.69.48C17.14 18.16 20 14.42 20 10c0-5.52-4.48-10-10-10z")),e}();case"facebook":return function(){const e=I("0 0 20 20",20,20);return e.appendChild($("M20 10.06c0-5.52-4.48-10-10-10S0 4.53 0 10.06c0 4.99 3.66 9.13 8.44 9.88v-6.99H5.9v-2.89h2.54V7.85c0-2.51 1.49-3.89 3.78-3.89 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.77-1.63 1.56v1.88h2.77l-.44 2.89h-2.33v6.99c4.78-.75 8.44-4.89 8.44-9.88z",{fill:"#1877F2"})),e}();case"linkedin":return function(){const e=I("0 0 20 20",20,20);return e.appendChild($("M17.04 17.04h-2.96v-4.64c0-1.11-.02-2.53-1.54-2.53-1.55 0-1.78 1.2-1.78 2.45v4.73H7.8V7.5h2.84v1.3h.04c.4-.75 1.36-1.54 2.81-1.54 3 0 3.56 1.98 3.56 4.55v5.24zM4.45 6.19c-.95 0-1.72-.77-1.72-1.72s.77-1.72 1.72-1.72 1.72.77 1.72 1.72-.77 1.72-1.72 1.72zm1.48 10.85H2.96V7.5h2.97v9.54zM18.52 0H1.47C.66 0 0 .65 0 1.44v17.12c0 .79.66 1.44 1.48 1.44h17.04c.82 0 1.48-.65 1.48-1.44V1.44c0-.79-.66-1.44-1.48-1.44z",{fill:"#0A66C2"})),e}();case"building":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M2.5 17.5h15")),e.appendChild($("M4.17 17.5V5.83L10.83 2.5v15")),e.appendChild($("M15.83 17.5V9.17l-5-3.33")),e.appendChild($("M7.5 7.5v.01")),e.appendChild($("M7.5 10v.01")),e.appendChild($("M7.5 12.5v.01")),e.appendChild($("M7.5 15v.01")),e}();case"users":return function(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M14.17 17.5v-1.67a3.33 3.33 0 00-3.34-3.33H4.17a3.33 3.33 0 00-3.34 3.33v1.67")),e.appendChild(F(7.5,5.83,3.33,{stroke:"currentColor","stroke-width":"1.5",fill:"none"})),e.appendChild($("M19.17 17.5v-1.67a3.33 3.33 0 00-2.5-3.22")),e.appendChild($("M13.33 2.6a3.33 3.33 0 010 6.46")),e}()}}function z(){const e=I("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild($("M3 4h14c.55 0 1 .45 1 1v10c0 .55-.45 1-1 1H3c-.55 0-1-.45-1-1V5c0-.55.45-1 1-1z")),e.appendChild($("M18 5l-8 5.5L2 5")),e}const V={companyName:"",logoLight:null,logoDark:null};class D{constructor(){this.elements=null,this.onCloseCallback=null,this.keydownHandler=null,this.overlayClickHandler=null,this.closeBtnClickHandler=null,this.closeBtn=null,this.backdropBlur=!0,this.effectiveTheme="light",this.headerElement=null}createLoading(e,t){return this.create({branding:V,backdropBlur:e.backdropBlur},t)}updateBranding(e){if(!this.elements)return;this.effectiveTheme=_(e);const t=this.createHeader(e);this.headerElement?.parentNode&&this.headerElement.parentNode.replaceChild(t,this.headerElement),this.headerElement=t}updateBackdropBlur(e){this.elements&&(this.backdropBlur=e,e?this.elements.overlay.classList.add("sv-blur"):this.elements.overlay.classList.remove("sv-blur"))}create(e,t){if(this.elements)return this.elements;this.onCloseCallback=t,this.backdropBlur=!1!==e.backdropBlur,this.effectiveTheme=_(e.branding);P({branding:e.branding,backdropBlur:e.backdropBlur});const n=document.createElement("div");n.id="sparkvault-identity-overlay",n.className=this.backdropBlur?"sv-overlay sv-blur":"sv-overlay",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-labelledby","sv-modal-title");const i=document.createElement("div");i.id="sparkvault-identity-modal",i.className="sv-modal";const s=this.createHeader(e.branding);this.headerElement=s;const o=document.createElement("div");o.className="sv-body";const r=document.createElement("div");r.className="sv-footer";const a=document.createElement("span");a.className="sv-footer-text",a.appendChild(document.createTextNode("Secured by "));const l=document.createElement("a");l.href="https://sparkvault.com",l.target="_blank",l.rel="noopener noreferrer",l.className="sv-footer-link",l.textContent="SparkVault",a.appendChild(l),r.appendChild(a),i.appendChild(s),i.appendChild(o),i.appendChild(r),n.appendChild(i),this.overlayClickHandler=e=>{e.target===n&&this.handleClose()},n.addEventListener("click",this.overlayClickHandler),this.keydownHandler=e=>{"Escape"===e.key&&this.handleClose()},document.addEventListener("keydown",this.keydownHandler),document.body.appendChild(n),document.body.style.overflow="hidden",this.elements={overlay:n,modal:i,header:s,body:o,footer:r};const d=o.querySelector("input, button");return d instanceof HTMLElement&&d.focus(),this.elements}createHeader(e){const t=document.createElement("div");t.className="sv-header";const n=document.createElement("div");n.className="sv-header-title";const i="dark"===this.effectiveTheme?e.logoDark||e.logoLight:e.logoLight||e.logoDark;if(i){const t=document.createElement("img");t.className="sv-logo",t.src=i,t.alt=e.companyName,n.appendChild(t);const s=document.createElement("span");s.className="sv-sr-only",s.id="sv-modal-title",s.textContent=e.companyName,n.appendChild(s)}else{const t=document.createElement("h2");t.className="sv-company-name",t.id="sv-modal-title",t.textContent=e.companyName,n.appendChild(t)}return this.closeBtn=document.createElement("button"),this.closeBtn.className="sv-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.appendChild(N()),this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(n),t.appendChild(this.closeBtn),t}handleClose(){this.onCloseCallback&&this.onCloseCallback()}getBody(){return this.elements?.body??null}isOpen(){return null!==this.elements}destroy(){this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null),this.elements&&this.overlayClickHandler&&(this.elements.overlay.removeEventListener("click",this.overlayClickHandler),this.overlayClickHandler=null),this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.elements&&(this.elements.overlay.remove(),this.elements=null),this.headerElement=null,document.body.style.overflow="",this.onCloseCallback=null}}function j(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function U(e,t){const n=document.createElement("div");return e&&(n.className=e),n}function q(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function K(e){const t=document.createElement("div");return t.className="sv-error",t.setAttribute("role","alert"),t.textContent=e,t}function W(e){const t=e.trim().toLowerCase();return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&t.length<=254?t:null}function G(e){const t=e.trim().startsWith("+"),n=e.replace(/\D/g,"");return 10===n.length?`+1${n}`:11===n.length&&n.startsWith("1")||t&&n.length>=10&&n.length<=15?`+${n}`:null}function J(e){const t=e.replace(/\D/g,""),n=t.startsWith("1")&&t.length>10?t.slice(1):t;return 0===n.length?"":n.length<=3?`(${n}`:n.length<=6?`(${n.slice(0,3)}) ${n.slice(3)}`:`(${n.slice(0,3)}) ${n.slice(3,6)}-${n.slice(6,10)}`}class Y{constructor(e={}){this.message=e.message??"Loading..."}render(){const e=U("sv-loading"),t=document.createElement("div");t.className="sv-spinner",t.setAttribute("role","status"),t.setAttribute("aria-label","Loading");const n=document.createElement("p");return n.className="sv-loading-text",n.textContent=this.message,e.appendChild(t),e.appendChild(n),e}destroy(){}}class X{constructor(e){this.inputElement=null,this.labelElement=null,this.submitButton=null,this.errorContainer=null,this.focusTimeoutId=null,this.detectedType="email",this.props=e,this.boundHandleInput=()=>this.handleInput(),this.boundHandleKeyDown=e=>{"Enter"===e.key&&(e.preventDefault(),this.handleSubmit())},this.boundHandleSubmit=()=>this.handleSubmit()}get allowsBoth(){return this.props.allowedTypes.includes("email")&&this.props.allowedTypes.includes("phone")}get allowsEmail(){return this.props.allowedTypes.includes("email")}get allowsPhone(){return this.props.allowedTypes.includes("phone")}render(){const e=U("sv-email-view"),t=U("sv-email-header"),n=document.createElement("p");n.className="sv-email-subtitle",n.textContent=this.getSubtitleText(),t.appendChild(n),e.appendChild(t),this.errorContainer=U("sv-email-error-container"),this.props.error&&this.errorContainer.appendChild(K(this.props.error)),e.appendChild(this.errorContainer);const i=U("sv-email-form"),s=U("sv-email-input-wrapper");return this.labelElement=document.createElement("label"),this.labelElement.className="sv-email-label",this.labelElement.htmlFor="sv-identity-input",this.labelElement.textContent=this.getLabelText(),this.inputElement=document.createElement("input"),this.inputElement.type=this.allowsPhone&&!this.allowsEmail?"tel":"text",this.inputElement.id="sv-identity-input",this.inputElement.className="sv-email-input",this.inputElement.placeholder=this.getPlaceholderText(),this.inputElement.autocomplete=this.allowsBoth?"on":this.allowsEmail?"email":"tel",this.inputElement.required=!0,this.inputElement.maxLength=254,this.props.initialValue&&(this.inputElement.value=this.props.initialValue,this.detectAndUpdateType(this.props.initialValue)),this.inputElement.addEventListener("input",this.boundHandleInput),this.inputElement.addEventListener("keydown",this.boundHandleKeyDown),s.appendChild(this.labelElement),s.appendChild(this.inputElement),i.appendChild(s),this.submitButton=document.createElement("button"),this.submitButton.className="sv-btn sv-btn-email-primary",this.submitButton.textContent="Continue",this.submitButton.addEventListener("click",this.boundHandleSubmit),i.appendChild(this.submitButton),e.appendChild(i),this.focusTimeoutId=setTimeout(()=>this.inputElement?.focus(),50),e}getSubtitleText(){return this.allowsBoth?"Enter your email or phone to continue":this.allowsPhone?"Enter your phone number to continue":"Enter your email to continue"}getLabelText(){return this.allowsBoth?"phone"===this.detectedType?"Phone number":"Email address":this.allowsPhone?"Phone number":"Email address"}getPlaceholderText(){return this.allowsBoth?"you@example.com or (555) 123-4567":this.allowsPhone?"(555) 123-4567":"you@example.com"}handleInput(){if(this.clearError(),!this.inputElement)return;const e=this.inputElement.value;if(this.allowsBoth){const t="phone"===this.detectedType;if(this.detectAndUpdateType(e),"phone"===this.detectedType){const t=this.inputElement.selectionStart??e.length,n=J(e);if(n!==e){this.inputElement.value=n;const i=Math.min(t+(n.length-e.length),n.length);this.inputElement.setSelectionRange(i,i)}}t!==("phone"===this.detectedType)&&this.labelElement&&(this.labelElement.textContent=this.getLabelText())}else if(this.allowsPhone){const t=this.inputElement.selectionStart??e.length,n=J(e);if(n!==e){this.inputElement.value=n;const i=Math.min(t+(n.length-e.length),n.length);this.inputElement.setSelectionRange(i,i)}}}detectAndUpdateType(e){!function(e){const t=e.trim();return!!t&&/^[+(\d]/.test(t)&&!/[@.]/.test(t)}(e)?this.detectedType="email":this.detectedType="phone"}clearError(){this.errorContainer&&q(this.errorContainer),this.inputElement?.classList.remove("sv-email-input-error")}showError(e){this.errorContainer&&(q(this.errorContainer),this.errorContainer.appendChild(K(e))),this.inputElement?.classList.add("sv-email-input-error"),this.inputElement?.focus()}handleSubmit(){if(!this.inputElement||!this.submitButton)return;const e=this.inputElement.value;if(this.allowsBoth)if("phone"===this.detectedType){const t=G(e);if(!t)return void this.showError("Please enter a valid phone number");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"phone"})}else{const t=W(e);if(!t)return void this.showError("Please enter a valid email address");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"email"})}else if(this.allowsPhone){const t=G(e);if(!t)return void this.showError("Please enter a valid phone number");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"phone"})}else{const t=W(e);if(!t)return void this.showError("Please enter a valid email address");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"email"})}}destroy(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),this.inputElement&&(this.inputElement.removeEventListener("input",this.boundHandleInput),this.inputElement.removeEventListener("keydown",this.boundHandleKeyDown)),this.submitButton&&this.submitButton.removeEventListener("click",this.boundHandleSubmit)}}class Q{constructor(e){this.backLink=null,this.methodButtons=[],this.methodClickHandlers=new Map,this.props=e,this.boundHandleBack=()=>this.props.onBack()}render(){const e=U();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Choose how to sign in";const n=document.createElement("p");n.className="sv-subtitle",n.textContent=j(this.props.email);const i=U();for(const e of this.props.methods){const t=this.createMethodButton(e);this.methodButtons.push(t),i.appendChild(t)}return e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(i),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(M()),e.appendChild(document.createTextNode(" Change email")),e.addEventListener("click",this.boundHandleBack),e}createMethodButton(e){const t=document.createElement("button");t.className="sv-btn sv-btn-method";const n=U("sv-method-content"),i=this.getMethodIcon(e);n.appendChild(i);const s=U("sv-method-text"),o=document.createElement("div");o.className="sv-method-name",o.textContent=e.name;const r=document.createElement("div");r.className="sv-method-description",r.textContent=e.description,s.appendChild(o),s.appendChild(r),n.appendChild(s),t.appendChild(n);const a=()=>this.props.onSelectMethod(e);return this.methodClickHandlers.set(t,a),t.addEventListener("click",a),t}getMethodIcon(e){const t=U("sv-method-icon");return t.appendChild(O(e.icon)),t}destroy(){this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack);for(const e of this.methodButtons){const t=this.methodClickHandlers.get(e);t&&e.removeEventListener("click",t)}this.methodClickHandlers.clear(),this.methodButtons=[]}}class Z{constructor(e){this.inputElements=[],this.submitButton=null,this.resendButton=null,this.backLink=null,this.errorContainer=null,this.resendTimer=null,this.backoffTimer=null,this.backoffSeconds=0,this.focusTimeoutId=null,this.autoSubmitTimeoutId=null,this.isSubmitting=!1,this.inputHandlers=new Map,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleResend=()=>this.handleResend(),this.boundHandleSubmit=()=>this.handleSubmit()}render(){const e=U();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Enter verification code";const n="email"===this.props.method?"email":"phone",i=document.createElement("p");i.className="sv-subtitle",i.innerHTML=`We sent a 6-digit code to your ${n}<br><strong>${j(this.props.email)}</strong>`,this.errorContainer=U(),this.props.error&&this.errorContainer.appendChild(K(this.props.error));const s=this.createInputGroup();if(this.submitButton=document.createElement("button"),this.submitButton.className="sv-btn sv-btn-primary",this.submitButton.textContent="Verify",this.submitButton.addEventListener("click",this.boundHandleSubmit),this.props.backoffExpires){Math.max(0,Math.ceil(this.props.backoffExpires-Date.now()/1e3))>0&&this.startBackoff(this.props.backoffExpires)}const o=U("sv-resend-container");return this.resendButton=document.createElement("button"),this.resendButton.className="sv-back-link",this.resendButton.textContent="Resend code",this.resendButton.addEventListener("click",this.boundHandleResend),o.appendChild(this.resendButton),e.style.display="flex",e.style.flexDirection="column",e.appendChild(t),e.appendChild(i),e.appendChild(this.errorContainer),e.appendChild(s),e.appendChild(this.submitButton),e.appendChild(o),e.appendChild(this.backLink),this.focusTimeoutId=setTimeout(()=>this.inputElements[0]?.focus(),50),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.style.order="-1",e.appendChild(M()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}createInputGroup(){const e=U("sv-totp-input-group");for(let t=0;t<6;t++){const n=document.createElement("input");n.type="text",n.inputMode="numeric",n.pattern="[0-9]*",n.maxLength=1,n.className="sv-totp-digit",n.autocomplete="one-time-code",n.setAttribute("aria-label",`Digit ${t+1} of 6`);const i={input:e=>this.handleInput(e,t),keydown:e=>this.handleKeyDown(e,t),paste:e=>this.handlePaste(e),focus:()=>n.select()};this.inputHandlers.set(n,i),n.addEventListener("input",i.input),n.addEventListener("keydown",i.keydown),n.addEventListener("paste",i.paste),n.addEventListener("focus",i.focus),this.inputElements.push(n),e.appendChild(n)}return e}handleInput(e,t){const n=e.target,i=n.value.replace(/\D/g,"");i.length>0?(n.value=i[0],this.clearError(),t<5?this.inputElements[t+1].focus():this.checkAutoSubmit()):n.value=""}handleKeyDown(e,t){const n=e.target;"Backspace"===e.key?""===n.value&&t>0&&(this.inputElements[t-1].focus(),this.inputElements[t-1].value=""):"ArrowLeft"===e.key&&t>0?this.inputElements[t-1].focus():"ArrowRight"===e.key&&t<5?this.inputElements[t+1].focus():"Enter"===e.key&&this.handleSubmit()}handlePaste(e){e.preventDefault();const t=(e.clipboardData?.getData("text")??"").replace(/\D/g,"").slice(0,6);for(let e=0;e<t.length;e++)this.inputElements[e]&&(this.inputElements[e].value=t[e]);if(t.length>0){this.clearError();const e=Math.min(t.length,5);this.inputElements[e].focus()}6===t.length&&this.checkAutoSubmit()}checkAutoSubmit(){6===this.getCode().length&&(this.autoSubmitTimeoutId=setTimeout(()=>this.handleSubmit(),100))}getCode(){return this.inputElements.map(e=>e.value).join("")}clearError(){this.errorContainer&&q(this.errorContainer),this.inputElements.forEach(e=>e.classList.remove("sv-input-error"))}showError(e){this.errorContainer&&(q(this.errorContainer),this.errorContainer.appendChild(K(e))),this.inputElements.forEach(e=>e.classList.add("sv-input-error")),this.inputElements[0]?.focus()}handleSubmit(){if(!this.submitButton)return;if(this.isSubmitting)return;if(this.backoffSeconds>0)return;const e=function(e){const t=e.replace(/\D/g,"");return 6===t.length?t:null}(this.getCode());e?(null!==this.autoSubmitTimeoutId&&(clearTimeout(this.autoSubmitTimeoutId),this.autoSubmitTimeoutId=null),this.isSubmitting=!0,this.submitButton.disabled=!0,this.submitButton.textContent="Verifying...",this.props.onSubmit(e)):this.showError("Please enter the complete 6-digit code")}startBackoff(e){this.disableInputs(!0),this.backoffTimer=new g({expiresAt:e,onTick:e=>{this.backoffSeconds=e,this.updateSubmitButton()},onExpired:()=>{this.backoffSeconds=0,this.updateSubmitButton(),this.disableInputs(!1),this.inputElements[0]?.focus()}}),this.backoffTimer.start()}updateSubmitButton(){this.submitButton&&(this.backoffSeconds>0?(this.submitButton.textContent=`Wait ${this.backoffSeconds}s`,this.submitButton.disabled=!0):(this.submitButton.textContent="Verify",this.submitButton.disabled=!1))}disableInputs(e){this.inputElements.forEach(t=>{t.disabled=e})}handleResend(){!this.resendTimer?.isRunning()&&this.resendButton&&(this.resendTimer=new m({duration:30,onTick:e=>{this.resendButton&&(this.resendButton.textContent=`Resend code (${e}s)`,this.resendButton.disabled=!0)},onComplete:()=>{this.resendButton&&(this.resendButton.textContent="Resend code",this.resendButton.disabled=!1)}}),this.resendTimer.start(),this.props.onResend())}destroy(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),null!==this.autoSubmitTimeoutId&&(clearTimeout(this.autoSubmitTimeoutId),this.autoSubmitTimeoutId=null),this.resendTimer?.stop(),this.resendTimer=null,this.backoffTimer?.stop(),this.backoffTimer=null;for(const e of this.inputElements){const t=this.inputHandlers.get(e);t&&(e.removeEventListener("input",t.input),e.removeEventListener("keydown",t.keydown),e.removeEventListener("paste",t.paste),e.removeEventListener("focus",t.focus))}this.inputHandlers.clear(),this.inputElements=[],this.submitButton&&this.submitButton.removeEventListener("click",this.boundHandleSubmit),this.resendButton&&this.resendButton.removeEventListener("click",this.boundHandleResend),this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack)}}class ee{constructor(e){this.actionButton=null,this.errorContainer=null,this.backLink=null,this.fallbackLink=null,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleStart=()=>this.handleStart(),this.boundHandleFallback=e.onFallback?()=>e.onFallback():null}render(){const e=U();this.backLink=this.createBackLink();const t=U();t.appendChild(R());const n=document.createElement("h3");n.className="sv-title",n.textContent="register"===this.props.mode?"Set up a passkey":"Use your passkey";const i=document.createElement("p");i.className="sv-subtitle","register"===this.props.mode?i.innerHTML=`Create a passkey for<br><strong>${j(this.props.email)}</strong><br>to sign in faster next time`:i.innerHTML=`Use your passkey to verify<br><strong>${j(this.props.email)}</strong>`,this.errorContainer=U(),this.props.error&&this.errorContainer.appendChild(K(this.props.error));const s=document.createElement("p");s.className="sv-passkey-description",s.textContent="register"===this.props.mode?"Use Face ID, Touch ID, Windows Hello, or a security key.":"Your device will prompt you to verify your identity.";const o="register"===this.props.mode?"Create Passkey":"Continue with Passkey";return this.actionButton=document.createElement("button"),this.actionButton.className="sv-btn sv-btn-primary",this.actionButton.textContent=o,this.actionButton.addEventListener("click",this.boundHandleStart),e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(i),e.appendChild(this.errorContainer),e.appendChild(s),e.appendChild(this.actionButton),this.props.onFallback&&this.boundHandleFallback&&(this.fallbackLink=this.createFallbackLink(),e.appendChild(this.fallbackLink)),e}createFallbackLink(){const e=document.createElement("button");return e.className="sv-fallback-link",e.textContent="Having trouble? Use email code instead",this.boundHandleFallback&&e.addEventListener("click",this.boundHandleFallback),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(M()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}handleStart(){this.actionButton&&(this.actionButton.disabled=!0,this.actionButton.textContent="Waiting for device...",this.props.onStart())}showError(e){this.errorContainer&&(q(this.errorContainer),this.errorContainer.appendChild(K(e))),this.actionButton&&(this.actionButton.disabled=!1,this.actionButton.textContent="Try Again")}destroy(){this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack),this.actionButton&&this.actionButton.removeEventListener("click",this.boundHandleStart),this.fallbackLink&&this.boundHandleFallback&&this.fallbackLink.removeEventListener("click",this.boundHandleFallback)}}class te{constructor(e){this.addButton=null,this.skipLink=null,this.props=e,this.boundHandleAdd=()=>this.props.onAddPasskey(),this.boundHandleSkip=()=>this.props.onSkip()}render(){const e=U(),t=U();t.appendChild(R());const n=document.createElement("h3");n.className="sv-title",n.textContent="Add a passkey for faster sign-in?";const i=document.createElement("p");i.className="sv-subtitle",i.innerHTML=`Next time, sign in instantly as<br><strong>${j(this.props.email)}</strong>`;const s=document.createElement("div");s.className="sv-passkey-prompt-benefits";const o=document.createElement("ul"),r=["No codes to type or wait for","Phishing-resistant security","Works with Face ID, Touch ID, or Windows Hello"];for(const e of r){const t=document.createElement("li");t.appendChild(H()),t.appendChild(document.createTextNode(e)),o.appendChild(t)}return s.appendChild(o),this.addButton=document.createElement("button"),this.addButton.className="sv-btn sv-btn-primary",this.addButton.textContent="Add Passkey",this.addButton.addEventListener("click",this.boundHandleAdd),this.skipLink=document.createElement("button"),this.skipLink.className="sv-skip-link",this.skipLink.textContent="Not now",this.skipLink.addEventListener("click",this.boundHandleSkip),e.appendChild(t),e.appendChild(n),e.appendChild(i),e.appendChild(s),e.appendChild(this.addButton),e.appendChild(this.skipLink),e}destroy(){this.addButton&&this.addButton.removeEventListener("click",this.boundHandleAdd),this.skipLink&&this.skipLink.removeEventListener("click",this.boundHandleSkip)}}class ne{constructor(e){this.expirationTimer=null,this.resendTimer=null,this.countdownElement=null,this.countdownSection=null,this.waitingSection=null,this.resendButton=null,this.backLink=null,this.fallbackButton=null,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleResend=()=>this.handleResend(),this.boundHandleFallback=()=>this.props.onFallback()}render(){const e=U();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Check your email";const n=document.createElement("p");n.className="sv-subtitle",n.innerHTML=`We sent a secure link to<br><strong>${j(this.props.email)}</strong>`,this.waitingSection=U("sv-sparklink-waiting");const i=document.createElement("div");i.className="sv-spinner sv-spinner-small",i.setAttribute("role","status"),i.setAttribute("aria-label","Waiting for verification");const s=document.createElement("span");s.className="sv-sparklink-waiting-text",s.textContent="Waiting for you to click the link...",this.waitingSection.appendChild(i),this.waitingSection.appendChild(s),this.countdownSection=U("sv-sparklink-countdown");const o=document.createElement("span");o.textContent="Link expires in ",this.countdownElement=document.createElement("span"),this.countdownElement.className="sv-sparklink-countdown-time",this.startExpirationTimer(),this.countdownSection.appendChild(o),this.countdownSection.appendChild(this.countdownElement);const r=U("sv-resend-container");this.resendButton=document.createElement("button"),this.resendButton.className="sv-back-link",this.resendButton.textContent="Resend link",this.resendButton.addEventListener("click",this.boundHandleResend),r.appendChild(this.resendButton);const a=U("sv-sparklink-fallback");return this.fallbackButton=document.createElement("button"),this.fallbackButton.className="sv-back-link",this.fallbackButton.textContent="Use verification code instead",this.fallbackButton.addEventListener("click",this.boundHandleFallback),a.appendChild(this.fallbackButton),e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(this.waitingSection),e.appendChild(this.countdownSection),e.appendChild(r),e.appendChild(a),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(M()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}formatTime(e){if(!Number.isFinite(e)||e<0)return"--:--";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`}startExpirationTimer(){if(!Number.isFinite(this.props.expiresAt)||this.props.expiresAt<=0)return this.countdownElement&&(this.countdownElement.textContent="--:--"),void console.warn("[SparkVault] Invalid expiresAt timestamp:",this.props.expiresAt);const e=Math.floor(this.props.expiresAt/1e3);this.expirationTimer=new g({expiresAt:e,onTick:e=>{this.countdownElement&&(this.countdownElement.textContent=this.formatTime(e))},onExpired:()=>{this.showExpiredState()}}),this.expirationTimer.start()}showExpiredState(){if(this.props.onExpired(),this.waitingSection){this.waitingSection.innerHTML="",this.waitingSection.classList.add("sv-sparklink-expired");const e=U("sv-sparklink-expired-icon");e.appendChild(function(){const e=I("0 0 48 48",48,48);e.classList.add("sv-expired-icon"),e.appendChild(F(24,24,22,{fill:"#F5F5F5",stroke:"#E5E5E5","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.setAttribute("transform","translate(10, 12)"),t.appendChild($("M14 4L2 24h24L14 4z",{fill:"#737373"})),t.appendChild($("M14 10v5",{stroke:"#FFFFFF","stroke-width":"2","stroke-linecap":"round"})),t.appendChild(F(14,19,1,{fill:"#FFFFFF"})),e.appendChild(t),e}()),this.waitingSection.appendChild(e);const t=document.createElement("span");t.className="sv-sparklink-expired-text",t.textContent="This link has expired",this.waitingSection.appendChild(t)}this.countdownSection&&(this.countdownSection.style.display="none")}handleResend(){!this.resendTimer?.isRunning()&&this.resendButton&&(this.resendTimer=new m({duration:30,onTick:e=>{this.resendButton&&(this.resendButton.textContent=`Resend link (${e}s)`,this.resendButton.disabled=!0)},onComplete:()=>{this.resendButton&&(this.resendButton.textContent="Resend link",this.resendButton.disabled=!1)}}),this.resendTimer.start(),this.props.onResend())}destroy(){this.expirationTimer?.stop(),this.expirationTimer=null,this.resendTimer?.stop(),this.resendTimer=null,this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack),this.resendButton&&this.resendButton.removeEventListener("click",this.boundHandleResend),this.fallbackButton&&this.fallbackButton.removeEventListener("click",this.boundHandleFallback)}}class ie{constructor(e){this.retryButton=null,this.closeButton=null,this.props=e,this.boundHandleRetry=()=>this.props.onRetry(),this.boundHandleClose=()=>this.props.onClose()}render(){const e=U();e.className="sv-error-view";const t=U();t.className="sv-error-icon-container",t.appendChild(function(){const e=I("0 0 48 48",48,48);e.classList.add("sv-error-icon"),e.appendChild(F(24,24,22,{fill:"#FEF2F2",stroke:"#FECACA","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.setAttribute("transform","translate(10, 12)"),t.appendChild($("M14 4L2 24h24L14 4z",{fill:"#DC2626"})),t.appendChild($("M14 10v5",{stroke:"#FFFFFF","stroke-width":"2","stroke-linecap":"round"})),t.appendChild(F(14,19,1,{fill:"#FFFFFF"})),e.appendChild(t),e}());const n=U();n.className="sv-error-content";const i=document.createElement("h3");i.className="sv-error-title",i.textContent="Something went wrong";const s=document.createElement("p");s.className="sv-error-message",s.textContent=this.props.message;const o=document.createElement("div");o.className="sv-error-code-badge";const r=document.createElement("span");r.className="sv-error-code-label",r.textContent="Error code";const a=document.createElement("code");a.className="sv-error-code-value",a.textContent=this.props.code,o.appendChild(r),o.appendChild(a),n.appendChild(i),n.appendChild(s),n.appendChild(o);const l=U();return l.className="sv-error-actions",this.retryButton=document.createElement("button"),this.retryButton.className="sv-btn sv-btn-error-primary",this.retryButton.textContent="Try Again",this.retryButton.addEventListener("click",this.boundHandleRetry),this.closeButton=document.createElement("button"),this.closeButton.className="sv-btn sv-btn-error-secondary",this.closeButton.textContent="Close",this.closeButton.addEventListener("click",this.boundHandleClose),l.appendChild(this.retryButton),l.appendChild(this.closeButton),e.appendChild(t),e.appendChild(n),e.appendChild(l),e}destroy(){this.retryButton&&this.retryButton.removeEventListener("click",this.boundHandleRetry),this.closeButton&&this.closeButton.removeEventListener("click",this.boundHandleClose)}}class se{constructor(e,t,n,i){this.currentView=null,this.focusTimeoutId=null,this.pollingInterval=null,this.messageListener=null,this.container=e,this.api=t,this.options=n,this.callbacks=i,this.verificationState=new S,this.passkeyHandler=new T(t,this.verificationState),this.totpHandler=new B(t,this.verificationState),this.sparkLinkHandler=new L(t,this.verificationState),n.email?this.verificationState.setIdentity(n.email,"email"):n.phone&&this.verificationState.setIdentity(n.phone,"phone")}get recipient(){return this.verificationState.recipient}get identityType(){return this.verificationState.identityType}get sdkConfig(){return this.verificationState.sdkConfig}async start(){let e=null;if(this.api.isConfigPreloaded()){const t=new Promise(e=>setTimeout(()=>e(null),50)),n=await Promise.race([this.api.getConfig().then(e=>e),t]);null!==n&&(e=n)}this.container.createLoading({backdropBlur:this.options.backdropBlur},()=>this.handleClose());try{e||(this.setState({view:"loading"}),e=await this.api.getConfig()),this.verificationState.setConfig(e),e.branding&&this.container.updateBranding(e.branding);const t=void 0!==this.options.backdropBlur?this.options.backdropBlur:void 0===e.branding?.backdrop_blur||e.branding.backdrop_blur;this.container.updateBackdropBlur(t),this.recipient?this.showMethodSelect():this.showIdentityInput()}catch(e){const n=this.normalizeError(e);this.setState({view:"error",message:n.message,code:n instanceof t?n.code:"config_error"})}}close(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),this.stopSparkLinkPolling(),this.destroyCurrentView(),this.container.destroy()}handleClose(){this.close(),this.callbacks.onCancel()}get viewState(){return this.verificationState.viewState}setState(e){this.verificationState.setViewState(e),this.render()}render(){const e=this.container.getBody();if(!e)return;this.destroyCurrentView();const t=this.createViewForState(this.viewState);this.currentView=t,q(e),e.appendChild(t.render());const n=e.querySelector("input:not([disabled]), button.sv-btn-primary:not([disabled]), button.sv-btn-email-primary:not([disabled]), button.sv-btn-method:not([disabled])");n&&(null!==this.focusTimeoutId&&clearTimeout(this.focusTimeoutId),this.focusTimeoutId=setTimeout(()=>n.focus(),50))}destroyCurrentView(){this.currentView?.destroy&&this.currentView.destroy(),this.currentView=null}createViewForState(e){switch(e.view){case"loading":return new Y({message:"Loading..."});case"identity-input":return new X({allowedTypes:this.getAllowedIdentityTypes(),initialValue:this.recipient,error:e.error,onSubmit:e=>this.handleIdentitySubmit(e)});case"method-select":return new Q({email:e.email,methods:e.methods,onSelectMethod:e=>this.handleMethodSelect(e),onBack:()=>this.showIdentityInput()});case"totp-verify":return new Z({email:e.email,method:e.method,error:e.error,backoffExpires:e.backoffExpires,onSubmit:e=>this.handleTotpSubmit(e),onResend:()=>this.handleTotpResend(),onBack:()=>this.showMethodSelect()});case"passkey":{const{passkey:t}=this.verificationState,n="register"===e.mode&&null!==t.pendingResult;return new ee({email:e.email,mode:e.mode,error:e.error,onStart:()=>this.handlePasskeyStart(),onBack:n?()=>this.handlePasskeyRegistrationSkip():()=>this.showMethodSelect(),onFallback:t.hasPasskey&&!t.isFallbackMode?()=>this.handlePasskeyFallback():void 0})}case"passkey-prompt":return new te({email:e.email,onAddPasskey:()=>this.handlePasskeyPromptAdd(e.pendingResult),onSkip:()=>this.handlePasskeyPromptSkip(e.pendingResult)});case"sparklink-waiting":return new ne({email:e.email,expiresAt:e.expiresAt,onResend:()=>this.handleSparkLinkResend(),onFallback:()=>this.handleSparkLinkFallback(),onBack:()=>this.showMethodSelect(),onExpired:()=>this.stopSparkLinkPolling()});case"oauth-pending":return new Y({message:`Connecting to ${e.provider}...`});case"error":return new ie({message:e.message,code:e.code,onRetry:()=>this.showIdentityInput(),onClose:()=>this.handleClose()})}}showIdentityInput(e){this.setState({view:"identity-input",error:e})}async showMethodSelect(){if(!this.sdkConfig)return;const e=this.sdkConfig.methods??[];if(!Array.isArray(e))return void this.setState({view:"error",message:"Invalid configuration",code:"invalid_config"});let t=E(e);if(t=t.filter(e=>"phone"===this.identityType?"totp"===e.type&&"totp_sms"===e.id:"email"===e.identityType||void 0===e.identityType),0===t.length)return void this.setState({view:"error",message:"No authentication methods available",code:"no_methods"});const n=t.some(e=>"passkey"===e.type),{passkey:i}=this.verificationState;if(n&&"email"===this.identityType&&!i.isFallbackMode){this.setState({view:"loading"});const e=await this.passkeyHandler.checkPasskey();if(null!==e&&!e.emailValid)return void this.showIdentityInput("This email domain cannot receive messages. Please check your email address.");if(!0===e?.hasPasskey)return void this.setState({view:"passkey",email:this.recipient,mode:"verify"});t=t.filter(e=>"passkey"!==e.type)}0!==t.length?1!==t.length?this.setState({view:"method-select",email:this.recipient,methods:t}):this.handleMethodSelect(t[0]):this.setState({view:"error",message:"No authentication methods available",code:"no_methods"})}handleIdentitySubmit(e){this.verificationState.setIdentity(e.value,e.type),this.showMethodSelect()}getAllowedIdentityTypes(){return this.verificationState.getAllowedIdentityTypes()}async handleMethodSelect(e){try{switch(e.type){case"totp":{const t="totp_sms"===e.id?"sms":"email";this.setState({view:"loading"});const n=await this.totpHandler.send(t);if(!n.success)return void this.setState({view:"error",message:n.error??"Failed to send code",code:"totp_send_failed"});this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling});break}case"passkey":this.setState({view:"passkey",email:this.recipient,mode:"verify"});break;case"magic_link":{this.setState({view:"loading"});const e=await this.sparkLinkHandler.send();if(!e.success)return void this.setState({view:"error",message:e.error??"Failed to send SparkLink",code:"sparklink_send_failed"});this.setState({view:"sparklink-waiting",email:this.recipient,sparkId:e.sparkId,expiresAt:e.expiresAt}),this.startSparkLinkPolling(e.sparkId);break}case"social":e.provider&&this.handleSocialLogin(e.provider);break;default:this.setState({view:"error",message:`Authentication method not supported: ${e.type}`,code:"unsupported_method"})}}catch(e){const n=this.normalizeError(e);this.setState({view:"error",message:n.message,code:n instanceof t?n.code:"unknown"})}}async handleTotpSubmit(e){if("totp-verify"!==this.viewState.view)return;const t=this.verificationState.totp.method??"email",n=await this.totpHandler.verify(e);if(n.success&&n.result){if(await this.shouldShowPasskeyPrompt())return void this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:n.result});this.close(),this.callbacks.onSuccess(n.result)}else this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling,error:n.error??"Invalid code. Please try again.",backoffExpires:n.backoffExpires})}async handleTotpResend(){if("totp-verify"!==this.viewState.view)return;const e=this.verificationState.totp.method??"email",t=await this.totpHandler.resend();t.success||this.setState({view:"totp-verify",email:this.recipient,method:e,kindling:this.verificationState.totp.kindling,error:t.error??"Failed to resend code"})}async handlePasskeyStart(){if("passkey"!==this.viewState.view)return;const e=this.viewState.mode,t="register"===e?await this.passkeyHandler.register():await this.passkeyHandler.verify();t.success&&t.result?(this.close(),this.callbacks.onSuccess(t.result)):"not_found"===t.errorType?this.setState({view:"passkey",email:this.recipient,mode:"register",error:t.error}):this.setState({view:"passkey",email:this.recipient,mode:e,error:t.error})}async handlePasskeyFallback(){this.verificationState.enablePasskeyFallback(),await this.showMethodSelect()}handlePasskeyRegistrationSkip(){const e=this.verificationState.passkey.pendingResult;e&&(this.verificationState.setPendingResult(null),this.close(),this.callbacks.onSuccess(e))}handleSocialLogin(e){this.setState({view:"oauth-pending",provider:e});const t=function(){const e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}(),n=window.location.origin+window.location.pathname;sessionStorage.setItem("sv_oauth_state",t),sessionStorage.setItem("sv_oauth_email",this.recipient);const i=this.api.getSocialAuthUrl(e,n,t);window.location.href=i}normalizeError(e){return e instanceof x?new t(e.message,e.code):e instanceof Error?e:new Error(String(e))}async shouldShowPasskeyPrompt(){if(!this.verificationState.shouldShowPasskeyPrompt())return!1;const{passkey:e}=this.verificationState;if(null===e.hasPasskey){const e=await this.passkeyHandler.checkPasskey();return null!==e&&e.emailValid&&!e.hasPasskey}return!e.hasPasskey}async handlePasskeyPromptAdd(e){this.verificationState.setPendingResult(e),this.setState({view:"loading"});const t=await this.passkeyHandler.register();t.success&&t.result?(this.close(),this.callbacks.onSuccess(t.result)):(t.errorType,this.verificationState.setPendingResult(null),this.close(),this.callbacks.onSuccess(e))}handlePasskeyPromptSkip(e){this.verificationState.dismissPasskeyPrompt(),this.close(),this.callbacks.onSuccess(e)}startSparkLinkPolling(e){this.stopSparkLinkPolling(),this.messageListener=e=>{if(!e.data||"object"!=typeof e.data)return;if("sparklink_verified"!==e.data.type)return;const{token:t,identity:n,identityType:i}=e.data;t&&n&&this.handleSparkLinkVerified({token:t,identity:n,identityType:i||"email"})},window.addEventListener("message",this.messageListener),this.pollingInterval=setInterval(async()=>{const t=await this.sparkLinkHandler.checkStatus(e);t.verified&&t.token&&t.identity&&this.handleSparkLinkVerified({token:t.token,identity:t.identity,identityType:t.identityType||"email"})},2e3)}async handleSparkLinkVerified(e){this.stopSparkLinkPolling(),await this.shouldShowPasskeyPrompt()?this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:e}):(this.close(),this.callbacks.onSuccess(e))}stopSparkLinkPolling(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null)}async handleSparkLinkResend(){const e=await this.sparkLinkHandler.send();e.success&&e.sparkId&&(this.stopSparkLinkPolling(),this.setState({view:"sparklink-waiting",email:this.recipient,sparkId:e.sparkId,expiresAt:e.expiresAt}),this.startSparkLinkPolling(e.sparkId))}async handleSparkLinkFallback(){this.stopSparkLinkPolling(),this.setState({view:"loading"});const e=await this.totpHandler.send("email");e.success?this.setState({view:"totp-verify",email:this.recipient,method:"email",kindling:this.verificationState.totp.kindling}):this.setState({view:"error",message:e.error??"Failed to send code",code:"totp_send_failed"})}}const oe={showHeader:!0,showCloseButton:!0,showFooter:!0};class re{constructor(e,t={}){this.container=null,this.header=null,this.body=null,this.footer=null,this.closeBtn=null,this.onCloseCallback=null,this.closeBtnClickHandler=null,this.effectiveTheme="light",this.targetElement=e,this.containerOptions={...oe,...t}}createLoading(e,t){if(this.container)return;this.onCloseCallback=t;if(P({branding:{companyName:"",logoLight:null,logoDark:null},backdropBlur:!1}),this.container=document.createElement("div"),this.container.className="sv-inline-container",this.containerOptions.showHeader&&(this.header=this.createHeader({companyName:"",logoLight:null,logoDark:null}),this.container.appendChild(this.header)),this.body=document.createElement("div"),this.body.className="sv-body sv-inline-body",this.container.appendChild(this.body),this.containerOptions.showFooter){this.footer=document.createElement("div"),this.footer.className="sv-footer";const e=document.createElement("span");e.className="sv-footer-text",e.appendChild(document.createTextNode("Secured by "));const t=document.createElement("a");t.href="https://sparkvault.com",t.target="_blank",t.rel="noopener noreferrer",t.className="sv-footer-link",t.textContent="SparkVault",e.appendChild(t),this.footer.appendChild(e),this.container.appendChild(this.footer)}this.targetElement.innerHTML="",this.targetElement.appendChild(this.container)}updateBranding(e){if(this.container&&(this.effectiveTheme=_(e),this.containerOptions.showHeader&&this.header)){const t=this.createHeader(e);this.container.replaceChild(t,this.header),this.header=t}}updateBackdropBlur(e){}getBody(){return this.body}isOpen(){return null!==this.container}destroy(){this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.container&&this.container.parentNode&&this.container.remove(),this.container=null,this.header=null,this.body=null,this.footer=null,this.onCloseCallback=null}createHeader(e){const t=document.createElement("div");t.className="sv-header sv-inline-header";const n=document.createElement("div");n.className="sv-header-title";const i="dark"===this.effectiveTheme?e.logoDark||e.logoLight:e.logoLight||e.logoDark;if(i){const t=document.createElement("img");t.className="sv-logo",t.src=i,t.alt=e.companyName,n.appendChild(t);const s=document.createElement("span");s.className="sv-sr-only",s.textContent=e.companyName,n.appendChild(s)}else if(e.companyName){const t=document.createElement("h2");t.className="sv-company-name",t.textContent=e.companyName,n.appendChild(t)}return t.appendChild(n),this.containerOptions.showCloseButton&&(this.closeBtn=document.createElement("button"),this.closeBtn.className="sv-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.appendChild(N()),this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(this.closeBtn)),t}handleClose(){this.onCloseCallback&&this.onCloseCallback()}}class ae{constructor(e){this.renderer=null,this.config=e,this.api=new w(e),e.preloadConfig&&this.api.preloadConfig()}async pop(e={}){return this.renderer&&this.renderer.close(),new Promise((t,n)=>{const i=new D;this.renderer=new se(i,this.api,e,{onSuccess:n=>{e.onSuccess?.(n),t(n)},onError:t=>{e.onError?.(t),n(t)},onCancel:()=>{const t=new a;e.onCancel?.(),n(t)}}),this.renderer.start().catch(t=>{e.onError?.(t),n(t)})})}async render(e){if(!(e.target&&e.target instanceof HTMLElement))throw new s("target must be a valid HTMLElement");return this.renderer&&this.renderer.close(),new Promise((t,n)=>{const i=new re(e.target,{showHeader:e.showHeader,showCloseButton:e.showCloseButton,showFooter:e.showFooter});this.renderer=new se(i,this.api,e,{onSuccess:n=>{e.onSuccess?.(n),t(n)},onError:t=>{e.onError?.(t),n(t)},onCancel:()=>{const t=new a;e.onCancel?.(),n(t)}}),this.renderer.start().catch(t=>{e.onError?.(t),n(t)})})}async verifyToken(e){if(!e||"string"!=typeof e)throw new s("Token is required");const t=e.split(".");if(3!==t.length)throw new s("Invalid token format");const[,n]=t,i=JSON.parse(function(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t+"=".repeat((4-t.length%4)%4);return atob(n)}(n));if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.iss&&"string"==typeof t.sub&&"string"==typeof t.aud&&"number"==typeof t.exp&&"number"==typeof t.iat&&"string"==typeof t.identity&&"string"==typeof t.identity_type&&"number"==typeof t.verified_at&&"string"==typeof t.method}(i))throw new s("Invalid token payload structure");const o=Math.floor(Date.now()/1e3);if(i.exp<o)throw new s("Token has expired");const r=`${this.config.apiBaseUrl}/apps/identity/${this.config.accountId}`;if(i.iss!==r)throw new s("Invalid token issuer");return i}close(){this.renderer&&(this.renderer.close(),this.renderer=null)}async verify(e={}){return this.pop(e)}}class le{constructor(e){this.http=e}async create(e){this.validateCreateOptions(e);const t=this.encodePayload(e.payload),n=await this.http.post("/v1/sparks",{payload:t,ttl:e.ttl??3600,max_reads:e.maxReads??1,password:e.password,name:e.name});return{id:n.data.spark_id,url:n.data.url,expiresAt:n.data.expires_at,maxReads:n.data.max_reads,name:n.data.name}}async read(e,t){if(!e)throw new s("Spark ID is required");const n=e.startsWith("spk_")?e:`spk_${e}`,i={};t&&(i["X-Spark-Password"]=t);const o=await this.http.get(`/v1/sparks/${n}`,{headers:i});return{data:this.decodePayload(o.data.payload),readAt:o.data.read_at,burned:o.data.burned,readsRemaining:o.data.reads_remaining}}validateCreateOptions(e){if(!e.payload)throw new s("Payload is required");if(void 0!==e.ttl&&(e.ttl<60||e.ttl>604800))throw new s("TTL must be between 60 and 604800 seconds (1 minute to 7 days)");if(void 0!==e.maxReads&&(e.maxReads<1||e.maxReads>100))throw new s("maxReads must be between 1 and 100")}encodePayload(e){return"string"==typeof e?e:b(e)}decodePayload(e){return e}}class de{constructor(e,t){this.http=t}async create(e){this.validateCreateOptions(e);const t=await this.http.post("/v1/vaults",{name:e.name,hosted_vmk:e.hostedVmk??!1});return{id:t.data.vault_id,name:t.data.name,vmk:t.data.vmk,createdAt:t.data.created_at,hostedVmk:t.data.hosted_vmk}}async unseal(e,t){if(!e)throw new s("Vault ID is required");if(!t)throw new s("VMK is required");const n=e.startsWith("vlt_")?e:`vlt_${e}`,i=await this.http.post(`/v1/vaults/${n}/unseal`,{vmk:t});return{id:i.data.vault_id,name:i.data.name,vatToken:i.data.vat_token,expiresAt:i.data.expires_at,ingotCount:i.data.ingot_count,storageBytes:i.data.storage_bytes}}async list(){return(await this.http.get("/v1/vaults")).data.vaults.map(e=>({id:e.vault_id,name:e.name,createdAt:e.created_at,ingotCount:e.ingot_count,storageBytes:e.storage_bytes,hostedVmk:e.hosted_vmk}))}async delete(e,t){const n=e.startsWith("vlt_")?e:`vlt_${e}`;await this.http.delete(`/v1/vaults/${n}`,{headers:{"X-VMK":t}})}async uploadIngot(e,t){this.validateUploadOptions(t);const n=t.name??(t.file instanceof File?t.file.name:"unnamed"),i=t.contentType??t.file.type??"application/octet-stream",s=await this.http.post(`/v1/vaults/${e.id}/ingots`,{name:n,content_type:i,size_bytes:t.file.size},{headers:{Authorization:`Bearer ${e.vatToken}`}});return{id:s.data.ingot_id,name:s.data.name,contentType:s.data.content_type,size:s.data.size_bytes,createdAt:s.data.created_at,type:s.data.ingot_type}}async downloadIngot(e,t){const n=t.startsWith("ing_")?t:`ing_${t}`;return this.http.requestRaw(`/v1/vaults/${e.id}/ingots/${n}/download`,{method:"POST",headers:{Authorization:`Bearer ${e.vatToken}`}})}async listIngots(e){return(await this.http.get(`/v1/vaults/${e.id}/ingots`,{headers:{Authorization:`Bearer ${e.vatToken}`}})).data.ingots.map(e=>({id:e.ingot_id,name:e.name,contentType:e.content_type,size:e.size_bytes,createdAt:e.created_at,type:e.ingot_type}))}async deleteIngot(e,t){const n=t.startsWith("ing_")?t:`ing_${t}`;await this.http.delete(`/v1/vaults/${e.id}/ingots/${n}`,{headers:{Authorization:`Bearer ${e.vatToken}`}})}validateCreateOptions(e){if(!e.name?.trim())throw new s("Vault name is required");if(e.name.length>255)throw new s("Vault name must be 255 characters or less")}validateUploadOptions(e){if(!e.file)throw new s("File is required");if(0===e.file.size)throw new s("File cannot be empty")}}const ce=["hex","base64","base64url","alphanumeric","alphanumeric-mixed","password","numeric","uuid","bytes"];function he(e){return ce.includes(e)}class pe{constructor(e){this.http=e}async generate(e){this.validateOptions(e);const t=await this.http.post("/v1/apps/rng/generate",{num_bytes:e.bytes,format:e.format??"base64url"}),n=t.data.format??"base64url";if(!he(n))throw new s(`Server returned invalid format: ${n}`);return{value:"bytes"===n?v(t.data.random_bytes_b64):t.data.random_bytes_b64,bytes:t.data.num_bytes,format:n,referenceId:t.data.reference_id}}async uuid(){const e=await this.generate({bytes:16,format:"uuid"});if("string"!=typeof e.value)throw new s("Expected string value for uuid format");return e.value}async hex(e){const t=await this.generate({bytes:e,format:"hex"});if("string"!=typeof t.value)throw new s("Expected string value for hex format");return t.value}async alphanumeric(e){const t=await this.generate({bytes:e,format:"alphanumeric-mixed"});if("string"!=typeof t.value)throw new s("Expected string value for alphanumeric format");return t.value}async password(e){const t=await this.generate({bytes:e,format:"password"});if("string"!=typeof t.value)throw new s("Expected string value for password format");return t.value}validateOptions(e){if(!e.bytes||"number"!=typeof e.bytes)throw new s("bytes is required and must be a number");if(e.bytes<1||e.bytes>1024)throw new s("bytes must be between 1 and 1024");if(e.format&&!he(e.format))throw new s(`Invalid format. Must be one of: ${ce.join(", ")}`)}}let ue=!1;function me(e){ue=e,e&&ge("info","Debug mode enabled")}function ge(e,t,...n){const i=`[SparkVault] ${(new Date).toISOString().split("T")[1].slice(0,-1)} ${t}`;switch(e){case"debug":ue&&console.debug(i,...n);break;case"info":ue&&console.log(i,...n);break;case"warn":ue&&console.warn(i,...n);break;case"error":console.error(i,...n)}}const be={debug:(e,...t)=>ge("debug",e,...t),info:(e,...t)=>ge("info",e,...t),warn:(e,...t)=>ge("warn",e,...t),error:(e,...t)=>ge("error",e,...t),group:e=>{ue&&console.group(`[SparkVault] ${e}`)},groupEnd:()=>{ue&&console.groupEnd()}},ye={initialized:!1,instance:null,config:null,observer:null,isAuthenticating:!1};function fe(e){if(!e||"string"!=typeof e)return null;const t=e.split(".");let n=window;for(const i of t){if(!n||"object"!=typeof n||!(i in n))return be.warn(`Function "${e}" not found on window`),null;n=n[i]}return"function"==typeof n?n:(be.warn(`"${e}" is not a function`),null)}function ke(e){const t=ye.config;if(t){if(be.error("Verification error:",e.message),t.errorFunction){const n=fe(t.errorFunction);if(n){be.debug(`Calling error function: ${t.errorFunction}`);try{n(e)}catch(e){be.error("Error in error function:",e)}}}if(t.errorUrl){const n=new URL(t.errorUrl,window.location.origin);n.searchParams.set("error",e.message),be.debug(`Redirecting to error URL: ${n.toString()}`),window.location.href=n.toString()}}}async function ve(){if(ye.instance)if(ye.isAuthenticating)be.debug("Already authenticating, skipping");else{ye.isAuthenticating=!0,be.info("Starting verification...");try{const e=await ye.instance.identity.pop();if(!e)return be.info("User cancelled verification"),void(ye.isAuthenticating=!1);await async function(e){const t=ye.config;if(t){if(be.info("Verification successful",{identity:e.identity,identityType:e.identityType,hasToken:!!e.token}),t.successFunction){const n=fe(t.successFunction);if(n){be.debug(`Calling success function: ${t.successFunction}`);try{n(e)}catch(e){be.error("Error in success function:",e)}}}if(t.successUrl){be.debug(`POSTing to success URL: ${t.successUrl}`);try{const n=await fetch(t.successUrl,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},credentials:"include",body:JSON.stringify({token:e.token,identity:e.identity,identityType:e.identityType})}),i=await n.json();if(be.debug("Success URL response:",i),i.redirectUrl||i.redirect_url){const e=i.redirectUrl||i.redirect_url;be.info(`Redirecting to: ${e}`),window.location.href=e}else!0===i.reload&&(be.info("Reloading page"),window.location.reload())}catch(e){be.error("Failed to POST to success URL:",e),ke(e instanceof Error?e:new Error(String(e)))}}}}(e)}catch(e){if(e&&"object"==typeof e&&"name"in e){const t=e;if("UserCancelledError"===t.name||"user_cancelled"===t.code)return be.info("User cancelled verification"),void(ye.isAuthenticating=!1)}ke(e instanceof Error?e:new Error(String(e)))}finally{ye.isAuthenticating=!1}}else be.error("SDK not initialized")}function we(){const e=ye.config;if(!e?.attachSelector)return;const t=document.querySelectorAll(e.attachSelector);be.debug(`Found ${t.length} elements matching "${e.attachSelector}"`),t.forEach(e=>{"true"!==e.dataset.sparkvaultAttached&&(e.dataset.sparkvaultAttached="true",be.debug("Attaching click handler to element:",e),e.addEventListener("click",e=>{be.debug("Auth element clicked"),e.preventDefault(),e.stopPropagation(),ve()}))})}function xe(){const e=ye.config;e?.attachSelector&&("undefined"!=typeof MutationObserver?(ye.observer=new MutationObserver(e=>{let t=!1;for(const n of e)if(n.addedNodes.length>0){t=!0;break}t&&we()}),ye.observer.observe(document.body,{childList:!0,subtree:!0}),be.debug("MutationObserver started for dynamic elements")):be.warn("MutationObserver not available, dynamic elements will not be auto-attached"))}class Ce{constructor(e){!function(e){if(!e.accountId)throw new s("accountId is required",{field:"accountId"});if("string"!=typeof e.accountId)throw new s("accountId must be a string",{field:"accountId",received:typeof e.accountId});if(!e.accountId.startsWith("acc_"))throw new s('accountId must start with "acc_"',{field:"accountId",received:e.accountId})}(e),this.config=function(e){return{accountId:e.accountId,timeout:e.timeout??3e4,apiBaseUrl:"https://api.sparkvault.com",identityBaseUrl:"https://api.sparkvault.com/v1/apps/identity",preloadConfig:!1!==e.preloadConfig}}(e);const t=new u(this.config);this.identity=new ae(this.config),this.sparks=new le(t),this.vaults=new de(this.config,t),this.rng=new pe(t)}static init(e){return new Ce(e)}static get version(){return"__VERSION__"}}"undefined"!=typeof window&&(window.SparkVault=Ce,function(e){if(ye.initialized)return void be.debug("Auto-init already completed");if("undefined"==typeof window||"undefined"==typeof document)return;const t=function(){if(document.currentScript instanceof HTMLScriptElement)return document.currentScript;const e=document.querySelectorAll('script[src*="sparkvault"]');for(const t of e)if(t.dataset.accountId)return t;return e[0]||null}();if(!t)return;const n=function(e){const t=e.dataset.timeout;return{accountId:e.dataset.accountId||null,attachSelector:e.dataset.attachSelector||null,successUrl:e.dataset.successUrl||null,successFunction:e.dataset.successFunction||null,errorUrl:e.dataset.errorUrl||null,errorFunction:e.dataset.errorFunction||null,debug:"true"===e.dataset.debug,preloadConfig:"false"!==e.dataset.preloadConfig,timeout:t?parseInt(t,10):3e4}}(t);if(ye.config=n,n.debug&&me(!0),be.info("Auto-init starting..."),be.group("Configuration"),be.debug("Account ID:",n.accountId||"(not set)"),be.debug("Attach Selector:",n.attachSelector||"(not set)"),be.debug("Success URL:",n.successUrl||"(not set)"),be.debug("Success Function:",n.successFunction||"(not set)"),be.debug("Error URL:",n.errorUrl||"(not set)"),be.debug("Error Function:",n.errorFunction||"(not set)"),be.debug("Debug:",n.debug),be.groupEnd(),!n.accountId)return void be.debug("No data-account-id attribute, skipping auto-init");try{ye.instance=e.init({accountId:n.accountId,preloadConfig:n.preloadConfig,timeout:n.timeout}),ye.initialized=!0,be.info("SDK initialized successfully")}catch(e){return void be.error("Failed to initialize SDK:",e)}n.attachSelector&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{we(),xe()}):(we(),xe()));const i=window.SparkVault;i&&(i.identity={pop:ve,render:e=>ye.instance?ye.instance.identity.render(e):Promise.reject(new Error("SDK not initialized")),authenticate:ve,verify:e=>ye.instance?ye.instance.identity.pop(e):Promise.reject(new Error("SDK not initialized"))},i.getInstance=()=>ye.instance),be.info("Auto-init complete")}(Ce)),e.AuthenticationError=n,e.AuthorizationError=i,e.NetworkError=o,e.PopupBlockedError=l,e.SparkVault=Ce,e.SparkVaultError=t,e.TimeoutError=r,e.UserCancelledError=a,e.ValidationError=s,e.default=Ce,e.logger=be,e.setDebugMode=me,Object.defineProperty(e,"__esModule",{value:!0})});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).SparkVault={})}(this,function(e){"use strict";class t extends Error{constructor(e,n,s,i){super(e),this.name="SparkVaultError",this.code=n,this.statusCode=s,this.details=i,Object.setPrototypeOf(this,t.prototype)}}class n extends t{constructor(e,t){super(e,"authentication_error",401,t),this.name="AuthenticationError",Object.setPrototypeOf(this,n.prototype)}}class s extends t{constructor(e,t){super(e,"authorization_error",403,t),this.name="AuthorizationError",Object.setPrototypeOf(this,s.prototype)}}class i extends t{constructor(e,t){super(e,"validation_error",400,t),this.name="ValidationError",Object.setPrototypeOf(this,i.prototype)}}class r extends t{constructor(e,t){super(e,"network_error",void 0,t),this.name="NetworkError",Object.setPrototypeOf(this,r.prototype)}}class o extends t{constructor(e="Request timed out"){super(e,"timeout_error"),this.name="TimeoutError",Object.setPrototypeOf(this,o.prototype)}}class a extends t{constructor(e="User cancelled the operation"){super(e,"user_cancelled"),this.name="UserCancelledError",Object.setPrototypeOf(this,a.prototype)}}class l extends t{constructor(){super("Popup was blocked. Please allow popups for this site.","popup_blocked"),this.name="PopupBlockedError",Object.setPrototypeOf(this,l.prototype)}}const d={maxAttempts:3,baseDelayMs:200,maxDelayMs:5e3,jitterFactor:.2,isRetryable:function(e){if(e instanceof TypeError)return!0;if(e instanceof DOMException&&"AbortError"===e.name)return!0;if("object"==typeof e&&null!==e&&"statusCode"in e){const t=e.statusCode;return t>=500||429===t}return!1}};function c(e,t,n,s){const i=t*Math.pow(2,e),r=Math.min(i,n);return r+r*s*Math.random()}function h(e){return new Promise(t=>setTimeout(t,e))}async function p(e,t={}){const n={...d,...t};let s;for(let t=0;t<n.maxAttempts;t++)try{return await e()}catch(e){s=e;if(t===n.maxAttempts-1||!n.isRetryable(e))throw e;const i=c(t,n.baseDelayMs,n.maxDelayMs,n.jitterFactor);await h(i)}throw s}class u{constructor(e){this.config=e}async request(e,t={}){const{retry:n}=t;if(n){return p(()=>this.executeRequest(e,t),{..."object"==typeof n?n:{},isRetryable:e=>this.isRetryableError(e)})}return this.executeRequest(e,t)}async executeRequest(e,n){const{method:s="GET",headers:i={},body:a,timeout:l=this.config.timeout}=n,d=`${this.config.apiBaseUrl}${e}`,c={"Content-Type":"application/json",Accept:"application/json",...i},h=new AbortController,p=setTimeout(()=>h.abort(),l);try{const e=await fetch(d,{method:s,headers:c,body:a?JSON.stringify(a):void 0,signal:h.signal});clearTimeout(p);const t=await this.parseResponse(e);if(!e.ok)throw this.createErrorFromResponse(e.status,t);return{data:t,status:e.status,headers:e.headers}}catch(e){if(clearTimeout(p),e instanceof t)throw e;if(e instanceof DOMException&&"AbortError"===e.name)throw new o;if(e instanceof TypeError)throw new r("Network request failed. Please check your connection.");throw new t(e instanceof Error?e.message:"Unknown error","unknown_error")}}isRetryableError(e){return e instanceof r||e instanceof o||e instanceof t&&void 0!==e.statusCode&&(e.statusCode>=500||429===e.statusCode)}async parseResponse(e){const n=e.headers.get("content-length");if(204===e.status||"0"===n)return null;const s=e.headers.get("content-type");if(s?.includes("application/json")){return await e.json()}const i=await e.text();throw new t(`Unexpected response format: expected JSON but received ${s??"unknown content type"}`,"invalid_response_format",e.status,{body:i.slice(0,500)})}createErrorFromResponse(e,r){const o="object"==typeof r&&null!==r?r:{},a=("string"==typeof o.message?o.message:null)??("string"==typeof o.error?o.error:null)??"Request failed",l="string"==typeof o.code?o.code:"api_error",d="object"==typeof o.details&&null!==o.details?o.details:void 0;switch(e){case 400:return new i(a,d);case 401:return new n(a,d);case 403:return new s(a,d);default:return new t(a,l,e,d)}}get(e,t){return this.request(e,{...t,method:"GET"})}post(e,t,n){return this.request(e,{...n,method:"POST",body:t})}put(e,t,n){return this.request(e,{...n,method:"PUT",body:t})}patch(e,t,n){return this.request(e,{...n,method:"PATCH",body:t})}delete(e,t){return this.request(e,{...t,method:"DELETE"})}async requestRaw(e,t={}){const{retry:n}=t;if(n){return p(()=>this.executeRequestRaw(e,t),{..."object"==typeof n?n:{},isRetryable:e=>this.isRetryableError(e)})}return this.executeRequestRaw(e,t)}async executeRequestRaw(e,n){const{method:s="GET",headers:i={},body:a,timeout:l=this.config.timeout}=n,d=`${this.config.apiBaseUrl}${e}`,c={"Content-Type":"application/json",...i},h=new AbortController,p=setTimeout(()=>h.abort(),l);try{const e=await fetch(d,{method:s,headers:c,body:a?JSON.stringify(a):void 0,signal:h.signal});if(clearTimeout(p),!e.ok){const t=await e.json().catch(()=>({}));throw this.createErrorFromResponse(e.status,t)}return e.blob()}catch(e){if(clearTimeout(p),e instanceof t)throw e;if(e instanceof DOMException&&"AbortError"===e.name)throw new o;if(e instanceof TypeError)throw new r("Network request failed. Please check your connection.");throw new t(e instanceof Error?e.message:"Unknown error","unknown_error")}}}class m{constructor(e){this.intervalId=null,this.secondsRemaining=e.duration,this.onTick=e.onTick,this.onComplete=e.onComplete}start(){this.stop(),this.onTick(this.secondsRemaining),this.intervalId=setInterval(()=>{this.secondsRemaining--,this.onTick(this.secondsRemaining),this.secondsRemaining<=0&&(this.stop(),this.onComplete())},1e3)}stop(){null!==this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}isRunning(){return null!==this.intervalId}getRemainingSeconds(){return this.secondsRemaining}}class v{constructor(e){this.intervalId=null,Number.isFinite(e.expiresAt)?this.expiresAt=e.expiresAt:(console.warn("[ExpirationTimer] Invalid expiresAt:",e.expiresAt),this.expiresAt=0),this.onTick=e.onTick,this.onExpired=e.onExpired}calculateRemaining(){const e=Math.floor(Date.now()/1e3),t=this.expiresAt-e;return!Number.isFinite(t)||t<0?0:Math.ceil(t)}start(){this.stop();const e=this.calculateRemaining();this.onTick(e),e<=0?this.onExpired():this.intervalId=setInterval(()=>{const e=this.calculateRemaining();this.onTick(e),e<=0&&(this.stop(),this.onExpired())},1e3)}stop(){null!==this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null)}isRunning(){return null!==this.intervalId}}function g(e){return function(e){let t="";for(let n=0;n<e.byteLength;n++)t+=String.fromCharCode(e[n]);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}(new Uint8Array(e))}class b{constructor(e,t=3e4){this.configCache=null,this.config=e,this.timeoutMs=t}get baseUrl(){return`${this.config.identityBaseUrl}/${this.config.accountId}`}async request(e,t,n){const s=`${this.baseUrl}${t}`,i={"Content-Type":"application/json",Accept:"application/json"},r=new AbortController,o=setTimeout(()=>r.abort(),this.timeoutMs);try{const t=await fetch(s,{method:e,headers:i,body:n?JSON.stringify(n):void 0,signal:r.signal}),o=await t.json();if(!t.ok){const e=o.error||{},n=e.message||o.message||"Request failed",s=e.code||o.code||"api_error";throw new f(n,s,t.status)}return o.data??o}catch(e){if(e instanceof Error&&"AbortError"===e.name)throw new f("Request timed out","timeout",0);throw e}finally{clearTimeout(o)}}async getConfig(){return this.configCache||(this.configCache=this.request("GET","/config")),this.configCache}preloadConfig(){this.configCache||(this.configCache=this.request("GET","/config"))}isConfigPreloaded(){return null!==this.configCache}async checkPasskey(e){return this.request("POST","/passkey/check",{email:e})}buildAuthContextParams(e){if(!e)return{};const t={};return e.authRequestId&&(t.auth_request_id=e.authRequestId),e.simpleMode&&(t.simple_mode={success_url:e.simpleMode.successUrl,failure_url:e.simpleMode.failureUrl,state:e.simpleMode.state}),t}async sendTotp(e){return this.request("POST","/totp/send",{recipient:e.recipient,method:e.method,...this.buildAuthContextParams(e.authContext)})}async verifyTotp(e){return this.request("POST","/totp/verify",{kindling:e.kindling,pin:e.pin,recipient:e.recipient,...this.buildAuthContextParams(e.authContext)})}async startPasskeyRegister(e){const t=await this.request("POST","/passkey/register",{email:e});return{challenge:t.options.challenge,rpId:t.options.rp.id,rpName:t.options.rp.name,userId:t.options.user.id,userName:t.options.user.name,timeout:t.options.timeout,session:t.session}}async completePasskeyRegister(e){const t=e.credential.response;return this.request("POST","/passkey/register/complete",{session:e.session,credential:{id:e.credential.id,rawId:g(e.credential.rawId),type:e.credential.type,response:{clientDataJSON:g(t.clientDataJSON),attestationObject:g(t.attestationObject)}}})}async startPasskeyVerify(e,t){const n=await this.request("POST","/passkey/verify",{email:e,...this.buildAuthContextParams(t)});return{challenge:n.options.challenge,rpId:n.options.rpId,rpName:"SparkVault Identity",timeout:n.options.timeout,allowCredentials:n.options.allowCredentials,session:n.session}}async completePasskeyVerify(e){const t=e.credential.response;return this.request("POST","/passkey/verify/complete",{session:e.session,...this.buildAuthContextParams(e.authContext),credential:{id:e.credential.id,rawId:g(e.credential.rawId),type:e.credential.type,response:{clientDataJSON:g(t.clientDataJSON),authenticatorData:g(t.authenticatorData),signature:g(t.signature),userHandle:t.userHandle?g(t.userHandle):null}}})}getSocialAuthUrl(e,t,n){const s=new URLSearchParams({redirect_uri:t,state:n});return`${this.baseUrl}/social/${e}?${s}`}async sendSparkLink(e,t){return this.request("POST","/sparklink/send",{email:e,type:"verify_identity",openerOrigin:"undefined"!=typeof window?window.location.origin:void 0,...this.buildAuthContextParams(t)})}async checkSparkLinkStatus(e,t){return this.request("GET",`/sparklink/status/${e}`)}}class f extends Error{constructor(e,t,n){super(e),this.name="IdentityApiError",this.code=t,this.statusCode=n}}const k={totp_email:{id:"totp_email",type:"totp",identityType:"email",name:"Email code",description:"Get a one-time code via email",icon:"email"},totp_sms:{id:"totp_sms",type:"totp",identityType:"phone",name:"Text message",description:"Get a one-time code via SMS",icon:"sms"},totp_voice:{id:"totp_voice",type:"totp",identityType:"phone",name:"Voice call",description:"Get a one-time code via phone call",icon:"phone"},passkey:{id:"passkey",type:"passkey",identityType:"email",name:"Passkey",description:"Use biometrics or security key",icon:"passkey"},sparklink:{id:"sparklink",type:"sparklink",identityType:"email",name:"SparkLink",description:"Get an instant sign-in link via email",icon:"link"},social_google:{id:"social_google",type:"social",identityType:"email",name:"Google",description:"Sign in with Google",icon:"google",provider:"google"},social_apple:{id:"social_apple",type:"social",identityType:"email",name:"Apple",description:"Sign in with Apple",icon:"apple",provider:"apple"},social_microsoft:{id:"social_microsoft",type:"social",identityType:"email",name:"Microsoft",description:"Sign in with Microsoft",icon:"microsoft",provider:"microsoft"},social_github:{id:"social_github",type:"social",identityType:"email",name:"GitHub",description:"Sign in with GitHub",icon:"github",provider:"github"},social_facebook:{id:"social_facebook",type:"social",identityType:"email",name:"Facebook",description:"Sign in with Facebook",icon:"facebook",provider:"facebook"},social_linkedin:{id:"social_linkedin",type:"social",identityType:"email",name:"LinkedIn",description:"Sign in with LinkedIn",icon:"linkedin",provider:"linkedin"}};function y(e){return e.map(e=>k[e]).filter(e=>void 0!==e)}class x{constructor(){this._sdkConfig=null,this._viewState={view:"loading"},this._recipient="",this._identityType="email",this._authContext=void 0,this._passkey={hasPasskey:null,isFallbackMode:!1,pendingResult:null},this._totp={kindling:"",method:null},this.listeners=new Set}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(const e of this.listeners)e(this._viewState)}get sdkConfig(){return this._sdkConfig}setConfig(e){this._sdkConfig=e}get accountId(){return this._sdkConfig?.accountId??""}getAvailableMethods(){if(!this._sdkConfig)return[];let e=y(this._sdkConfig.methods??[]);return e="phone"===this._identityType?e.filter(e=>"totp"===e.type&&"totp_sms"===e.id):e.filter(e=>"email"===e.identityType),e}isPasskeyEnabled(){return this._sdkConfig?.methods?.includes("passkey")??!1}get viewState(){return this._viewState}setViewState(e){this._viewState=e,this.notify()}get recipient(){return this._recipient}get identityType(){return this._identityType}setIdentity(e,t){this._recipient=e,this._identityType=t}getAllowedIdentityTypes(){return this._sdkConfig?.allowedIdentityTypes??["email"]}get authContext(){return this._authContext}setAuthContext(e){this._authContext=e}get passkey(){return this._passkey}setPasskeyStatus(e){this._passkey.hasPasskey=e}enablePasskeyFallback(){this._passkey.isFallbackMode=!0}setPendingResult(e){this._passkey.pendingResult=e}shouldShowPasskeyPrompt(){return"email"===this._identityType&&(!!this.isPasskeyEnabled()&&(!this.isPasskeyPromptDismissed()&&!0!==this._passkey.hasPasskey))}isPasskeyPromptDismissed(){return null!==function(e){const t=document.cookie.match(new RegExp(`(^| )${e}=([^;]+)`));return t?t[2]:null}(`sv_passkey_prompt_dismissed_${this.accountId}`)}dismissPasskeyPrompt(){!function(e,t,n){const s=new Date;s.setTime(s.getTime()+24*n*60*60*1e3);const i=`expires=${s.toUTCString()}`;document.cookie=`${e}=${t}; ${i}; path=/; SameSite=Lax`}(`sv_passkey_prompt_dismissed_${this.accountId}`,"1",30)}get totp(){return this._totp}setKindling(e){this._totp.kindling=e}setTotpMethod(e){this._totp.method=e}reset(){this._viewState={view:"loading"},this._recipient="",this._identityType="email",this._authContext=void 0,this._passkey.hasPasskey=null,this._passkey.isFallbackMode=!1,this._passkey.pendingResult=null,this._totp.kindling="",this._totp.method=null}}class w{constructor(e,t){this.api=e,this.state=t;const n=e.config;this.baseUrl=n.identityBaseUrl,this.accountId=n.accountId}async checkPasskey(){try{const e=await this.api.checkPasskey(this.state.recipient);return this.state.setPasskeyStatus(e.hasPasskey),{emailValid:e.email_valid,hasPasskey:e.hasPasskey}}catch(e){return console.warn("Passkey check failed:",e),this.state.setPasskeyStatus(null),null}}async register(){const e=await this.openPasskeyPopup("register");return e.success&&this.state.setPasskeyStatus(!0),e}async verify(){return this.openPasskeyPopup("verify")}async openPasskeyPopup(e){return new Promise(t=>{const n=new URLSearchParams({mode:e,email:this.state.recipient,origin:window.location.origin}),s=this.state.authContext;s?.authRequestId&&n.set("auth_request_id",s.authRequestId),s?.simpleMode&&(n.set("simple_mode","true"),n.set("success_url",s.simpleMode.successUrl),n.set("failure_url",s.simpleMode.failureUrl),s.simpleMode.state&&n.set("state",s.simpleMode.state));const i=`${this.baseUrl}/${this.accountId}/passkey/popup?${n}`,r=Math.round((window.screen.width-450)/2),o=Math.round((window.screen.height-500)/2),a=window.open(i,"sparkvault-passkey",`width=450,height=500,left=${r},top=${o},popup=1`);if(!a)return void t({success:!1,error:"Popup was blocked. Please allow popups for this site.",errorType:"popup_blocked"});let l=!1;const d=()=>{window.removeEventListener("message",c),clearTimeout(h),clearInterval(p)},c=e=>{if(!this.isValidMessageOrigin(e.origin))return;const n=e.data;"sparkvault-passkey-result"===n?.type&&(l=!0,d(),n.success&&n.data?t({success:!0,result:{token:n.data.token||"",identity:n.data.identity||this.state.recipient,identityType:n.data.identity_type||"email",redirect:n.data.redirect}}):t(this.handlePopupError(n.error,n.message)))};window.addEventListener("message",c);const h=setTimeout(()=>{l||(l=!0,d(),a.close(),t({success:!1,error:"Passkey operation timed out. Please try again.",errorType:"unknown"}))},6e4),p=setInterval(()=>{a.closed&&!l&&(l=!0,d(),t({success:!1,error:"Authentication was cancelled.",errorType:"cancelled"}))},500)})}isValidMessageOrigin(e){try{const t=new URL(e).hostname;return!("sparkvault.com"!==t&&!t.endsWith(".sparkvault.com"))||"localhost"===t}catch{return!1}}handlePopupError(e,t){return"cancelled"===e?{success:!1,error:t||"Authentication was cancelled. Please try again.",errorType:"cancelled"}:t?.includes("No passkey")||t?.includes("not found")?{success:!1,error:"No passkey found. Create one to continue.",errorType:"not_found"}:{success:!1,error:t||e||"Passkey authentication failed",errorType:"unknown"}}}class C{constructor(e,t){this.api=e,this.state=t}async send(e){try{const t=await this.api.sendTotp({recipient:this.state.recipient,method:e,authContext:this.state.authContext});return this.state.setKindling(t.kindling),this.state.setTotpMethod(e),{success:!0,kindling:t.kindling,expiresAt:t.expires_at}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to send code"}}}async resend(){const e=this.state.totp.method;if(!e)return{success:!1,error:"No TOTP method set"};try{const t=await this.api.sendTotp({recipient:this.state.recipient,method:e,authContext:this.state.authContext});return this.state.setKindling(t.kindling),{success:!0,kindling:t.kindling,expiresAt:t.expires_at}}catch(e){return{success:!1,error:`Failed to resend: ${e instanceof Error?e.message:"Failed to resend code"}`}}}async verify(e){const t=this.state.totp.kindling;if(!t)return{success:!1,error:"No kindling available"};try{const n=await this.api.verifyTotp({kindling:t,pin:e,recipient:this.state.recipient,authContext:this.state.authContext});return n.verified&&n.token?{success:!0,result:{token:n.token,identity:n.identity??this.state.recipient,identityType:n.identity_type??this.state.identityType,redirect:n.redirect}}:(n.kindling&&this.state.setKindling(n.kindling),{success:!1,newKindling:n.kindling,retryAfter:n.retry_after,backoffExpires:n.expires_at,error:"Invalid code. Please try again."})}catch(e){return{success:!1,error:e instanceof Error?e.message:"Verification failed"}}}}class E{constructor(e,t){this.api=e,this.state=t}async send(){try{const e=await this.api.sendSparkLink(this.state.recipient,this.state.authContext);return{success:!0,sparkId:e.sparkId,expiresAt:e.expiresAt}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to send SparkLink"}}}async checkStatus(e){try{const t=await this.api.checkSparkLinkStatus(e);return{verified:t.verified,token:t.token,identity:t.identity,identityType:t.identityType,redirect:t.redirect}}catch{return{verified:!1}}}}const S="sparkvault-identity-styles";function B(e){if(document.getElementById(S))return e.branding,void function(e){const t=document.getElementById("sparkvault-identity-overlay");t&&(!1!==e?t.classList.add("sv-blur"):t.classList.remove("sv-blur"))}(e.backdropBlur);const t=document.createElement("style");t.id=S,t.textContent=function(e){const{branding:t,backdropBlur:n}=e,s="dark"===$(t),i=!1!==n,r={primary:"#4F46E5",primaryHover:"#4338CA",primaryLight:s?"rgba(99, 102, 241, 0.15)":"rgba(79, 70, 229, 0.08)",error:"#DC2626",errorLight:s?"rgba(220, 38, 38, 0.15)":"#FEF2F2",errorBorder:s?"rgba(220, 38, 38, 0.3)":"#FECACA",bg:s?"#0F0F0F":"#FFFFFF",bgSubtle:s?"#171717":"#FAFAFA",bgHover:s?"#1A1A1A":"#F5F5F5",bgInput:s?"#0F0F0F":"#FFFFFF",border:s?"#262626":"#E5E5E5",borderHover:s?"#404040":"#D4D4D4",borderFocus:"#4F46E5",textPrimary:s?"#FAFAFA":"#0A0A0A",textSecondary:s?"#A3A3A3":"#525252",textMuted:"#737373",textOnPrimary:"#FFFFFF",shadowSm:s?"0 1px 2px rgba(0, 0, 0, 0.4)":"0 1px 2px rgba(0, 0, 0, 0.04)",shadowLg:s?"0 8px 24px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05)":"0 8px 24px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04)"};return`\n /* ========================================\n OVERLAY & MODAL CONTAINER\n ======================================== */\n\n .sv-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, ${s?"0.7":"0.5"});\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n padding: 16px;\n box-sizing: border-box;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n .sv-overlay.sv-blur {\n backdrop-filter: blur(${i?"8px":"0"});\n -webkit-backdrop-filter: blur(${i?"8px":"0"});\n }\n\n .sv-modal {\n background: ${r.bg};\n border-radius: 16px;\n box-shadow: ${r.shadowLg};\n width: 100%;\n max-width: 400px;\n max-height: calc(100vh - 32px);\n display: flex;\n flex-direction: column;\n color: ${r.textPrimary};\n }\n\n /* ========================================\n HEADER\n ======================================== */\n\n .sv-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid ${r.border};\n background: ${r.bg};\n flex-shrink: 0;\n }\n\n .sv-header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n }\n\n .sv-logo {\n height: 28px;\n width: auto;\n max-width: 140px;\n object-fit: contain;\n flex-shrink: 0;\n }\n\n .sv-company-name {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sv-close-btn {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n color: ${r.textMuted};\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .sv-close-btn:hover {\n background: ${r.bgHover};\n color: ${r.textPrimary};\n }\n\n .sv-close-btn:focus-visible {\n outline: 2px solid ${r.borderFocus};\n outline-offset: 2px;\n }\n\n .sv-close-btn:active {\n transform: scale(0.96);\n }\n\n /* ========================================\n BODY\n ======================================== */\n\n .sv-body {\n padding: 24px 28px;\n overflow-y: auto;\n flex: 1;\n }\n\n /* ========================================\n TYPOGRAPHY\n ======================================== */\n\n .sv-title {\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.02em;\n line-height: 1.3;\n margin: 0 0 6px 0;\n text-align: center;\n color: ${r.textPrimary};\n }\n\n .sv-subtitle {\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n color: ${r.textSecondary};\n margin: 0 0 16px 0;\n text-align: center;\n }\n\n .sv-subtitle strong {\n color: ${r.textPrimary};\n font-weight: 500;\n }\n\n /* ========================================\n FORM ELEMENTS\n ======================================== */\n\n .sv-form-group {\n margin-bottom: 16px;\n }\n\n .sv-label {\n display: block;\n font-size: 13px;\n font-weight: 500;\n letter-spacing: -0.005em;\n margin-bottom: 6px;\n color: ${r.textPrimary};\n }\n\n .sv-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.4;\n border: 1px solid ${r.border};\n border-radius: 8px;\n background: ${r.bgInput};\n color: ${r.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-input:hover:not(:focus):not(:disabled) {\n border-color: ${r.borderHover};\n }\n\n .sv-input:focus {\n outline: none;\n border-color: ${r.borderFocus};\n box-shadow: 0 0 0 3px ${r.primaryLight};\n }\n\n .sv-input::placeholder {\n color: ${r.textMuted};\n }\n\n .sv-input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-input.sv-input-error,\n .sv-input.sv-email-input-error {\n border-color: ${r.error};\n }\n\n .sv-input.sv-input-error:focus,\n .sv-input.sv-email-input-error:focus {\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\n }\n\n /* ========================================\n BUTTONS\n ======================================== */\n\n .sv-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 10px 16px;\n font-size: 14px;\n font-weight: 500;\n letter-spacing: -0.005em;\n line-height: 1.4;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;\n box-sizing: border-box;\n }\n\n .sv-btn:focus-visible {\n outline: 2px solid ${r.borderFocus};\n outline-offset: 2px;\n }\n\n .sv-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-btn:active:not(:disabled) {\n transform: scale(0.98);\n }\n\n /* Primary Button */\n .sv-btn-primary,\n .sv-btn-email-primary {\n background: ${r.primary};\n color: ${r.textOnPrimary};\n box-shadow: ${r.shadowSm};\n }\n\n .sv-btn-primary:hover:not(:disabled),\n .sv-btn-email-primary:hover:not(:disabled) {\n background: ${r.primaryHover};\n }\n\n /* Secondary Button */\n .sv-btn-secondary {\n background: ${r.bgSubtle};\n color: ${r.textPrimary};\n border: 1px solid ${r.border};\n }\n\n .sv-btn-secondary:hover:not(:disabled) {\n background: ${r.bgHover};\n border-color: ${r.borderHover};\n }\n\n /* Method Button */\n .sv-btn-method {\n background: ${r.bg};\n border: 1px solid ${r.border};\n color: ${r.textPrimary};\n text-align: left;\n padding: 12px 14px;\n margin-bottom: 8px;\n }\n\n .sv-btn-method:hover:not(:disabled) {\n background: ${r.bgSubtle};\n border-color: ${r.borderHover};\n }\n\n .sv-btn-method:last-child {\n margin-bottom: 0;\n }\n\n /* Error Buttons */\n .sv-btn-error-primary {\n background: ${r.error};\n color: ${r.textOnPrimary};\n box-shadow: ${r.shadowSm};\n }\n\n .sv-btn-error-primary:hover:not(:disabled) {\n background: #B91C1C;\n }\n\n .sv-btn-error-secondary {\n background: ${r.bgSubtle};\n color: ${r.textSecondary};\n border: 1px solid ${r.border};\n }\n\n .sv-btn-error-secondary:hover:not(:disabled) {\n background: ${r.bgHover};\n color: ${r.textPrimary};\n }\n\n /* ========================================\n METHOD SELECTION\n ======================================== */\n\n .sv-method-content {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n }\n\n .sv-method-icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n color: ${r.textSecondary};\n }\n\n .sv-method-icon svg {\n width: 20px;\n height: 20px;\n }\n\n .sv-method-text {\n flex: 1;\n min-width: 0;\n }\n\n .sv-method-name {\n font-weight: 500;\n font-size: 14px;\n color: ${r.textPrimary};\n }\n\n .sv-method-description {\n font-size: 12px;\n color: ${r.textMuted};\n margin-top: 1px;\n }\n\n /* ========================================\n TOTP INPUT\n ======================================== */\n\n .sv-totp-input-group {\n display: flex;\n gap: 8px;\n justify-content: center;\n margin-bottom: 16px;\n }\n\n .sv-totp-digit {\n width: 44px;\n height: 52px;\n text-align: center;\n font-size: 20px;\n font-weight: 600;\n letter-spacing: 0;\n border: 1px solid ${r.border};\n border-radius: 8px;\n background: ${r.bgInput};\n color: ${r.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-totp-digit:hover:not(:focus):not(:disabled) {\n border-color: ${r.borderHover};\n }\n\n .sv-totp-digit:focus {\n outline: none;\n border-color: ${r.borderFocus};\n box-shadow: 0 0 0 3px ${r.primaryLight};\n }\n\n .sv-totp-digit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* ========================================\n BACK LINK\n ======================================== */\n\n .sv-back-link {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n color: ${r.textSecondary};\n font-size: 13px;\n font-weight: 500;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n margin-bottom: 16px;\n transition: color 0.15s ease;\n }\n\n .sv-back-link:hover:not(:disabled) {\n color: ${r.primary};\n }\n\n .sv-back-link:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .sv-back-link svg {\n width: 14px;\n height: 14px;\n }\n\n /* ========================================\n ERROR MESSAGE\n ======================================== */\n\n .sv-error {\n background: ${r.errorLight};\n border: 1px solid ${r.errorBorder};\n color: ${r.error};\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 450;\n margin-bottom: 16px;\n }\n\n /* ========================================\n LOADING STATE\n ======================================== */\n\n .sv-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n gap: 16px;\n }\n\n .sv-spinner {\n width: 28px;\n height: 28px;\n border: 2.5px solid ${r.border};\n border-top-color: ${r.primary};\n border-radius: 50%;\n animation: sv-spin 0.7s linear infinite;\n }\n\n .sv-loading-text {\n font-size: 14px;\n color: ${r.textSecondary};\n margin: 0;\n }\n\n @keyframes sv-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ========================================\n FOOTER\n ======================================== */\n\n .sv-footer {\n padding: 10px 20px;\n border-top: 1px solid ${r.border};\n text-align: center;\n background: ${r.bgSubtle};\n flex-shrink: 0;\n }\n\n .sv-footer-text {\n font-size: 10px;\n color: ${r.textMuted};\n letter-spacing: 0.02em;\n }\n\n .sv-footer-link {\n color: ${r.textSecondary};\n text-decoration: none;\n font-weight: 500;\n transition: color 0.15s ease;\n }\n\n .sv-footer-link:hover {\n color: ${r.primary};\n }\n\n /* ========================================\n IDENTITY INPUT VIEW\n ======================================== */\n\n .sv-email-view {\n display: flex;\n flex-direction: column;\n }\n\n .sv-email-header {\n margin-bottom: 16px;\n }\n\n .sv-email-subtitle {\n font-size: 14px;\n font-weight: 500;\n line-height: 1.4;\n color: ${r.textSecondary};\n margin: 0;\n }\n\n .sv-email-error-container {\n width: 100%;\n }\n\n .sv-email-form {\n width: 100%;\n }\n\n .sv-email-input-wrapper {\n margin-bottom: 14px;\n }\n\n .sv-email-label {\n display: block;\n font-size: 13px;\n font-weight: 500;\n letter-spacing: -0.005em;\n margin-bottom: 6px;\n color: ${r.textPrimary};\n }\n\n .sv-email-input {\n width: 100%;\n padding: 10px 12px;\n font-size: 15px;\n font-weight: 400;\n line-height: 1.4;\n border: 1px solid ${r.border};\n border-radius: 8px;\n background: ${r.bgInput};\n color: ${r.textPrimary};\n box-sizing: border-box;\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .sv-email-input:hover:not(:focus):not(:disabled) {\n border-color: ${r.borderHover};\n }\n\n .sv-email-input:focus {\n outline: none;\n border-color: ${r.borderFocus};\n box-shadow: 0 0 0 3px ${r.primaryLight};\n }\n\n .sv-email-input::placeholder {\n color: ${r.textMuted};\n }\n\n .sv-email-input-error {\n border-color: ${r.error};\n }\n\n .sv-email-input-error:focus {\n box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);\n }\n\n /* ========================================\n ERROR VIEW\n ======================================== */\n\n .sv-error-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n }\n\n .sv-error-icon-container {\n margin-bottom: 16px;\n }\n\n .sv-error-icon {\n width: 48px;\n height: 48px;\n }\n\n .sv-error-content {\n margin-bottom: 24px;\n }\n\n .sv-error-title {\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.02em;\n margin: 0 0 8px 0;\n color: ${r.textPrimary};\n }\n\n .sv-error-message {\n font-size: 14px;\n line-height: 1.5;\n color: ${r.textSecondary};\n margin: 0 0 16px 0;\n }\n\n .sv-error-code-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n background: ${r.errorLight};\n border: 1px solid ${r.errorBorder};\n border-radius: 6px;\n }\n\n .sv-error-code-label {\n font-size: 10px;\n font-weight: 600;\n color: ${s?"#F87171":"#991B1B"};\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .sv-error-code-value {\n font-size: 11px;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', monospace;\n color: ${r.error};\n font-weight: 500;\n }\n\n .sv-error-actions {\n display: flex;\n gap: 10px;\n width: 100%;\n }\n\n .sv-error-actions .sv-btn {\n flex: 1;\n }\n\n /* ========================================\n TOTP VIEW\n ======================================== */\n\n .sv-resend-container {\n text-align: center;\n margin-top: 16px;\n }\n\n /* ========================================\n PASSKEY VIEW\n ======================================== */\n\n .sv-passkey-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n display: block;\n }\n\n .sv-passkey-description {\n font-size: 13px;\n color: ${r.textMuted};\n text-align: center;\n margin: 0 0 16px 0;\n line-height: 1.4;\n }\n\n .sv-fallback-link {\n display: block;\n width: 100%;\n text-align: center;\n color: ${r.textSecondary};\n font-size: 13px;\n font-weight: 400;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 12px 0 0 0;\n margin-top: 8px;\n transition: color 0.15s ease;\n }\n\n .sv-fallback-link:hover {\n color: ${r.primary};\n text-decoration: underline;\n }\n\n /* ========================================\n PASSKEY PROMPT VIEW\n ======================================== */\n\n .sv-passkey-prompt-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n display: block;\n color: ${r.primary};\n }\n\n .sv-passkey-prompt-benefits {\n background: ${r.bgSubtle};\n border-radius: 8px;\n padding: 10px 14px;\n margin-bottom: 16px;\n }\n\n .sv-passkey-prompt-benefits ul {\n list-style: none;\n margin: 0;\n padding: 0;\n }\n\n .sv-passkey-prompt-benefits li {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 13px;\n color: ${r.textSecondary};\n padding: 6px 0;\n }\n\n .sv-passkey-prompt-benefits li svg {\n width: 16px;\n height: 16px;\n color: ${r.primary};\n flex-shrink: 0;\n }\n\n .sv-skip-link {\n display: block;\n width: 100%;\n text-align: center;\n color: ${r.textMuted};\n font-size: 13px;\n font-weight: 400;\n text-decoration: none;\n cursor: pointer;\n background: none;\n border: none;\n padding: 12px 0 0 0;\n transition: color 0.15s ease;\n }\n\n .sv-skip-link:hover {\n color: ${r.textSecondary};\n text-decoration: underline;\n }\n\n /* ========================================\n SPARKLINK WAITING VIEW\n ======================================== */\n\n .sv-sparklink-icon-container {\n display: flex;\n justify-content: center;\n margin-bottom: 16px;\n }\n\n .sv-sparklink-icon {\n width: 56px;\n height: 56px;\n color: ${r.primary};\n background: ${r.primaryLight};\n padding: 14px;\n border-radius: 50%;\n box-sizing: content-box;\n }\n\n .sv-sparklink-waiting {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n background: ${r.bgSubtle};\n border-radius: 10px;\n padding: 14px 18px;\n margin: 16px 0;\n }\n\n .sv-spinner-small {\n width: 18px;\n height: 18px;\n border: 2px solid ${r.border};\n border-top-color: ${r.primary};\n border-radius: 50%;\n animation: sv-spin 0.7s linear infinite;\n flex-shrink: 0;\n }\n\n .sv-sparklink-waiting-text {\n font-size: 13px;\n font-weight: 450;\n color: ${r.textSecondary};\n }\n\n .sv-sparklink-countdown {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 13px;\n color: ${r.textMuted};\n margin-bottom: 20px;\n }\n\n .sv-sparklink-countdown-time {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', monospace;\n font-weight: 600;\n font-size: 14px;\n color: ${r.textPrimary};\n min-width: 40px;\n }\n\n .sv-sparklink-fallback {\n text-align: center;\n margin-top: 12px;\n padding-top: 16px;\n border-top: 1px solid ${r.border};\n }\n\n .sv-sparklink-fallback .sv-back-link {\n margin-bottom: 0;\n font-size: 12px;\n color: ${r.textMuted};\n }\n\n .sv-sparklink-fallback .sv-back-link:hover:not(:disabled) {\n color: ${r.textSecondary};\n }\n\n /* SparkLink Expired State */\n .sv-sparklink-expired {\n flex-direction: column;\n gap: 12px;\n background: ${r.bgSubtle};\n border: 1px solid ${r.border};\n }\n\n .sv-sparklink-expired-icon {\n display: flex;\n justify-content: center;\n }\n\n .sv-sparklink-expired-icon svg {\n width: 48px;\n height: 48px;\n }\n\n .sv-sparklink-expired-text {\n font-size: 14px;\n font-weight: 500;\n color: ${r.textSecondary};\n text-align: center;\n }\n\n .sv-expired-icon {\n width: 48px;\n height: 48px;\n }\n\n /* ========================================\n DIVIDER\n ======================================== */\n\n .sv-divider {\n display: flex;\n align-items: center;\n margin: 20px 0;\n }\n\n .sv-divider::before,\n .sv-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: ${r.border};\n }\n\n .sv-divider-text {\n padding: 0 12px;\n font-size: 12px;\n color: ${r.textMuted};\n }\n\n /* ========================================\n ACCESSIBILITY\n ======================================== */\n\n .sv-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ========================================\n INLINE CONTAINER\n ======================================== */\n\n .sv-inline-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n background: ${r.bg};\n color: ${r.textPrimary};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n border-radius: 12px;\n border: 1px solid ${r.border};\n }\n\n .sv-inline-header {\n border-bottom: 1px solid ${r.border};\n }\n\n .sv-inline-body {\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-height: 200px;\n flex: 1;\n }\n\n /* ========================================\n RESPONSIVE\n ======================================== */\n\n @media (max-width: 480px) {\n .sv-modal {\n max-width: 100%;\n max-height: 100%;\n border-radius: 0;\n }\n\n .sv-overlay {\n padding: 0;\n }\n\n .sv-body {\n padding: 24px 28px;\n }\n\n .sv-totp-digit {\n width: 40px;\n height: 48px;\n font-size: 18px;\n }\n\n .sv-error-actions {\n flex-direction: column;\n }\n }\n\n @media (max-width: 360px) {\n .sv-totp-input-group {\n gap: 6px;\n }\n\n .sv-totp-digit {\n width: 36px;\n height: 44px;\n font-size: 16px;\n }\n }\n `}(e),document.head.appendChild(t)}function $(e){return e?.themeMode??"light"}function T(e,t=16,n=16){const s=document.createElementNS("http://www.w3.org/2000/svg","svg");return s.setAttribute("viewBox",e),s.setAttribute("width",String(t)),s.setAttribute("height",String(n)),s.setAttribute("fill","none"),s.setAttribute("xmlns","http://www.w3.org/2000/svg"),s}function L(e,t={}){const n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d",e);for(const[e,s]of Object.entries(t))n.setAttribute(e,s);return n}function M(e,t,n,s={}){const i=document.createElementNS("http://www.w3.org/2000/svg","circle");i.setAttribute("cx",String(e)),i.setAttribute("cy",String(t)),i.setAttribute("r",String(n));for(const[e,t]of Object.entries(s))i.setAttribute(e,t);return i}function I(){const e=T("0 0 16 16");return e.appendChild(L("M13.25 4.75L6 12 2.75 8.75",{stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})),e}function H(){const e=T("0 0 16 16");return e.appendChild(L("M10 12L6 8L10 4",{stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"})),e}function A(){const e=T("0 0 20 20",20,20);return e.appendChild(L("M15 5L5 15M5 5L15 15",{stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round"})),e}function P(){const e=T("0 0 56 56",56,56);e.classList.add("sv-passkey-icon"),e.appendChild(M(28,28,26,{fill:"#EEF2FF",stroke:"#E0E7FF","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");t.setAttribute("transform","translate(28, 28)");const n={stroke:"#4F46E5","stroke-width":"2.5","stroke-linecap":"round","stroke-linejoin":"round",fill:"none"};return t.appendChild(M(-6,-6,6,n)),t.appendChild(L("M-1.5 -1.5L10 10",n)),t.appendChild(L("M6 6L6 10",n)),t.appendChild(L("M10 10L10 14",n)),e.appendChild(t),e}function N(e){switch(e){case"email":default:return F();case"phone":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M18 14v2.5a1.5 1.5 0 01-1.64 1.5 14.85 14.85 0 01-6.47-2.3 14.63 14.63 0 01-4.5-4.5A14.85 14.85 0 013.1 4.64 1.5 1.5 0 014.59 3H7.1a1.5 1.5 0 011.5 1.29 9.63 9.63 0 00.52 2.11 1.5 1.5 0 01-.34 1.58l-.95.95a12 12 0 004.5 4.5l.95-.95a1.5 1.5 0 011.58-.34 9.63 9.63 0 002.11.52A1.5 1.5 0 0118 14z")),e}();case"fingerprint":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M2 10c0-4.42 3.58-8 8-8 2.65 0 5 1.29 6.47 3.28")),e.appendChild(L("M4 16.58c.42-.35.79-.76 1.1-1.22")),e.appendChild(L("M14.41 17.51c.09-.45.32-1.73.38-2.26")),e.appendChild(L("M10 8.33a1.5 1.5 0 00-1.5 1.5c0 .77-.08 1.88-.2 3")),e.appendChild(L("M7.21 18.33c.16-.5.34-1 .43-1.5")),e.appendChild(L("M11.67 10.93c0 1.79 0 4.79-.75 6.65")),e.appendChild(L("M17.33 13.33c.15-1.5.1-4.02 0-4.5")),e.appendChild(L("M7.5 5.67a4.5 4.5 0 016.75 3.9c0 .35 0 .88-.02 1.5")),e}();case"link":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M8.33 10.83a3.75 3.75 0 005.66.41l2.25-2.25a3.75 3.75 0 00-5.3-5.3l-1.29 1.28")),e.appendChild(L("M11.67 9.17a3.75 3.75 0 00-5.66-.41l-2.25 2.25a3.75 3.75 0 005.3 5.3l1.28-1.28")),e}();case"google":return function(){const e=T("0 0 20 20",20,20);return e.appendChild(L("M18.8 10.21c0-.65-.06-1.28-.17-1.88H10v3.55h4.93c-.21 1.14-.87 2.11-1.84 2.76v2.3h2.98c1.73-1.6 2.73-3.96 2.73-6.73z",{fill:"#4285F4"})),e.appendChild(L("M10 19.17c2.48 0 4.55-.82 6.07-2.23l-2.98-2.3c-.82.55-1.86.88-3.09.88-2.38 0-4.4-1.6-5.13-3.77H1.82v2.37c1.52 3.02 4.6 5.05 8.18 5.05z",{fill:"#34A853"})),e.appendChild(L("M4.87 11.74c-.18-.55-.29-1.14-.29-1.74s.1-1.19.29-1.74V5.89H1.82c-.6 1.23-.94 2.6-.94 4.11s.34 2.88.94 4.11l3.05-2.37z",{fill:"#FBBC05"})),e.appendChild(L("M10 4.48c1.35 0 2.55.47 3.5 1.37l2.63-2.63C14.53 1.74 12.47.83 10 .83c-3.58 0-6.66 2.03-8.18 5.05l3.05 2.37c.72-2.17 2.75-3.77 5.13-3.77z",{fill:"#EA4335"})),e}();case"apple":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("fill","currentColor"),e.appendChild(L("M14.21 16.9c-.82.79-1.71.67-2.57.29-.91-.38-1.74-.4-2.7 0-1.2.51-1.83.37-2.55-.29C2.7 12.71 3.3 6.33 7.54 6.09c1.13.06 1.91.61 2.57.66.98-.2 1.92-.78 2.97-.7 1.26.1 2.21.6 2.83 1.5-2.6 1.56-1.98 4.99.4 5.94-.48 1.25-1.09 2.49-2.11 3.41h.01zM10.02 6.04c-.12-1.86 1.38-3.39 3.11-3.54.24 2.15-1.95 3.75-3.11 3.54z")),e}();case"microsoft":return function(){const e=T("0 0 20 20",20,20);return e.appendChild(L("M1 1h8.33v8.33H1z",{fill:"#F25022"})),e.appendChild(L("M1 10.67h8.33V19H1z",{fill:"#00A4EF"})),e.appendChild(L("M10.67 1H19v8.33h-8.33z",{fill:"#7FBA00"})),e.appendChild(L("M10.67 10.67H19V19h-8.33z",{fill:"#FFB900"})),e}();case"github":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("fill","currentColor"),e.appendChild(L("M10 0C4.48 0 0 4.48 0 10c0 4.42 2.86 8.17 6.84 9.49.5.09.68-.22.68-.48 0-.24-.01-1.02-.01-1.86-2.51.46-3.16-.61-3.36-1.18-.11-.29-.6-1.18-1.02-1.41-.35-.19-.85-.65-.01-.66.79-.01 1.35.72 1.54 1.02.9 1.51 2.34 1.09 2.91.83.09-.65.35-1.09.64-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.99 1.02-2.69-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02.8-.22 1.65-.33 2.5-.33s1.7.11 2.5.33c1.91-1.3 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.02 1.59 1.02 2.69 0 3.84-2.34 4.69-4.57 4.94.36.31.67.91.67 1.85 0 1.34-.01 2.41-.01 2.75 0 .27.18.58.69.48C17.14 18.16 20 14.42 20 10c0-5.52-4.48-10-10-10z")),e}();case"facebook":return function(){const e=T("0 0 20 20",20,20);return e.appendChild(L("M20 10.06c0-5.52-4.48-10-10-10S0 4.53 0 10.06c0 4.99 3.66 9.13 8.44 9.88v-6.99H5.9v-2.89h2.54V7.85c0-2.51 1.49-3.89 3.78-3.89 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.77-1.63 1.56v1.88h2.77l-.44 2.89h-2.33v6.99c4.78-.75 8.44-4.89 8.44-9.88z",{fill:"#1877F2"})),e}();case"linkedin":return function(){const e=T("0 0 20 20",20,20);return e.appendChild(L("M17.04 17.04h-2.96v-4.64c0-1.11-.02-2.53-1.54-2.53-1.55 0-1.78 1.2-1.78 2.45v4.73H7.8V7.5h2.84v1.3h.04c.4-.75 1.36-1.54 2.81-1.54 3 0 3.56 1.98 3.56 4.55v5.24zM4.45 6.19c-.95 0-1.72-.77-1.72-1.72s.77-1.72 1.72-1.72 1.72.77 1.72 1.72-.77 1.72-1.72 1.72zm1.48 10.85H2.96V7.5h2.97v9.54zM18.52 0H1.47C.66 0 0 .65 0 1.44v17.12c0 .79.66 1.44 1.48 1.44h17.04c.82 0 1.48-.65 1.48-1.44V1.44c0-.79-.66-1.44-1.48-1.44z",{fill:"#0A66C2"})),e}();case"building":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M2.5 17.5h15")),e.appendChild(L("M4.17 17.5V5.83L10.83 2.5v15")),e.appendChild(L("M15.83 17.5V9.17l-5-3.33")),e.appendChild(L("M7.5 7.5v.01")),e.appendChild(L("M7.5 10v.01")),e.appendChild(L("M7.5 12.5v.01")),e.appendChild(L("M7.5 15v.01")),e}();case"users":return function(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M14.17 17.5v-1.67a3.33 3.33 0 00-3.34-3.33H4.17a3.33 3.33 0 00-3.34 3.33v1.67")),e.appendChild(M(7.5,5.83,3.33,{stroke:"currentColor","stroke-width":"1.5",fill:"none"})),e.appendChild(L("M19.17 17.5v-1.67a3.33 3.33 0 00-2.5-3.22")),e.appendChild(L("M13.33 2.6a3.33 3.33 0 010 6.46")),e}()}}function F(){const e=T("0 0 20 20",20,20);return e.setAttribute("stroke","currentColor"),e.setAttribute("stroke-width","1.5"),e.setAttribute("stroke-linecap","round"),e.setAttribute("stroke-linejoin","round"),e.appendChild(L("M3 4h14c.55 0 1 .45 1 1v10c0 .55-.45 1-1 1H3c-.55 0-1-.45-1-1V5c0-.55.45-1 1-1z")),e.appendChild(L("M18 5l-8 5.5L2 5")),e}const _={companyName:"",logoLight:null,logoDark:null};class D{constructor(){this.elements=null,this.onCloseCallback=null,this.keydownHandler=null,this.overlayClickHandler=null,this.closeBtnClickHandler=null,this.closeBtn=null,this.backdropBlur=!0,this.effectiveTheme="light",this.headerElement=null}createLoading(e,t){return this.create({branding:_,backdropBlur:e.backdropBlur},t)}updateBranding(e){if(!this.elements)return;this.effectiveTheme=$(e);const t=this.createHeader(e);this.headerElement?.parentNode&&this.headerElement.parentNode.replaceChild(t,this.headerElement),this.headerElement=t}updateBackdropBlur(e){this.elements&&(this.backdropBlur=e,e?this.elements.overlay.classList.add("sv-blur"):this.elements.overlay.classList.remove("sv-blur"))}create(e,t){if(this.elements)return this.elements;this.onCloseCallback=t,this.backdropBlur=!1!==e.backdropBlur,this.effectiveTheme=$(e.branding);B({branding:e.branding,backdropBlur:e.backdropBlur});const n=document.createElement("div");n.id="sparkvault-identity-overlay",n.className=this.backdropBlur?"sv-overlay sv-blur":"sv-overlay",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-labelledby","sv-modal-title");const s=document.createElement("div");s.id="sparkvault-identity-modal",s.className="sv-modal";const i=this.createHeader(e.branding);this.headerElement=i;const r=document.createElement("div");r.className="sv-body";const o=document.createElement("div");o.className="sv-footer";const a=document.createElement("span");a.className="sv-footer-text",a.appendChild(document.createTextNode("Secured by "));const l=document.createElement("a");l.href="https://sparkvault.com",l.target="_blank",l.rel="noopener noreferrer",l.className="sv-footer-link",l.style.color="inherit",l.style.textDecoration="none",l.textContent="SparkVault",a.appendChild(l),o.appendChild(a),s.appendChild(i),s.appendChild(r),s.appendChild(o),n.appendChild(s),this.overlayClickHandler=e=>{e.target===n&&this.handleClose()},n.addEventListener("click",this.overlayClickHandler),this.keydownHandler=e=>{"Escape"===e.key&&this.handleClose()},document.addEventListener("keydown",this.keydownHandler),document.body.appendChild(n),document.body.style.overflow="hidden",this.elements={overlay:n,modal:s,header:i,body:r,footer:o};const d=r.querySelector("input, button");return d instanceof HTMLElement&&d.focus(),this.elements}createHeader(e){const t=document.createElement("div");t.className="sv-header";const n=document.createElement("div");n.className="sv-header-title";const s="dark"===this.effectiveTheme?e.logoDark||e.logoLight:e.logoLight||e.logoDark;if(s){const t=document.createElement("img");t.className="sv-logo",t.src=s,t.alt=e.companyName,n.appendChild(t);const i=document.createElement("span");i.className="sv-sr-only",i.id="sv-modal-title",i.textContent=e.companyName,n.appendChild(i)}else{const t=document.createElement("h2");t.className="sv-company-name",t.id="sv-modal-title",t.textContent=e.companyName,n.appendChild(t)}return this.closeBtn=document.createElement("button"),this.closeBtn.className="sv-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.appendChild(A()),this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(n),t.appendChild(this.closeBtn),t}handleClose(){this.onCloseCallback&&this.onCloseCallback()}getBody(){return this.elements?.body??null}isOpen(){return null!==this.elements}destroy(){this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null),this.elements&&this.overlayClickHandler&&(this.elements.overlay.removeEventListener("click",this.overlayClickHandler),this.overlayClickHandler=null),this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.elements&&(this.elements.overlay.remove(),this.elements=null),this.headerElement=null,document.body.style.overflow="",this.onCloseCallback=null}}function z(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function R(e,t){const n=document.createElement("div");return e&&(n.className=e),n}function O(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function U(e){const t=document.createElement("div");return t.className="sv-error",t.setAttribute("role","alert"),t.textContent=e,t}function V(e){const t=e.trim().toLowerCase();return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)&&t.length<=254?t:null}function j(e){const t=e.trim().startsWith("+"),n=e.replace(/\D/g,"");return 10===n.length?`+1${n}`:11===n.length&&n.startsWith("1")||t&&n.length>=10&&n.length<=15?`+${n}`:null}function q(e){const t=e.replace(/\D/g,""),n=t.startsWith("1")&&t.length>10?t.slice(1):t;return 0===n.length?"":n.length<=3?`(${n}`:n.length<=6?`(${n.slice(0,3)}) ${n.slice(3)}`:`(${n.slice(0,3)}) ${n.slice(3,6)}-${n.slice(6,10)}`}class K{constructor(e={}){this.message=e.message??"Loading..."}render(){const e=R("sv-loading"),t=document.createElement("div");t.className="sv-spinner",t.setAttribute("role","status"),t.setAttribute("aria-label","Loading");const n=document.createElement("p");return n.className="sv-loading-text",n.textContent=this.message,e.appendChild(t),e.appendChild(n),e}destroy(){}}class W{constructor(e){this.inputElement=null,this.labelElement=null,this.submitButton=null,this.errorContainer=null,this.focusTimeoutId=null,this.detectedType="email",this.props=e,this.boundHandleInput=()=>this.handleInput(),this.boundHandleKeyDown=e=>{"Enter"===e.key&&(e.preventDefault(),this.handleSubmit())},this.boundHandleSubmit=()=>this.handleSubmit()}get allowsBoth(){return this.props.allowedTypes.includes("email")&&this.props.allowedTypes.includes("phone")}get allowsEmail(){return this.props.allowedTypes.includes("email")}get allowsPhone(){return this.props.allowedTypes.includes("phone")}render(){const e=R("sv-email-view"),t=R("sv-email-header"),n=document.createElement("p");n.className="sv-email-subtitle",n.textContent=this.getSubtitleText(),t.appendChild(n),e.appendChild(t),this.errorContainer=R("sv-email-error-container"),this.props.error&&this.errorContainer.appendChild(U(this.props.error)),e.appendChild(this.errorContainer);const s=R("sv-email-form"),i=R("sv-email-input-wrapper");return this.labelElement=document.createElement("label"),this.labelElement.className="sv-email-label",this.labelElement.htmlFor="sv-identity-input",this.labelElement.textContent=this.getLabelText(),this.inputElement=document.createElement("input"),this.inputElement.type=this.allowsPhone&&!this.allowsEmail?"tel":"text",this.inputElement.id="sv-identity-input",this.inputElement.className="sv-email-input",this.inputElement.placeholder=this.getPlaceholderText(),this.inputElement.autocomplete=this.allowsBoth?"on":this.allowsEmail?"email":"tel",this.inputElement.required=!0,this.inputElement.maxLength=254,this.props.initialValue&&(this.inputElement.value=this.props.initialValue,this.detectAndUpdateType(this.props.initialValue)),this.inputElement.addEventListener("input",this.boundHandleInput),this.inputElement.addEventListener("keydown",this.boundHandleKeyDown),i.appendChild(this.labelElement),i.appendChild(this.inputElement),s.appendChild(i),this.submitButton=document.createElement("button"),this.submitButton.className="sv-btn sv-btn-email-primary",this.submitButton.textContent="Continue",this.submitButton.addEventListener("click",this.boundHandleSubmit),s.appendChild(this.submitButton),e.appendChild(s),this.focusTimeoutId=setTimeout(()=>this.inputElement?.focus(),50),e}getSubtitleText(){return this.allowsBoth?"Enter your email or phone to continue":this.allowsPhone?"Enter your phone number to continue":"Enter your email to continue"}getLabelText(){return this.allowsBoth?"phone"===this.detectedType?"Phone number":"Email address":this.allowsPhone?"Phone number":"Email address"}getPlaceholderText(){return this.allowsBoth?"you@example.com or (555) 123-4567":this.allowsPhone?"(555) 123-4567":"you@example.com"}handleInput(){if(this.clearError(),!this.inputElement)return;const e=this.inputElement.value;if(this.allowsBoth){const t="phone"===this.detectedType;if(this.detectAndUpdateType(e),"phone"===this.detectedType){const t=this.inputElement.selectionStart??e.length,n=q(e);if(n!==e){this.inputElement.value=n;const s=Math.min(t+(n.length-e.length),n.length);this.inputElement.setSelectionRange(s,s)}}t!==("phone"===this.detectedType)&&this.labelElement&&(this.labelElement.textContent=this.getLabelText())}else if(this.allowsPhone){const t=this.inputElement.selectionStart??e.length,n=q(e);if(n!==e){this.inputElement.value=n;const s=Math.min(t+(n.length-e.length),n.length);this.inputElement.setSelectionRange(s,s)}}}detectAndUpdateType(e){!function(e){const t=e.trim();return!!t&&/^[+(\d]/.test(t)&&!/[@.]/.test(t)}(e)?this.detectedType="email":this.detectedType="phone"}clearError(){this.errorContainer&&O(this.errorContainer),this.inputElement?.classList.remove("sv-email-input-error")}showError(e){this.errorContainer&&(O(this.errorContainer),this.errorContainer.appendChild(U(e))),this.inputElement?.classList.add("sv-email-input-error"),this.inputElement?.focus()}handleSubmit(){if(!this.inputElement||!this.submitButton)return;const e=this.inputElement.value;if(this.allowsBoth)if("phone"===this.detectedType){const t=j(e);if(!t)return void this.showError("Please enter a valid phone number");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"phone"})}else{const t=V(e);if(!t)return void this.showError("Please enter a valid email address");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"email"})}else if(this.allowsPhone){const t=j(e);if(!t)return void this.showError("Please enter a valid phone number");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"phone"})}else{const t=V(e);if(!t)return void this.showError("Please enter a valid email address");this.submitButton.disabled=!0,this.submitButton.textContent="Please wait...",this.props.onSubmit({value:t,type:"email"})}}destroy(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),this.inputElement&&(this.inputElement.removeEventListener("input",this.boundHandleInput),this.inputElement.removeEventListener("keydown",this.boundHandleKeyDown)),this.submitButton&&this.submitButton.removeEventListener("click",this.boundHandleSubmit)}}class G{constructor(e){this.backLink=null,this.methodButtons=[],this.methodClickHandlers=new Map,this.props=e,this.boundHandleBack=()=>this.props.onBack()}render(){const e=R();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Choose how to sign in";const n=document.createElement("p");n.className="sv-subtitle",n.textContent=z(this.props.email);const s=R();for(const e of this.props.methods){const t=this.createMethodButton(e);this.methodButtons.push(t),s.appendChild(t)}return e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(s),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(H()),e.appendChild(document.createTextNode(" Change email")),e.addEventListener("click",this.boundHandleBack),e}createMethodButton(e){const t=document.createElement("button");t.className="sv-btn sv-btn-method";const n=R("sv-method-content"),s=this.getMethodIcon(e);n.appendChild(s);const i=R("sv-method-text"),r=document.createElement("div");r.className="sv-method-name",r.textContent=e.name;const o=document.createElement("div");o.className="sv-method-description",o.textContent=e.description,i.appendChild(r),i.appendChild(o),n.appendChild(i),t.appendChild(n);const a=()=>this.props.onSelectMethod(e);return this.methodClickHandlers.set(t,a),t.addEventListener("click",a),t}getMethodIcon(e){const t=R("sv-method-icon");return t.appendChild(N(e.icon)),t}destroy(){this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack);for(const e of this.methodButtons){const t=this.methodClickHandlers.get(e);t&&e.removeEventListener("click",t)}this.methodClickHandlers.clear(),this.methodButtons=[]}}class Y{constructor(e){this.inputElements=[],this.submitButton=null,this.resendButton=null,this.backLink=null,this.errorContainer=null,this.resendTimer=null,this.backoffTimer=null,this.backoffSeconds=0,this.focusTimeoutId=null,this.autoSubmitTimeoutId=null,this.isSubmitting=!1,this.inputHandlers=new Map,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleResend=()=>this.handleResend(),this.boundHandleSubmit=()=>this.handleSubmit()}render(){const e=R();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Enter verification code";const n="email"===this.props.method?"email":"phone",s=document.createElement("p");s.className="sv-subtitle",s.innerHTML=`We sent a 6-digit code to your ${n}<br><strong>${z(this.props.email)}</strong>`,this.errorContainer=R(),this.props.error&&this.errorContainer.appendChild(U(this.props.error));const i=this.createInputGroup();if(this.submitButton=document.createElement("button"),this.submitButton.className="sv-btn sv-btn-primary",this.submitButton.textContent="Verify",this.submitButton.addEventListener("click",this.boundHandleSubmit),this.props.backoffExpires){Math.max(0,Math.ceil(this.props.backoffExpires-Date.now()/1e3))>0&&this.startBackoff(this.props.backoffExpires)}const r=R("sv-resend-container");return this.resendButton=document.createElement("button"),this.resendButton.className="sv-back-link",this.resendButton.textContent="Resend code",this.resendButton.addEventListener("click",this.boundHandleResend),r.appendChild(this.resendButton),e.style.display="flex",e.style.flexDirection="column",e.appendChild(t),e.appendChild(s),e.appendChild(this.errorContainer),e.appendChild(i),e.appendChild(this.submitButton),e.appendChild(r),e.appendChild(this.backLink),this.focusTimeoutId=setTimeout(()=>this.inputElements[0]?.focus(),50),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.style.order="-1",e.appendChild(H()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}createInputGroup(){const e=R("sv-totp-input-group");for(let t=0;t<6;t++){const n=document.createElement("input");n.type="text",n.inputMode="numeric",n.pattern="[0-9]*",n.maxLength=1,n.className="sv-totp-digit",n.autocomplete="one-time-code",n.setAttribute("aria-label",`Digit ${t+1} of 6`);const s={input:e=>this.handleInput(e,t),keydown:e=>this.handleKeyDown(e,t),paste:e=>this.handlePaste(e),focus:()=>n.select()};this.inputHandlers.set(n,s),n.addEventListener("input",s.input),n.addEventListener("keydown",s.keydown),n.addEventListener("paste",s.paste),n.addEventListener("focus",s.focus),this.inputElements.push(n),e.appendChild(n)}return e}handleInput(e,t){const n=e.target,s=n.value.replace(/\D/g,"");s.length>0?(n.value=s[0],this.clearError(),t<5?this.inputElements[t+1].focus():this.checkAutoSubmit()):n.value=""}handleKeyDown(e,t){const n=e.target;"Backspace"===e.key?""===n.value&&t>0&&(this.inputElements[t-1].focus(),this.inputElements[t-1].value=""):"ArrowLeft"===e.key&&t>0?this.inputElements[t-1].focus():"ArrowRight"===e.key&&t<5?this.inputElements[t+1].focus():"Enter"===e.key&&this.handleSubmit()}handlePaste(e){e.preventDefault();const t=(e.clipboardData?.getData("text")??"").replace(/\D/g,"").slice(0,6);for(let e=0;e<t.length;e++)this.inputElements[e]&&(this.inputElements[e].value=t[e]);if(t.length>0){this.clearError();const e=Math.min(t.length,5);this.inputElements[e].focus()}6===t.length&&this.checkAutoSubmit()}checkAutoSubmit(){6===this.getCode().length&&(this.autoSubmitTimeoutId=setTimeout(()=>this.handleSubmit(),100))}getCode(){return this.inputElements.map(e=>e.value).join("")}clearError(){this.errorContainer&&O(this.errorContainer),this.inputElements.forEach(e=>e.classList.remove("sv-input-error"))}showError(e){this.errorContainer&&(O(this.errorContainer),this.errorContainer.appendChild(U(e))),this.inputElements.forEach(e=>e.classList.add("sv-input-error")),this.inputElements[0]?.focus()}handleSubmit(){if(!this.submitButton)return;if(this.isSubmitting)return;if(this.backoffSeconds>0)return;const e=function(e){const t=e.replace(/\D/g,"");return 6===t.length?t:null}(this.getCode());e?(null!==this.autoSubmitTimeoutId&&(clearTimeout(this.autoSubmitTimeoutId),this.autoSubmitTimeoutId=null),this.isSubmitting=!0,this.submitButton.disabled=!0,this.submitButton.textContent="Verifying...",this.props.onSubmit(e)):this.showError("Please enter the complete 6-digit code")}startBackoff(e){this.disableInputs(!0),this.backoffTimer=new v({expiresAt:e,onTick:e=>{this.backoffSeconds=e,this.updateSubmitButton()},onExpired:()=>{this.backoffSeconds=0,this.updateSubmitButton(),this.disableInputs(!1),this.inputElements[0]?.focus()}}),this.backoffTimer.start()}updateSubmitButton(){this.submitButton&&(this.backoffSeconds>0?(this.submitButton.textContent=`Wait ${this.backoffSeconds}s`,this.submitButton.disabled=!0):(this.submitButton.textContent="Verify",this.submitButton.disabled=!1))}disableInputs(e){this.inputElements.forEach(t=>{t.disabled=e})}handleResend(){!this.resendTimer?.isRunning()&&this.resendButton&&(this.resendTimer=new m({duration:30,onTick:e=>{this.resendButton&&(this.resendButton.textContent=`Resend code (${e}s)`,this.resendButton.disabled=!0)},onComplete:()=>{this.resendButton&&(this.resendButton.textContent="Resend code",this.resendButton.disabled=!1)}}),this.resendTimer.start(),this.props.onResend())}destroy(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),null!==this.autoSubmitTimeoutId&&(clearTimeout(this.autoSubmitTimeoutId),this.autoSubmitTimeoutId=null),this.resendTimer?.stop(),this.resendTimer=null,this.backoffTimer?.stop(),this.backoffTimer=null;for(const e of this.inputElements){const t=this.inputHandlers.get(e);t&&(e.removeEventListener("input",t.input),e.removeEventListener("keydown",t.keydown),e.removeEventListener("paste",t.paste),e.removeEventListener("focus",t.focus))}this.inputHandlers.clear(),this.inputElements=[],this.submitButton&&this.submitButton.removeEventListener("click",this.boundHandleSubmit),this.resendButton&&this.resendButton.removeEventListener("click",this.boundHandleResend),this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack)}}class J{constructor(e){this.actionButton=null,this.errorContainer=null,this.backLink=null,this.fallbackLink=null,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleStart=()=>this.handleStart(),this.boundHandleFallback=e.onFallback?()=>e.onFallback():null}render(){const e=R();this.backLink=this.createBackLink();const t=R();t.appendChild(P());const n=document.createElement("h3");n.className="sv-title",n.textContent="register"===this.props.mode?"Set up a passkey":"Use your passkey";const s=document.createElement("p");s.className="sv-subtitle","register"===this.props.mode?s.innerHTML=`Create a passkey for<br><strong>${z(this.props.email)}</strong><br>to sign in faster next time`:s.innerHTML=`Use your passkey to verify<br><strong>${z(this.props.email)}</strong>`,this.errorContainer=R(),this.props.error&&this.errorContainer.appendChild(U(this.props.error));const i=document.createElement("p");i.className="sv-passkey-description",i.textContent="register"===this.props.mode?"Use Face ID, Touch ID, Windows Hello, or a security key.":"Your device will prompt you to verify your identity.";const r="register"===this.props.mode?"Create Passkey":"Continue with Passkey";return this.actionButton=document.createElement("button"),this.actionButton.className="sv-btn sv-btn-primary",this.actionButton.textContent=r,this.actionButton.addEventListener("click",this.boundHandleStart),e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(s),e.appendChild(this.errorContainer),e.appendChild(i),e.appendChild(this.actionButton),this.props.onFallback&&this.boundHandleFallback&&(this.fallbackLink=this.createFallbackLink(),e.appendChild(this.fallbackLink)),e}createFallbackLink(){const e=document.createElement("button");return e.className="sv-fallback-link",e.textContent="Having trouble? Use email code instead",this.boundHandleFallback&&e.addEventListener("click",this.boundHandleFallback),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(H()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}handleStart(){this.actionButton&&(this.actionButton.disabled=!0,this.actionButton.textContent="Waiting for device...",this.props.onStart())}showError(e){this.errorContainer&&(O(this.errorContainer),this.errorContainer.appendChild(U(e))),this.actionButton&&(this.actionButton.disabled=!1,this.actionButton.textContent="Try Again")}destroy(){this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack),this.actionButton&&this.actionButton.removeEventListener("click",this.boundHandleStart),this.fallbackLink&&this.boundHandleFallback&&this.fallbackLink.removeEventListener("click",this.boundHandleFallback)}}class Q{constructor(e){this.addButton=null,this.skipLink=null,this.props=e,this.boundHandleAdd=()=>this.props.onAddPasskey(),this.boundHandleSkip=()=>this.props.onSkip()}render(){const e=R(),t=R();t.appendChild(P());const n=document.createElement("h3");n.className="sv-title",n.textContent="Add a passkey for faster sign-in?";const s=document.createElement("p");s.className="sv-subtitle",s.innerHTML=`Next time, sign in instantly as<br><strong>${z(this.props.email)}</strong>`;const i=R();this.props.error&&i.appendChild(U(this.props.error));const r=document.createElement("div");r.className="sv-passkey-prompt-benefits";const o=document.createElement("ul"),a=["No codes to type or wait for","Phishing-resistant security","Works with Face ID, Touch ID, or Windows Hello"];for(const e of a){const t=document.createElement("li");t.appendChild(I()),t.appendChild(document.createTextNode(e)),o.appendChild(t)}return r.appendChild(o),this.addButton=document.createElement("button"),this.addButton.className="sv-btn sv-btn-primary",this.addButton.textContent=this.props.error?"Try Again":"Add Passkey",this.addButton.addEventListener("click",this.boundHandleAdd),this.skipLink=document.createElement("button"),this.skipLink.className="sv-skip-link",this.skipLink.textContent=this.props.error?"Skip for now":"Not now",this.skipLink.addEventListener("click",this.boundHandleSkip),e.appendChild(t),e.appendChild(n),e.appendChild(s),e.appendChild(i),e.appendChild(r),e.appendChild(this.addButton),e.appendChild(this.skipLink),e}destroy(){this.addButton&&this.addButton.removeEventListener("click",this.boundHandleAdd),this.skipLink&&this.skipLink.removeEventListener("click",this.boundHandleSkip)}}class Z{constructor(e){this.expirationTimer=null,this.resendTimer=null,this.countdownElement=null,this.countdownSection=null,this.waitingSection=null,this.resendButton=null,this.backLink=null,this.fallbackButton=null,this.props=e,this.boundHandleBack=()=>this.props.onBack(),this.boundHandleResend=()=>this.handleResend(),this.boundHandleFallback=()=>this.props.onFallback()}render(){const e=R();this.backLink=this.createBackLink();const t=document.createElement("h3");t.className="sv-title",t.textContent="Check your email";const n=document.createElement("p");n.className="sv-subtitle",n.innerHTML=`We sent a secure link to<br><strong>${z(this.props.email)}</strong>`,this.waitingSection=R("sv-sparklink-waiting");const s=document.createElement("div");s.className="sv-spinner sv-spinner-small",s.setAttribute("role","status"),s.setAttribute("aria-label","Waiting for verification");const i=document.createElement("span");i.className="sv-sparklink-waiting-text",i.textContent="Waiting for you to click the link...",this.waitingSection.appendChild(s),this.waitingSection.appendChild(i),this.countdownSection=R("sv-sparklink-countdown");const r=document.createElement("span");r.textContent="Link expires in ",this.countdownElement=document.createElement("span"),this.countdownElement.className="sv-sparklink-countdown-time",this.startExpirationTimer(),this.countdownSection.appendChild(r),this.countdownSection.appendChild(this.countdownElement);const o=R("sv-resend-container");this.resendButton=document.createElement("button"),this.resendButton.className="sv-btn sv-btn-secondary",this.resendButton.textContent="Resend link",this.resendButton.addEventListener("click",this.boundHandleResend),o.appendChild(this.resendButton);const a=R("sv-sparklink-fallback");return this.fallbackButton=document.createElement("button"),this.fallbackButton.className="sv-back-link",this.fallbackButton.textContent="Use verification code instead",this.fallbackButton.addEventListener("click",this.boundHandleFallback),a.appendChild(this.fallbackButton),e.appendChild(this.backLink),e.appendChild(t),e.appendChild(n),e.appendChild(this.waitingSection),e.appendChild(this.countdownSection),e.appendChild(o),e.appendChild(a),e}createBackLink(){const e=document.createElement("button");return e.className="sv-back-link",e.appendChild(H()),e.appendChild(document.createTextNode(" Choose another method")),e.addEventListener("click",this.boundHandleBack),e}formatTime(e){if(!Number.isFinite(e)||e<0)return"--:--";return`${Math.floor(e/60)}:${Math.floor(e%60).toString().padStart(2,"0")}`}startExpirationTimer(){if(!Number.isFinite(this.props.expiresAt)||this.props.expiresAt<=0)return this.countdownElement&&(this.countdownElement.textContent="--:--"),void console.warn("[SparkVault] Invalid expiresAt timestamp:",this.props.expiresAt);const e=Math.floor(this.props.expiresAt/1e3);this.expirationTimer=new v({expiresAt:e,onTick:e=>{this.countdownElement&&(this.countdownElement.textContent=this.formatTime(e))},onExpired:()=>{this.showExpiredState()}}),this.expirationTimer.start()}showExpiredState(){if(this.props.onExpired(),this.waitingSection){this.waitingSection.innerHTML="",this.waitingSection.classList.add("sv-sparklink-expired");const e=R("sv-sparklink-expired-icon");e.appendChild(function(){const e=T("0 0 48 48",48,48);e.classList.add("sv-expired-icon"),e.appendChild(M(24,24,22,{fill:"#F5F5F5",stroke:"#E5E5E5","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.setAttribute("transform","translate(10, 12)"),t.appendChild(L("M14 4L2 24h24L14 4z",{fill:"#737373"})),t.appendChild(L("M14 10v5",{stroke:"#FFFFFF","stroke-width":"2","stroke-linecap":"round"})),t.appendChild(M(14,19,1,{fill:"#FFFFFF"})),e.appendChild(t),e}()),this.waitingSection.appendChild(e);const t=document.createElement("span");t.className="sv-sparklink-expired-text",t.textContent="This link has expired",this.waitingSection.appendChild(t)}this.countdownSection&&(this.countdownSection.style.display="none")}handleResend(){!this.resendTimer?.isRunning()&&this.resendButton&&(this.resendTimer=new m({duration:30,onTick:e=>{this.resendButton&&(this.resendButton.textContent=`Resend link (${e}s)`,this.resendButton.disabled=!0)},onComplete:()=>{this.resendButton&&(this.resendButton.textContent="Resend link",this.resendButton.disabled=!1)}}),this.resendTimer.start(),this.props.onResend())}destroy(){this.expirationTimer?.stop(),this.expirationTimer=null,this.resendTimer?.stop(),this.resendTimer=null,this.backLink&&this.backLink.removeEventListener("click",this.boundHandleBack),this.resendButton&&this.resendButton.removeEventListener("click",this.boundHandleResend),this.fallbackButton&&this.fallbackButton.removeEventListener("click",this.boundHandleFallback)}}class X{constructor(e){this.retryButton=null,this.closeButton=null,this.props=e,this.boundHandleRetry=()=>this.props.onRetry(),this.boundHandleClose=()=>this.props.onClose()}render(){const e=R();e.className="sv-error-view";const t=R();t.className="sv-error-icon-container",t.appendChild(function(){const e=T("0 0 48 48",48,48);e.classList.add("sv-error-icon"),e.appendChild(M(24,24,22,{fill:"#FEF2F2",stroke:"#FECACA","stroke-width":"1"}));const t=document.createElementNS("http://www.w3.org/2000/svg","g");return t.setAttribute("transform","translate(10, 12)"),t.appendChild(L("M14 4L2 24h24L14 4z",{fill:"#DC2626"})),t.appendChild(L("M14 10v5",{stroke:"#FFFFFF","stroke-width":"2","stroke-linecap":"round"})),t.appendChild(M(14,19,1,{fill:"#FFFFFF"})),e.appendChild(t),e}());const n=R();n.className="sv-error-content";const s=document.createElement("h3");s.className="sv-error-title",s.textContent="Something went wrong";const i=document.createElement("p");i.className="sv-error-message",i.textContent=this.props.message;const r=document.createElement("div");r.className="sv-error-code-badge";const o=document.createElement("span");o.className="sv-error-code-label",o.textContent="Error code";const a=document.createElement("code");a.className="sv-error-code-value",a.textContent=this.props.code,r.appendChild(o),r.appendChild(a),n.appendChild(s),n.appendChild(i),n.appendChild(r);const l=R();return l.className="sv-error-actions",this.retryButton=document.createElement("button"),this.retryButton.className="sv-btn sv-btn-error-primary",this.retryButton.textContent="Try Again",this.retryButton.addEventListener("click",this.boundHandleRetry),this.closeButton=document.createElement("button"),this.closeButton.className="sv-btn sv-btn-error-secondary",this.closeButton.textContent="Close",this.closeButton.addEventListener("click",this.boundHandleClose),l.appendChild(this.retryButton),l.appendChild(this.closeButton),e.appendChild(t),e.appendChild(n),e.appendChild(l),e}destroy(){this.retryButton&&this.retryButton.removeEventListener("click",this.boundHandleRetry),this.closeButton&&this.closeButton.removeEventListener("click",this.boundHandleClose)}}class ee{constructor(e,t,n,s){this.currentView=null,this.focusTimeoutId=null,this.pollingInterval=null,this.messageListener=null,this.container=e,this.api=t,this.options=n,this.callbacks=s,this.verificationState=new x,this.passkeyHandler=new w(t,this.verificationState),this.totpHandler=new C(t,this.verificationState),this.sparkLinkHandler=new E(t,this.verificationState),n.email?this.verificationState.setIdentity(n.email,"email"):n.phone&&this.verificationState.setIdentity(n.phone,"phone"),n.authContext&&this.verificationState.setAuthContext(n.authContext)}get recipient(){return this.verificationState.recipient}get identityType(){return this.verificationState.identityType}get sdkConfig(){return this.verificationState.sdkConfig}async start(){let e=null;if(this.api.isConfigPreloaded()){const t=new Promise(e=>setTimeout(()=>e(null),50)),n=await Promise.race([this.api.getConfig().then(e=>e),t]);null!==n&&(e=n)}this.container.createLoading({backdropBlur:this.options.backdropBlur},()=>this.handleClose());try{e||(this.setState({view:"loading"}),e=await this.api.getConfig()),this.verificationState.setConfig(e),e.branding&&this.container.updateBranding(e.branding);const t=void 0!==this.options.backdropBlur?this.options.backdropBlur:void 0===e.branding?.backdrop_blur||e.branding.backdrop_blur;this.container.updateBackdropBlur(t),this.recipient?this.showMethodSelect():this.showIdentityInput()}catch(e){this.handleErrorWithRecovery(e,"config_error")}}close(){null!==this.focusTimeoutId&&(clearTimeout(this.focusTimeoutId),this.focusTimeoutId=null),this.stopSparkLinkPolling(),this.destroyCurrentView(),this.container.destroy()}handleClose(){this.close(),this.callbacks.onCancel()}get viewState(){return this.verificationState.viewState}setState(e){this.verificationState.setViewState(e),this.render()}render(){const e=this.container.getBody();if(!e)return;this.destroyCurrentView();const t=this.createViewForState(this.viewState);this.currentView=t,O(e),e.appendChild(t.render());const n=e.querySelector("input:not([disabled]), button.sv-btn-primary:not([disabled]), button.sv-btn-email-primary:not([disabled]), button.sv-btn-method:not([disabled])");n&&(null!==this.focusTimeoutId&&clearTimeout(this.focusTimeoutId),this.focusTimeoutId=setTimeout(()=>n.focus(),50))}destroyCurrentView(){this.currentView?.destroy&&this.currentView.destroy(),this.currentView=null}createViewForState(e){switch(e.view){case"loading":return new K({message:"Loading..."});case"identity-input":return new W({allowedTypes:this.getAllowedIdentityTypes(),initialValue:this.recipient,error:e.error,onSubmit:e=>this.handleIdentitySubmit(e)});case"method-select":return new G({email:e.email,methods:e.methods,onSelectMethod:e=>this.handleMethodSelect(e),onBack:()=>this.showIdentityInput()});case"totp-verify":return new Y({email:e.email,method:e.method,error:e.error,backoffExpires:e.backoffExpires,onSubmit:e=>this.handleTotpSubmit(e),onResend:()=>this.handleTotpResend(),onBack:()=>this.showMethodSelect()});case"passkey":{const{passkey:t}=this.verificationState,n="register"===e.mode&&null!==t.pendingResult;return new J({email:e.email,mode:e.mode,error:e.error,onStart:()=>this.handlePasskeyStart(),onBack:n?()=>this.handlePasskeyRegistrationSkip():"verify"===e.mode?()=>this.handlePasskeyFallback():()=>this.showMethodSelect(),onFallback:t.hasPasskey&&!t.isFallbackMode?()=>this.handlePasskeyFallback():void 0})}case"passkey-prompt":return new Q({email:e.email,onAddPasskey:()=>this.handlePasskeyPromptAdd(e.pendingResult),onSkip:()=>this.handlePasskeyPromptSkip(e.pendingResult),error:e.error});case"sparklink-waiting":return new Z({email:e.email,expiresAt:e.expiresAt,onResend:()=>this.handleSparkLinkResend(),onFallback:()=>this.handleSparkLinkFallback(),onBack:()=>this.showMethodSelect(),onExpired:()=>this.stopSparkLinkPolling()});case"oauth-pending":return new K({message:`Connecting to ${e.provider}...`});case"error":return new X({message:e.message,code:e.code,onRetry:()=>this.showIdentityInput(),onClose:()=>this.handleClose()})}}showIdentityInput(e){this.setState({view:"identity-input",error:e})}async showMethodSelect(){if(!this.sdkConfig)return;const e=this.sdkConfig.methods??[];if(!Array.isArray(e))return void this.setState({view:"error",message:"Invalid configuration",code:"invalid_config"});let t=y(e);if(t=t.filter(e=>"phone"===this.identityType?"totp"===e.type&&"totp_sms"===e.id:"email"===e.identityType||void 0===e.identityType),0===t.length)return void this.setState({view:"error",message:"No authentication methods available",code:"no_methods"});const n=t.some(e=>"passkey"===e.type),{passkey:s}=this.verificationState;if(n&&"email"===this.identityType&&!s.isFallbackMode){this.setState({view:"loading"});const e=await this.passkeyHandler.checkPasskey();if(null!==e&&!e.emailValid)return void this.showIdentityInput("This email domain cannot receive messages. Please check your email address.");if(!0===e?.hasPasskey)return void this.setState({view:"passkey",email:this.recipient,mode:"verify"});t=t.filter(e=>"passkey"!==e.type)}0!==t.length?1!==t.length?this.setState({view:"method-select",email:this.recipient,methods:t}):this.handleMethodSelect(t[0]):this.setState({view:"error",message:"No authentication methods available",code:"no_methods"})}handleIdentitySubmit(e){this.verificationState.setIdentity(e.value,e.type),this.showMethodSelect()}getAllowedIdentityTypes(){return this.verificationState.getAllowedIdentityTypes()}async handleMethodSelect(e){try{switch(e.type){case"totp":{const t="totp_sms"===e.id?"sms":"email";this.setState({view:"loading"});const n=await this.totpHandler.send(t);if(!n.success)return void this.setState({view:"error",message:n.error??"Failed to send code",code:"totp_send_failed"});this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling});break}case"passkey":this.setState({view:"passkey",email:this.recipient,mode:"verify"});break;case"sparklink":{this.setState({view:"loading"});const e=await this.sparkLinkHandler.send();if(!e.success)return void this.setState({view:"error",message:e.error??"Failed to send SparkLink",code:"sparklink_send_failed"});this.setState({view:"sparklink-waiting",email:this.recipient,sparkId:e.sparkId,expiresAt:e.expiresAt}),this.startSparkLinkPolling(e.sparkId);break}case"social":e.provider&&this.handleSocialLogin(e.provider);break;default:this.setState({view:"error",message:`Authentication method not supported: ${e.type}`,code:"unsupported_method"})}}catch(e){this.handleErrorWithRecovery(e,"unknown")}}async handleTotpSubmit(e){if("totp-verify"!==this.viewState.view)return;const t=this.verificationState.totp.method??"email",n=await this.totpHandler.verify(e);if(n.success&&n.result){if(n.result.redirect)return this.close(),void(window.location.href=n.result.redirect);if(await this.shouldShowPasskeyPrompt())return void this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:n.result});this.close(),this.callbacks.onSuccess(n.result)}else{if((n.error?.toLowerCase()??"").includes("expired")){const e=await this.totpHandler.resend();return e.success?void this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling,error:"Code expired. We've sent a new one."}):void this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling,error:e.error??"Code expired and failed to resend."})}this.setState({view:"totp-verify",email:this.recipient,method:t,kindling:this.verificationState.totp.kindling,error:n.error??"Invalid code. Please try again.",backoffExpires:n.backoffExpires})}}async handleTotpResend(){if("totp-verify"!==this.viewState.view)return;const e=this.verificationState.totp.method??"email",t=await this.totpHandler.resend();t.success||this.setState({view:"totp-verify",email:this.recipient,method:e,kindling:this.verificationState.totp.kindling,error:t.error??"Failed to resend code"})}async handlePasskeyStart(){if("passkey"!==this.viewState.view)return;const e=this.viewState.mode,t="register"===e?await this.passkeyHandler.register():await this.passkeyHandler.verify();if(t.success&&t.result){if(t.result.redirect)return this.close(),void(window.location.href=t.result.redirect);this.close(),this.callbacks.onSuccess(t.result)}else"not_found"===t.errorType?this.setState({view:"passkey",email:this.recipient,mode:"register",error:t.error}):this.setState({view:"passkey",email:this.recipient,mode:e,error:t.error})}async handlePasskeyFallback(){this.verificationState.enablePasskeyFallback(),await this.showMethodSelect()}handlePasskeyRegistrationSkip(){const e=this.verificationState.passkey.pendingResult;if(e){if(this.verificationState.setPendingResult(null),e.redirect)return this.close(),void(window.location.href=e.redirect);this.close(),this.callbacks.onSuccess(e)}}handleSocialLogin(e){this.setState({view:"oauth-pending",provider:e});const t=function(){const e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}(),n=window.location.origin+window.location.pathname;sessionStorage.setItem("sv_oauth_state",t),sessionStorage.setItem("sv_oauth_email",this.recipient);const s=this.api.getSocialAuthUrl(e,n,t);window.location.href=s}normalizeError(e){return e instanceof f?new t(e.message,e.code):e instanceof Error?e:new Error(String(e))}isSessionExpiredError(e){const n=e.message.toLowerCase(),s=e instanceof t?e.code:"";return n.includes("expired")||n.includes("session")||n.includes("invalid token")||n.includes("token invalid")||"token_expired"===s||"session_expired"===s||"kindling_expired"===s}handleErrorWithRecovery(e,n){const s=this.normalizeError(e);this.isSessionExpiredError(s)?this.showIdentityInput("Your session has expired. Please try again."):this.setState({view:"error",message:s.message,code:s instanceof t?s.code:n})}async shouldShowPasskeyPrompt(){if(!this.verificationState.shouldShowPasskeyPrompt())return!1;const{passkey:e}=this.verificationState;if(null===e.hasPasskey){const e=await this.passkeyHandler.checkPasskey();return null!==e&&e.emailValid&&!e.hasPasskey}return!e.hasPasskey}async handlePasskeyPromptAdd(e){this.verificationState.setPendingResult(e),this.setState({view:"loading"});const t=await this.passkeyHandler.register();if(t.success&&t.result){if(t.result.redirect)return this.close(),void(window.location.href=t.result.redirect);this.close(),this.callbacks.onSuccess(t.result)}else if("cancelled"===t.errorType)this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:e});else{const n=t.error||"Failed to create passkey. Please try again.";this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:e,error:n})}}handlePasskeyPromptSkip(e){if(this.verificationState.dismissPasskeyPrompt(),e.redirect)return this.close(),void(window.location.href=e.redirect);this.close(),this.callbacks.onSuccess(e)}startSparkLinkPolling(e){this.stopSparkLinkPolling(),this.messageListener=e=>{if(!e.data||"object"!=typeof e.data)return;if("sparklink_verified"!==e.data.type)return;const{token:t,identity:n,identityType:s,redirect:i}=e.data;t&&n&&this.handleSparkLinkVerified({token:t,identity:n,identityType:s||"email",redirect:i})},window.addEventListener("message",this.messageListener),this.pollingInterval=setInterval(async()=>{const t=await this.sparkLinkHandler.checkStatus(e);t.verified&&t.token&&t.identity&&this.handleSparkLinkVerified({token:t.token,identity:t.identity,identityType:t.identityType||"email",redirect:t.redirect})},2e3)}async handleSparkLinkVerified(e){if(this.stopSparkLinkPolling(),e.redirect)return this.close(),void(window.location.href=e.redirect);await this.shouldShowPasskeyPrompt()?this.setState({view:"passkey-prompt",email:this.recipient,pendingResult:e}):(this.close(),this.callbacks.onSuccess(e))}stopSparkLinkPolling(){this.pollingInterval&&(clearInterval(this.pollingInterval),this.pollingInterval=null),this.messageListener&&(window.removeEventListener("message",this.messageListener),this.messageListener=null)}async handleSparkLinkResend(){const e=await this.sparkLinkHandler.send();e.success&&e.sparkId&&(this.stopSparkLinkPolling(),this.setState({view:"sparklink-waiting",email:this.recipient,sparkId:e.sparkId,expiresAt:e.expiresAt}),this.startSparkLinkPolling(e.sparkId))}async handleSparkLinkFallback(){this.stopSparkLinkPolling(),this.setState({view:"loading"});const e=await this.totpHandler.send("email");e.success?this.setState({view:"totp-verify",email:this.recipient,method:"email",kindling:this.verificationState.totp.kindling}):this.setState({view:"error",message:e.error??"Failed to send code",code:"totp_send_failed"})}}const te={showHeader:!0,showCloseButton:!0,showFooter:!0};class ne{constructor(e,t={}){this.container=null,this.header=null,this.body=null,this.footer=null,this.closeBtn=null,this.onCloseCallback=null,this.closeBtnClickHandler=null,this.effectiveTheme="light",this.targetElement=e,this.containerOptions={...te,...t}}createLoading(e,t){if(this.container)return;this.onCloseCallback=t;if(B({branding:{companyName:"",logoLight:null,logoDark:null},backdropBlur:!1}),this.container=document.createElement("div"),this.container.className="sv-inline-container",this.containerOptions.showHeader&&(this.header=this.createHeader({companyName:"",logoLight:null,logoDark:null}),this.container.appendChild(this.header)),this.body=document.createElement("div"),this.body.className="sv-body sv-inline-body",this.container.appendChild(this.body),this.containerOptions.showFooter){this.footer=document.createElement("div"),this.footer.className="sv-footer";const e=document.createElement("span");e.className="sv-footer-text",e.appendChild(document.createTextNode("Secured by "));const t=document.createElement("a");t.href="https://sparkvault.com",t.target="_blank",t.rel="noopener noreferrer",t.className="sv-footer-link",t.style.color="inherit",t.style.textDecoration="none",t.textContent="SparkVault",e.appendChild(t),this.footer.appendChild(e),this.container.appendChild(this.footer)}this.targetElement.innerHTML="",this.targetElement.appendChild(this.container)}updateBranding(e){if(this.container&&(this.effectiveTheme=$(e),this.containerOptions.showHeader&&this.header)){const t=this.createHeader(e);this.container.replaceChild(t,this.header),this.header=t}}updateBackdropBlur(e){}getBody(){return this.body}isOpen(){return null!==this.container}destroy(){this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.container&&this.container.parentNode&&this.container.remove(),this.container=null,this.header=null,this.body=null,this.footer=null,this.onCloseCallback=null}createHeader(e){const t=document.createElement("div");t.className="sv-header sv-inline-header";const n=document.createElement("div");n.className="sv-header-title";const s="dark"===this.effectiveTheme?e.logoDark||e.logoLight:e.logoLight||e.logoDark;if(s){const t=document.createElement("img");t.className="sv-logo",t.src=s,t.alt=e.companyName,n.appendChild(t);const i=document.createElement("span");i.className="sv-sr-only",i.textContent=e.companyName,n.appendChild(i)}else if(e.companyName){const t=document.createElement("h2");t.className="sv-company-name",t.textContent=e.companyName,n.appendChild(t)}return t.appendChild(n),this.containerOptions.showCloseButton&&(this.closeBtn=document.createElement("button"),this.closeBtn.className="sv-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.appendChild(A()),this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(this.closeBtn)),t}handleClose(){this.onCloseCallback&&this.onCloseCallback()}}function se(e){"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}class ie{constructor(e){this.renderer=null,this.attachedElements=new Map,this.config=e,this.api=new b(e),e.preloadConfig&&this.api.preloadConfig()}async verify(e={}){this.renderer&&this.renderer.close();const t=!!e.target?this.createInlineContainer(e.target):new D,n={...e,backdropBlur:e.backdropBlur??this.config.backdropBlur};return new Promise((s,i)=>{this.renderer=new ee(t,this.api,n,{onSuccess:t=>{e.onSuccess?.(t),s(t)},onError:t=>{e.onError?.(t),i(t)},onCancel:()=>{const t=new a;e.onCancel?.(),i(t)}}),this.renderer.start().catch(t=>{e.onError?.(t),i(t)})})}attach(e,t={}){let n=null;const s=async e=>{e.preventDefault();try{await this.verify({email:t.email,phone:t.phone,authContext:t.authContext,onSuccess:t.onSuccess,onError:t.onError,onCancel:t.onCancel})}catch{}};return se(()=>{document.querySelectorAll(e).forEach(e=>{e.addEventListener("click",s),this.attachedElements.set(e,()=>{e.removeEventListener("click",s)})}),n=new MutationObserver(t=>{t.forEach(t=>{t.addedNodes.forEach(t=>{t instanceof Element&&(t.matches(e)&&(t.addEventListener("click",s),this.attachedElements.set(t,()=>{t.removeEventListener("click",s)})),t.querySelectorAll(e).forEach(e=>{this.attachedElements.has(e)||(e.addEventListener("click",s),this.attachedElements.set(e,()=>{e.removeEventListener("click",s)}))}))})})}),n.observe(document.body,{childList:!0,subtree:!0})}),()=>{n?.disconnect(),this.attachedElements.forEach(e=>e()),this.attachedElements.clear()}}async verifyToken(e){if(!e||"string"!=typeof e)throw new i("Token is required");const t=e.split(".");if(3!==t.length)throw new i("Invalid token format");const[,n]=t,s=JSON.parse(function(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),n=t+"=".repeat((4-t.length%4)%4);return atob(n)}(n));if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.iss&&"string"==typeof t.sub&&"string"==typeof t.aud&&"number"==typeof t.exp&&"number"==typeof t.iat&&"string"==typeof t.identity&&"string"==typeof t.identity_type&&"number"==typeof t.verified_at&&"string"==typeof t.method}(s))throw new i("Invalid token payload structure");const r=Math.floor(Date.now()/1e3);if(s.exp<r)throw new i("Token has expired");const o=`${this.config.apiBaseUrl}/apps/identity/${this.config.accountId}`;if(s.iss!==o)throw new i("Invalid token issuer");return s}close(){this.renderer&&(this.renderer.close(),this.renderer=null)}createInlineContainer(e){let t;if("string"==typeof e){const n=document.querySelector(e);if(!(n&&n instanceof HTMLElement))throw new i(`Target selector "${e}" did not match any element`);t=n}else{if(!(e instanceof HTMLElement))throw new i("Target must be a CSS selector string or HTMLElement");t=e}return new ne(t)}async pop(e={}){return this.verify(e)}async render(e){return this.verify(e)}}class re extends t{constructor(e,t,n){super(e,t,n),this.httpStatus=n,this.name="UploadApiError"}}class oe{constructor(e){this.config=e,this.timeoutMs=e.timeout??3e4}async getVaultUploadInfo(e){const t=`${this.config.apiBaseUrl}/v1/files/in/${e}`,n=await this.request(t,{method:"GET"});if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.vault_id&&"string"==typeof t.vault_name&&"number"==typeof t.max_size_bytes&&"object"==typeof t.branding&&null!==t.branding&&"string"==typeof t.branding.organization_name&&"object"==typeof t.encryption&&null!==t.encryption&&"string"==typeof t.encryption.algorithm&&("active"===t.forge_status||"inactive"===t.forge_status)}(n.data))throw new re("Invalid vault upload info response from server","invalid_response",n.status);const s=n.data;return{vaultId:s.vault_id,vaultName:s.vault_name,maxSizeBytes:s.max_size_bytes,branding:{organizationName:s.branding.organization_name,logoLightUrl:s.branding.logo_light_url,logoDarkUrl:s.branding.logo_dark_url},encryption:{algorithm:s.encryption.algorithm,keyDerivation:s.encryption.key_derivation,postQuantum:s.encryption.post_quantum},forgeStatus:s.forge_status}}async initiateUpload(e,t,n,s){const i=`${this.config.apiBaseUrl}/v1/files/in/${e}/upload`,r=await this.request(i,{method:"POST",body:JSON.stringify({filename:t,size_bytes:n,content_type:s})});if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.forge_url&&"string"==typeof t.ingot_id}(r.data))throw new re("Invalid initiate upload response from server","invalid_response",r.status);return{forgeUrl:r.data.forge_url,ingotId:r.data.ingot_id}}async request(e,n){const s=new AbortController,i=setTimeout(()=>s.abort(),this.timeoutMs);try{const t=await fetch(e,{method:n.method,headers:{"Content-Type":"application/json",Accept:"application/json"},body:n.body,signal:s.signal}),i=await t.json();if(!t.ok){const e="object"==typeof i&&null!==i?i:{},n="object"==typeof e.error&&null!==e.error?e.error:e,s=("string"==typeof n.message?n.message:null)??("string"==typeof n.error?n.error:null)??"Request failed",r="string"==typeof n.code?n.code:"api_error";throw new re(s,r,t.status)}return{data:"object"==typeof i&&null!==i&&"data"in i?i.data:i,status:t.status}}catch(s){if(s instanceof t)throw s;if(s instanceof DOMException&&"AbortError"===s.name)throw new o(`Request timed out after ${this.timeoutMs}ms`);if(s instanceof TypeError)throw new r(`Network request failed: ${s.message}`,{url:e,method:n.method});throw new r(s instanceof Error?`Request failed: ${s.message}`:"Request failed: Unknown error")}finally{clearTimeout(i)}}}const ae="sparkvault-upload-styles";function le(e){if(document.getElementById(ae))return;const t=document.createElement("style");t.id=ae,t.textContent=function(e){const{backdropBlur:t}=e,n=!1!==t,s={primary:"#4F46E5",primaryHover:"#4338CA",primaryLight:"rgba(79, 70, 229, 0.08)",error:"#DC2626",errorLight:"#FEF2F2",errorBorder:"#FECACA",success:"#059669",bg:"#FFFFFF",bgSubtle:"#FAFAFA",bgHover:"#F5F5F5",bgDark:"#0F0F0F",bgDarkSubtle:"#171717",border:"#E5E5E5",borderHover:"#D4D4D4",borderDark:"#262626",textPrimary:"#0A0A0A",textSecondary:"#525252",textMuted:"#737373",textOnPrimary:"#FFFFFF",textOnDark:"#FAFAFA",textMutedOnDark:"#A3A3A3",shadowSm:"0 1px 2px rgba(0, 0, 0, 0.04)",shadowLg:"0 8px 24px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04)"};return`\n /* ========================================\n OVERLAY & MODAL CONTAINER\n ======================================== */\n\n .svu-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n padding: 16px;\n box-sizing: border-box;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n }\n\n .svu-overlay.svu-blur {\n backdrop-filter: blur(${n?"8px":"0"});\n -webkit-backdrop-filter: blur(${n?"8px":"0"});\n }\n\n .svu-modal {\n background: ${s.bg};\n border-radius: 16px;\n box-shadow: ${s.shadowLg};\n width: 100%;\n max-width: 480px;\n max-height: calc(100vh - 32px);\n display: flex;\n flex-direction: column;\n color: ${s.textPrimary};\n overflow: hidden;\n }\n\n .svu-modal.svu-with-sidebar {\n max-width: 900px;\n flex-direction: row;\n }\n\n .svu-modal-main {\n flex: 1;\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n /* Dark card variant for uploading/ceremony states */\n .svu-modal.svu-dark {\n background: ${s.bgDark};\n color: ${s.textOnDark};\n }\n\n /* ========================================\n HEADER\n ======================================== */\n\n .svu-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 20px;\n border-bottom: 1px solid ${s.border};\n background: ${s.bg};\n flex-shrink: 0;\n }\n\n .svu-dark .svu-header {\n border-bottom-color: ${s.borderDark};\n background: ${s.bgDark};\n }\n\n .svu-header-title {\n display: flex;\n align-items: center;\n gap: 12px;\n min-width: 0;\n }\n\n .svu-logo {\n height: 28px;\n width: auto;\n max-width: 140px;\n object-fit: contain;\n flex-shrink: 0;\n }\n\n .svu-company-name {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n margin: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .svu-close-btn {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n color: ${s.textMuted};\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .svu-close-btn:hover {\n background: ${s.bgHover};\n color: ${s.textPrimary};\n }\n\n .svu-dark .svu-close-btn {\n color: ${s.textMutedOnDark};\n }\n\n .svu-dark .svu-close-btn:hover {\n background: ${s.bgDarkSubtle};\n color: ${s.textOnDark};\n }\n\n /* ========================================\n BODY\n ======================================== */\n\n .svu-body {\n padding: 24px 28px;\n overflow-y: auto;\n flex: 1;\n }\n\n /* ========================================\n FOOTER\n ======================================== */\n\n .svu-footer {\n padding: 10px 20px;\n border-top: 1px solid ${s.border};\n text-align: center;\n background: ${s.bgSubtle};\n flex-shrink: 0;\n }\n\n .svu-dark .svu-footer {\n border-top-color: ${s.borderDark};\n background: ${s.bgDarkSubtle};\n }\n\n .svu-footer-text {\n font-size: 10px;\n color: ${s.textMuted};\n letter-spacing: 0.02em;\n }\n\n .svu-dark .svu-footer-text {\n color: ${s.textMutedOnDark};\n }\n\n .svu-footer-link {\n color: ${s.textSecondary};\n text-decoration: none;\n font-weight: 500;\n transition: color 0.15s ease;\n }\n\n .svu-footer-link:hover {\n color: ${s.primary};\n }\n\n /* ========================================\n LOADING STATE\n ======================================== */\n\n .svu-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 48px 24px;\n gap: 16px;\n }\n\n .svu-spinner {\n width: 28px;\n height: 28px;\n border: 2.5px solid ${s.border};\n border-top-color: ${s.primary};\n border-radius: 50%;\n animation: svu-spin 0.7s linear infinite;\n }\n\n .svu-loading-text {\n font-size: 14px;\n color: ${s.textSecondary};\n margin: 0;\n }\n\n @keyframes svu-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ========================================\n FORM VIEW\n ======================================== */\n\n .svu-form-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .svu-title {\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.02em;\n line-height: 1.3;\n margin: 0 0 6px 0;\n text-align: center;\n color: ${s.textPrimary};\n }\n\n .svu-dark .svu-title {\n color: ${s.textOnDark};\n }\n\n .svu-subtitle {\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n color: ${s.textSecondary};\n margin: 0 0 20px 0;\n text-align: center;\n }\n\n .svu-subtitle strong {\n color: ${s.textPrimary};\n font-weight: 500;\n }\n\n /* Drop Zone */\n .svu-drop-zone {\n width: 100%;\n border: 2px dashed ${s.border};\n border-radius: 12px;\n padding: 32px 24px;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s ease, background 0.15s ease;\n margin-bottom: 16px;\n }\n\n .svu-drop-zone:hover {\n border-color: ${s.borderHover};\n background: ${s.bgSubtle};\n }\n\n .svu-drop-zone.svu-dragging {\n border-color: ${s.primary};\n background: ${s.primaryLight};\n }\n\n .svu-drop-zone.svu-has-file {\n border-style: solid;\n border-color: ${s.primary};\n background: ${s.primaryLight};\n cursor: default;\n }\n\n .svu-drop-icon {\n color: ${s.textMuted};\n margin-bottom: 12px;\n }\n\n .svu-drop-text {\n font-size: 14px;\n font-weight: 500;\n color: ${s.textPrimary};\n margin: 0 0 4px 0;\n }\n\n .svu-drop-subtext {\n font-size: 13px;\n color: ${s.textSecondary};\n margin: 0 0 8px 0;\n }\n\n .svu-drop-hint {\n font-size: 12px;\n color: ${s.textMuted};\n margin: 0;\n }\n\n /* Selected File */\n .svu-selected-file {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n }\n\n .svu-file-icon {\n color: ${s.primary};\n flex-shrink: 0;\n }\n\n .svu-file-info {\n flex: 1;\n min-width: 0;\n text-align: left;\n }\n\n .svu-file-name {\n display: block;\n font-size: 14px;\n font-weight: 500;\n color: ${s.textPrimary};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .svu-file-size {\n display: block;\n font-size: 12px;\n color: ${s.textSecondary};\n }\n\n .svu-remove-file {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 50%;\n cursor: pointer;\n font-size: 18px;\n color: ${s.textMuted};\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .svu-remove-file:hover {\n background: ${s.bgHover};\n color: ${s.error};\n }\n\n /* Max Size */\n .svu-max-size {\n font-size: 12px;\n color: ${s.textMuted};\n margin: 0 0 16px 0;\n }\n\n /* Upload Button */\n .svu-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n padding: 12px 20px;\n font-size: 14px;\n font-weight: 500;\n letter-spacing: -0.005em;\n line-height: 1.4;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s ease, transform 0.1s ease;\n box-sizing: border-box;\n }\n\n .svu-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .svu-btn:active:not(:disabled) {\n transform: scale(0.98);\n }\n\n .svu-btn-primary {\n background: ${s.primary};\n color: ${s.textOnPrimary};\n box-shadow: ${s.shadowSm};\n }\n\n .svu-btn-primary:hover:not(:disabled) {\n background: ${s.primaryHover};\n }\n\n .svu-btn-secondary {\n background: ${s.bgSubtle};\n color: ${s.textPrimary};\n border: 1px solid ${s.border};\n }\n\n .svu-btn-secondary:hover:not(:disabled) {\n background: ${s.bgHover};\n }\n\n /* Error Alert */\n .svu-error-alert {\n background: ${s.errorLight};\n border: 1px solid ${s.errorBorder};\n color: ${s.error};\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 450;\n margin-bottom: 16px;\n width: 100%;\n }\n\n /* Metadata Grid */\n .svu-metadata {\n width: 100%;\n margin-top: 20px;\n padding-top: 20px;\n border-top: 1px solid ${s.border};\n }\n\n .svu-metadata h4 {\n font-size: 12px;\n font-weight: 600;\n color: ${s.textSecondary};\n text-transform: uppercase;\n letter-spacing: 0.05em;\n margin: 0 0 12px 0;\n }\n\n .svu-metadata-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 8px;\n }\n\n .svu-metadata-item {\n font-size: 12px;\n }\n\n .svu-metadata-item.svu-full-width {\n grid-column: span 2;\n }\n\n .svu-metadata-label {\n display: block;\n color: ${s.textMuted};\n margin-bottom: 2px;\n }\n\n .svu-metadata-value {\n display: block;\n color: ${s.textPrimary};\n font-weight: 500;\n }\n\n .svu-metadata-value.svu-status-active {\n color: ${s.success};\n }\n\n /* ========================================\n UPLOADING VIEW\n ======================================== */\n\n .svu-uploading-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .svu-stages {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 12px;\n margin: 24px 0;\n width: 100%;\n }\n\n .svu-stage {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n opacity: 0.5;\n transition: opacity 0.3s ease;\n }\n\n .svu-stage.svu-active {\n opacity: 1;\n }\n\n .svu-stage span {\n font-size: 11px;\n color: ${s.textMutedOnDark};\n }\n\n .svu-stage-sub {\n font-size: 10px !important;\n color: ${s.primary} !important;\n }\n\n .svu-stage-arrow {\n width: 24px;\n height: 2px;\n background: ${s.borderDark};\n position: relative;\n }\n\n .svu-stage-arrow.svu-active::after {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n height: 100%;\n background: ${s.primary};\n animation: svu-arrow-flow 1s ease-in-out infinite;\n }\n\n @keyframes svu-arrow-flow {\n 0% { width: 0; }\n 50% { width: 100%; }\n 100% { width: 100%; }\n }\n\n /* Progress Bar */\n .svu-progress {\n width: 100%;\n margin: 20px 0;\n }\n\n .svu-progress-bar {\n width: 100%;\n height: 6px;\n background: ${s.borderDark};\n border-radius: 3px;\n overflow: hidden;\n }\n\n .svu-progress-fill {\n height: 100%;\n background: ${s.primary};\n border-radius: 3px;\n transition: width 0.3s ease;\n }\n\n .svu-progress-text {\n display: flex;\n justify-content: space-between;\n margin-top: 8px;\n font-size: 12px;\n color: ${s.textMutedOnDark};\n }\n\n /* Forging Info */\n .svu-forging-info {\n width: 100%;\n margin-top: 20px;\n padding: 16px;\n background: ${s.bgDarkSubtle};\n border-radius: 8px;\n }\n\n .svu-forging-line {\n font-size: 12px;\n color: ${s.textMutedOnDark};\n margin: 0 0 8px 0;\n }\n\n .svu-forging-line:last-child {\n margin-bottom: 0;\n }\n\n .svu-mono {\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, monospace;\n color: ${s.textOnDark};\n }\n\n /* ========================================\n CEREMONY VIEW\n ======================================== */\n\n .svu-ceremony-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n\n .svu-ceremony-steps {\n width: 100%;\n margin: 20px 0;\n }\n\n .svu-ceremony-step {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 0;\n opacity: 0.4;\n transition: opacity 0.3s ease;\n }\n\n .svu-ceremony-step.svu-active {\n opacity: 1;\n }\n\n .svu-ceremony-step.svu-complete {\n opacity: 0.7;\n }\n\n .svu-step-icon {\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: ${s.primary};\n }\n\n .svu-step-text {\n font-size: 13px;\n color: ${s.textOnDark};\n }\n\n /* Spinning loader */\n .svu-step-icon .svu-spin {\n animation: svu-spin 0.7s linear infinite;\n }\n\n /* ========================================\n COMPLETE VIEW\n ======================================== */\n\n .svu-complete-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n animation: svu-scale-in 0.3s ease;\n }\n\n @keyframes svu-scale-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n .svu-success-icon {\n color: ${s.success};\n margin-bottom: 16px;\n }\n\n .svu-success-title {\n font-size: 20px;\n font-weight: 600;\n color: ${s.textPrimary};\n margin: 0 0 24px 0;\n text-align: center;\n }\n\n .svu-success-details {\n width: 100%;\n background: ${s.bgSubtle};\n border-radius: 8px;\n padding: 16px;\n margin-bottom: 16px;\n }\n\n .svu-success-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 0;\n font-size: 13px;\n border-bottom: 1px solid ${s.border};\n }\n\n .svu-success-row:last-child {\n border-bottom: none;\n }\n\n .svu-success-label {\n color: ${s.textSecondary};\n }\n\n .svu-success-value {\n color: ${s.textPrimary};\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .svu-copy-btn {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n color: ${s.textMuted};\n transition: background 0.15s ease, color 0.15s ease;\n }\n\n .svu-copy-btn:hover {\n background: ${s.bgHover};\n color: ${s.primary};\n }\n\n .svu-success-guidance {\n font-size: 13px;\n color: ${s.textSecondary};\n text-align: center;\n margin: 0 0 20px 0;\n line-height: 1.5;\n }\n\n /* ========================================\n ERROR VIEW\n ======================================== */\n\n .svu-error-view {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n }\n\n .svu-error-icon {\n color: ${s.error};\n margin-bottom: 16px;\n }\n\n .svu-error-title {\n font-size: 18px;\n font-weight: 600;\n color: ${s.textPrimary};\n margin: 0 0 8px 0;\n }\n\n .svu-error-message {\n font-size: 14px;\n color: ${s.textSecondary};\n margin: 0 0 16px 0;\n line-height: 1.5;\n }\n\n .svu-error-code {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 10px;\n background: ${s.errorLight};\n border: 1px solid ${s.errorBorder};\n border-radius: 6px;\n margin-bottom: 20px;\n }\n\n .svu-error-code-label {\n font-size: 10px;\n font-weight: 600;\n color: #991B1B;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .svu-error-code-value {\n font-size: 11px;\n font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, monospace;\n color: ${s.error};\n font-weight: 500;\n }\n\n /* ========================================\n SECURITY SIDEBAR\n ======================================== */\n\n .svu-sidebar {\n width: 320px;\n background: ${s.bgDark};\n border-left: 1px solid ${s.borderDark};\n color: ${s.textOnDark};\n padding: 20px;\n overflow-y: auto;\n flex-shrink: 0;\n }\n\n .svu-sidebar-toggle {\n display: flex;\n align-items: center;\n gap: 4px;\n background: transparent;\n border: none;\n color: ${s.textMutedOnDark};\n font-size: 12px;\n cursor: pointer;\n padding: 0;\n margin-bottom: 16px;\n }\n\n .svu-sidebar-toggle:hover {\n color: ${s.textOnDark};\n }\n\n .svu-sidebar-logo {\n margin-bottom: 20px;\n }\n\n .svu-sidebar-logo img {\n height: 24px;\n width: auto;\n }\n\n .svu-sidebar-intro h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 0 0 8px 0;\n }\n\n .svu-sidebar-intro p {\n font-size: 12px;\n color: ${s.textMutedOnDark};\n line-height: 1.5;\n margin: 0 0 20px 0;\n }\n\n .svu-sidebar-security h4 {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n font-weight: 600;\n margin: 0 0 12px 0;\n }\n\n .svu-security-intro {\n font-size: 11px;\n color: ${s.textMutedOnDark};\n line-height: 1.5;\n margin: 0 0 16px 0;\n }\n\n .svu-security-intro strong {\n color: ${s.textOnDark};\n }\n\n .svu-key-chain {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-bottom: 16px;\n }\n\n .svu-key-item {\n display: flex;\n gap: 12px;\n padding: 10px;\n background: ${s.bgDarkSubtle};\n border-radius: 6px;\n }\n\n .svu-key-number {\n width: 20px;\n height: 20px;\n background: ${s.primary};\n color: ${s.textOnPrimary};\n border-radius: 50%;\n font-size: 11px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .svu-key-info {\n flex: 1;\n }\n\n .svu-key-name {\n display: block;\n font-size: 11px;\n font-weight: 600;\n color: ${s.textOnDark};\n margin-bottom: 2px;\n }\n\n .svu-key-algo {\n display: block;\n font-size: 10px;\n color: ${s.primary};\n margin-bottom: 4px;\n }\n\n .svu-key-desc {\n display: block;\n font-size: 10px;\n color: ${s.textMutedOnDark};\n line-height: 1.4;\n }\n\n .svu-key-connector {\n display: flex;\n justify-content: center;\n color: ${s.textMutedOnDark};\n }\n\n .svu-encryption-result {\n display: flex;\n gap: 8px;\n font-size: 10px;\n color: ${s.textMutedOnDark};\n line-height: 1.5;\n padding: 10px;\n background: ${s.bgDarkSubtle};\n border-radius: 6px;\n margin-bottom: 16px;\n }\n\n .svu-encryption-result svg {\n color: ${s.success};\n flex-shrink: 0;\n }\n\n .svu-encryption-result strong {\n color: ${s.textOnDark};\n }\n\n .svu-security-badges {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .svu-tls-badge {\n font-size: 9px;\n font-weight: 500;\n padding: 4px 8px;\n background: ${s.bgDarkSubtle};\n border-radius: 4px;\n color: ${s.textMutedOnDark};\n }\n\n /* ========================================\n INLINE CONTAINER\n ======================================== */\n\n .svu-inline-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n background: ${s.bg};\n color: ${s.textPrimary};\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n border-radius: 12px;\n border: 1px solid ${s.border};\n overflow: hidden;\n }\n\n .svu-inline-container.svu-dark {\n background: ${s.bgDark};\n color: ${s.textOnDark};\n border-color: ${s.borderDark};\n }\n\n /* ========================================\n RESPONSIVE\n ======================================== */\n\n @media (max-width: 768px) {\n .svu-modal.svu-with-sidebar {\n flex-direction: column;\n max-width: 480px;\n }\n\n .svu-sidebar {\n width: 100%;\n border-left: none;\n border-top: 1px solid ${s.borderDark};\n max-height: 300px;\n }\n }\n\n @media (max-width: 480px) {\n .svu-modal {\n max-width: 100%;\n max-height: 100%;\n border-radius: 0;\n }\n\n .svu-overlay {\n padding: 0;\n }\n\n .svu-body {\n padding: 20px;\n }\n }\n\n /* ========================================\n ACCESSIBILITY\n ======================================== */\n\n .svu-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n `}(e),document.head.appendChild(t)}const de={organizationName:"",logoLightUrl:null,logoDarkUrl:null};class ce{constructor(){this.elements=null,this.onCloseCallback=null,this.keydownHandler=null,this.overlayClickHandler=null,this.closeBtnClickHandler=null,this.closeBtn=null,this.backdropBlur=!0,this.isDarkMode=!1,this.headerElement=null,this.branding=de}createLoading(e,t){this.create({branding:de,backdropBlur:e.backdropBlur},t)}create(e,t){if(this.elements)return;this.onCloseCallback=t,this.backdropBlur=!1!==e.backdropBlur,this.branding=e.branding||de,le({branding:this.branding,backdropBlur:this.backdropBlur});const n=document.createElement("div");n.id="sparkvault-upload-overlay",n.className=this.backdropBlur?"svu-overlay svu-blur":"svu-overlay",n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-labelledby","svu-modal-title");const s=document.createElement("div");s.id="sparkvault-upload-modal",s.className="svu-modal";const i=document.createElement("div");i.className="svu-modal-main";const r=this.createHeader(this.branding);this.headerElement=r;const o=document.createElement("div");o.className="svu-body";const a=document.createElement("div");a.className="svu-footer";const l=document.createElement("span");l.className="svu-footer-text",l.appendChild(document.createTextNode("Secured by "));const d=document.createElement("a");d.href="https://sparkvault.com",d.target="_blank",d.rel="noopener noreferrer",d.className="svu-footer-link",d.textContent="SparkVault",l.appendChild(d),a.appendChild(l),i.appendChild(r),i.appendChild(o),i.appendChild(a),s.appendChild(i),n.appendChild(s),this.overlayClickHandler=e=>{e.target===n&&this.handleClose()},n.addEventListener("click",this.overlayClickHandler),this.keydownHandler=e=>{"Escape"===e.key&&this.handleClose()},document.addEventListener("keydown",this.keydownHandler),document.body.appendChild(n),document.body.style.overflow="hidden",this.elements={overlay:n,modal:s,main:i,header:r,body:o,footer:a,sidebar:null}}createHeader(e){const t=document.createElement("div");t.className="svu-header";const n=document.createElement("div");n.className="svu-header-title";const s=this.isDarkMode?e.logoDarkUrl||e.logoLightUrl:e.logoLightUrl||e.logoDarkUrl;if(s){const t=document.createElement("img");t.className="svu-logo",t.src=s,t.alt=e.organizationName,n.appendChild(t);const i=document.createElement("span");i.className="svu-sr-only",i.id="svu-modal-title",i.textContent=e.organizationName,n.appendChild(i)}else if(e.organizationName){const t=document.createElement("h2");t.className="svu-company-name",t.id="svu-modal-title",t.textContent=e.organizationName,n.appendChild(t)}return this.closeBtn=document.createElement("button"),this.closeBtn.className="svu-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.innerHTML='\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n ',this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(n),t.appendChild(this.closeBtn),t}updateBranding(e){if(!this.elements)return;this.branding=e;const t=this.createHeader(e);this.headerElement?.parentNode&&this.headerElement.parentNode.replaceChild(t,this.headerElement),this.headerElement=t}updateBackdropBlur(e){this.elements&&(this.backdropBlur=e,e?this.elements.overlay.classList.add("svu-blur"):this.elements.overlay.classList.remove("svu-blur"))}setDarkMode(e){if(!this.elements)return;this.isDarkMode=e,e?this.elements.modal.classList.add("svu-dark"):this.elements.modal.classList.remove("svu-dark");const t=this.createHeader(this.branding);this.headerElement?.parentNode&&this.headerElement.parentNode.replaceChild(t,this.headerElement),this.headerElement=t}toggleSidebar(e){if(this.elements)if(e&&!this.elements.sidebar){const e=this.createSecuritySidebar();this.elements.modal.classList.add("svu-with-sidebar"),this.elements.modal.appendChild(e),this.elements.sidebar=e}else!e&&this.elements.sidebar&&(this.elements.modal.classList.remove("svu-with-sidebar"),this.elements.sidebar.remove(),this.elements.sidebar=null)}createSecuritySidebar(){const e=document.createElement("div");e.className="svu-sidebar";const t=document.createElement("div");if(t.className="svu-sidebar-logo",this.branding.logoDarkUrl){const e=document.createElement("img");e.src=this.branding.logoDarkUrl,e.alt=this.branding.organizationName,t.appendChild(e)}e.appendChild(t);const n=document.createElement("div");n.className="svu-sidebar-intro",n.innerHTML="\n <h3>Secure File Transfer</h3>\n <p>This file is secured with SparkVault's advanced multi-key cryptography and end-to-end encryption.</p>\n ",e.appendChild(n);const s=document.createElement("div");return s.className="svu-sidebar-security",s.innerHTML='\n <h4>\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>\n </svg>\n SparkVault\'s Triple Zero-Trust\n </h4>\n <p class="svu-security-intro">\n Decryption requires <strong>three independent Master Keys</strong>, held in three different physical locations, by three separate companies, all cryptographically combined in real-time.\n </p>\n <div class="svu-key-chain">\n <div class="svu-key-item">\n <div class="svu-key-number">1</div>\n <div class="svu-key-info">\n <span class="svu-key-name">Kyber-1024 Post-Quantum Key</span>\n <span class="svu-key-algo">ML-KEM lattice-based encapsulation</span>\n <span class="svu-key-desc">Quantum-resistant key exchange</span>\n </div>\n </div>\n <div class="svu-key-connector">\n <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n </div>\n <div class="svu-key-item">\n <div class="svu-key-number">2</div>\n <div class="svu-key-info">\n <span class="svu-key-name">X25519 Ephemeral Key</span>\n <span class="svu-key-algo">Elliptic-curve Diffie-Hellman</span>\n <span class="svu-key-desc">Perfect forward secrecy</span>\n </div>\n </div>\n <div class="svu-key-connector">\n <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n </div>\n <div class="svu-key-item">\n <div class="svu-key-number">3</div>\n <div class="svu-key-info">\n <span class="svu-key-name">HKDF-SHA512 Derived Key</span>\n <span class="svu-key-algo">Hardware-bound key derivation</span>\n <span class="svu-key-desc">Vault master key in secure enclave</span>\n </div>\n </div>\n </div>\n <div class="svu-encryption-result">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n <span>Combined via <strong>HKDF</strong> producing <strong>AES-256-GCM</strong> authenticated cipher</span>\n </div>\n <div class="svu-security-badges">\n <span class="svu-tls-badge">TLS 1.3 In Transit</span>\n <span class="svu-tls-badge">Encrypted At Rest</span>\n <span class="svu-tls-badge">Zero Knowledge</span>\n </div>\n ',e.appendChild(s),e}handleClose(){this.onCloseCallback&&this.onCloseCallback()}getBody(){return this.elements?.body??null}getSidebar(){return this.elements?.sidebar??null}isOpen(){return null!==this.elements}destroy(){this.keydownHandler&&(document.removeEventListener("keydown",this.keydownHandler),this.keydownHandler=null),this.elements&&this.overlayClickHandler&&(this.elements.overlay.removeEventListener("click",this.overlayClickHandler),this.overlayClickHandler=null),this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.elements&&(this.elements.overlay.remove(),this.elements=null),this.headerElement=null,document.body.style.overflow="",this.onCloseCallback=null}}const he={showHeader:!0,showCloseButton:!0,showFooter:!0};class pe{constructor(e,t={}){this.container=null,this.header=null,this.body=null,this.footer=null,this.sidebar=null,this.closeBtn=null,this.onCloseCallback=null,this.closeBtnClickHandler=null,this.isDarkMode=!1,this.branding={organizationName:"",logoLightUrl:null,logoDarkUrl:null},this.targetElement=e,this.containerOptions={...he,...t}}createLoading(e,t){if(!this.container){if(this.onCloseCallback=t,le({branding:this.branding,backdropBlur:!1}),this.container=document.createElement("div"),this.container.className="svu-inline-container",this.containerOptions.showHeader&&(this.header=this.createHeader(this.branding),this.container.appendChild(this.header)),this.body=document.createElement("div"),this.body.className="svu-body",this.container.appendChild(this.body),this.containerOptions.showFooter){this.footer=document.createElement("div"),this.footer.className="svu-footer";const e=document.createElement("span");e.className="svu-footer-text",e.appendChild(document.createTextNode("Secured by "));const t=document.createElement("a");t.href="https://sparkvault.com",t.target="_blank",t.rel="noopener noreferrer",t.className="svu-footer-link",t.textContent="SparkVault",e.appendChild(t),this.footer.appendChild(e),this.container.appendChild(this.footer)}this.targetElement.innerHTML="",this.targetElement.appendChild(this.container)}}updateBranding(e){if(this.container&&(this.branding=e,this.containerOptions.showHeader&&this.header)){const t=this.createHeader(e);this.container.replaceChild(t,this.header),this.header=t}}updateBackdropBlur(e){}setDarkMode(e){if(this.container&&(this.isDarkMode=e,e?this.container.classList.add("svu-dark"):this.container.classList.remove("svu-dark"),this.containerOptions.showHeader&&this.header)){const e=this.createHeader(this.branding);this.container.replaceChild(e,this.header),this.header=e}}toggleSidebar(e){this.container&&(e&&!this.sidebar?(this.sidebar=this.createSecuritySidebar(),this.container.classList.add("svu-with-sidebar"),this.container.appendChild(this.sidebar)):!e&&this.sidebar&&(this.container.classList.remove("svu-with-sidebar"),this.sidebar.remove(),this.sidebar=null))}getBody(){return this.body}getSidebar(){return this.sidebar}isOpen(){return null!==this.container}destroy(){this.closeBtn&&this.closeBtnClickHandler&&(this.closeBtn.removeEventListener("click",this.closeBtnClickHandler),this.closeBtnClickHandler=null,this.closeBtn=null),this.container&&this.container.parentNode&&this.container.remove(),this.container=null,this.header=null,this.body=null,this.footer=null,this.sidebar=null,this.onCloseCallback=null}createHeader(e){const t=document.createElement("div");t.className="svu-header";const n=document.createElement("div");n.className="svu-header-title";const s=this.isDarkMode?e.logoDarkUrl||e.logoLightUrl:e.logoLightUrl||e.logoDarkUrl;if(s){const t=document.createElement("img");t.className="svu-logo",t.src=s,t.alt=e.organizationName,n.appendChild(t);const i=document.createElement("span");i.className="svu-sr-only",i.textContent=e.organizationName,n.appendChild(i)}else if(e.organizationName){const t=document.createElement("h2");t.className="svu-company-name",t.textContent=e.organizationName,n.appendChild(t)}return t.appendChild(n),this.containerOptions.showCloseButton&&(this.closeBtn=document.createElement("button"),this.closeBtn.className="svu-close-btn",this.closeBtn.setAttribute("aria-label","Close"),this.closeBtn.innerHTML='\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M18 6L6 18M6 6l12 12"/>\n </svg>\n ',this.closeBtnClickHandler=()=>this.handleClose(),this.closeBtn.addEventListener("click",this.closeBtnClickHandler),t.appendChild(this.closeBtn)),t}createSecuritySidebar(){const e=document.createElement("div");e.className="svu-sidebar";const t=document.createElement("div");if(t.className="svu-sidebar-logo",this.branding.logoDarkUrl){const e=document.createElement("img");e.src=this.branding.logoDarkUrl,e.alt=this.branding.organizationName,t.appendChild(e)}e.appendChild(t);const n=document.createElement("div");n.className="svu-sidebar-intro",n.innerHTML="\n <h3>Secure File Transfer</h3>\n <p>This file is secured with SparkVault's advanced multi-key cryptography and end-to-end encryption.</p>\n ",e.appendChild(n);const s=document.createElement("div");return s.className="svu-sidebar-security",s.innerHTML='\n <h4>\n <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>\n </svg>\n SparkVault\'s Triple Zero-Trust\n </h4>\n <p class="svu-security-intro">\n Decryption requires <strong>three independent Master Keys</strong>, held in three different physical locations, by three separate companies, all cryptographically combined in real-time.\n </p>\n <div class="svu-key-chain">\n <div class="svu-key-item">\n <div class="svu-key-number">1</div>\n <div class="svu-key-info">\n <span class="svu-key-name">Kyber-1024 Post-Quantum Key</span>\n <span class="svu-key-algo">ML-KEM lattice-based encapsulation</span>\n <span class="svu-key-desc">Quantum-resistant key exchange</span>\n </div>\n </div>\n <div class="svu-key-connector">\n <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n </div>\n <div class="svu-key-item">\n <div class="svu-key-number">2</div>\n <div class="svu-key-info">\n <span class="svu-key-name">X25519 Ephemeral Key</span>\n <span class="svu-key-algo">Elliptic-curve Diffie-Hellman</span>\n <span class="svu-key-desc">Perfect forward secrecy</span>\n </div>\n </div>\n <div class="svu-key-connector">\n <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M12 5v14M5 12h14"/>\n </svg>\n </div>\n <div class="svu-key-item">\n <div class="svu-key-number">3</div>\n <div class="svu-key-info">\n <span class="svu-key-name">HKDF-SHA512 Derived Key</span>\n <span class="svu-key-algo">Hardware-bound key derivation</span>\n <span class="svu-key-desc">Vault master key in secure enclave</span>\n </div>\n </div>\n </div>\n <div class="svu-encryption-result">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M20 6L9 17l-5-5"/>\n </svg>\n <span>Combined via <strong>HKDF</strong> producing <strong>AES-256-GCM</strong> authenticated cipher</span>\n </div>\n <div class="svu-security-badges">\n <span class="svu-tls-badge">TLS 1.3 In Transit</span>\n <span class="svu-tls-badge">Encrypted At Rest</span>\n <span class="svu-tls-badge">Zero Knowledge</span>\n </div>\n ',e.appendChild(s),e}handleClose(){this.onCloseCallback&&this.onCloseCallback()}}const ue=[{text:"File received by Forge",duration:600},{text:"Deriving Triple Zero-Trust encryption keys",duration:800},{text:"Encrypting with AES-256-GCM",duration:900},{text:"Generating cryptographic signatures",duration:700},{text:"Storing in post-quantum protected vault",duration:600},{text:"Verifying integrity",duration:400}];function me(e){const t=new Uint8Array(e.match(/.{2}/g).map(e=>parseInt(e,16)));return btoa(String.fromCharCode(...t)).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function ve(e){if(0===e)return"0 B";const t=Math.floor(Math.log(e)/Math.log(1024));return`${parseFloat((e/Math.pow(1024,t)).toFixed(2))} ${["B","KB","MB","GB","TB"][t]}`}class ge{constructor(e,t,n,s){this.viewState={view:"loading"},this.config=null,this.selectedFile=null,this.fileInputElement=null,this.pasteHandler=null,this.container=e,this.api=t,this.options=n,this.callbacks=s}async start(){this.container.createLoading({backdropBlur:this.options.backdropBlur},()=>this.handleClose()),this.setState({view:"loading"});try{const[e]=await Promise.all([this.api.getVaultUploadInfo(this.options.vaultId),new Promise(e=>setTimeout(e,1e3))]);this.config=e,this.container.updateBranding(e.branding),this.setState({view:"form",config:e})}catch(e){this.handleApiError(e)}}close(){this.cleanupFileInput(),this.cleanupPasteHandler(),this.container.destroy()}handleClose(){this.close(),this.callbacks.onCancel()}setState(e){this.viewState=e,this.render()}render(){const e=this.container.getBody();if(!e)return;e.innerHTML="";const t=this.container;if("setDarkMode"in t){const e="uploading"===this.viewState.view||"ceremony"===this.viewState.view;t.setDarkMode(e),this.container.toggleSidebar(e)}switch(this.viewState.view){case"loading":e.appendChild(this.renderLoading());break;case"form":e.appendChild(this.renderForm(this.viewState.config,this.viewState.error));break;case"uploading":e.appendChild(this.renderUploading(this.viewState));break;case"ceremony":e.appendChild(this.renderCeremony(this.viewState));break;case"complete":e.appendChild(this.renderComplete(this.viewState.result,this.viewState.config));break;case"error":e.appendChild(this.renderError(this.viewState))}}renderLoading(){const e=document.createElement("div");return e.className="svu-loading",e.innerHTML='\n <div class="svu-spinner"></div>\n <p class="svu-loading-text">Establishing secure connection...</p>\n ',e}renderForm(e,t){const n=document.createElement("div");n.className="svu-form-view";const s=document.createElement("h2");s.className="svu-title",s.textContent="Cryptographically Secure File Transfer",n.appendChild(s);const i=document.createElement("p");if(i.className="svu-subtitle",i.innerHTML=`Destination Vault: <strong>${this.escapeHtml(e.vaultName)}</strong>`,n.appendChild(i),t){const e=document.createElement("div");e.className="svu-error-alert",e.textContent=t,n.appendChild(e)}const r=document.createElement("div");if(r.className="svu-drop-zone"+(this.selectedFile?" svu-has-file":""),this.selectedFile){r.innerHTML=`\n <div class="svu-selected-file">\n <div class="svu-file-icon">\n <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>\n <path d="M14 2v6h6"/>\n </svg>\n </div>\n <div class="svu-file-info">\n <span class="svu-file-name">${this.escapeHtml(this.selectedFile.name)}</span>\n <span class="svu-file-size">${ve(this.selectedFile.size)}</span>\n </div>\n <button class="svu-remove-file" aria-label="Remove file">&times;</button>\n </div>\n `;const e=r.querySelector(".svu-remove-file");e&&e.addEventListener("click",e=>{e.stopPropagation(),this.selectedFile=null,this.render()})}else r.innerHTML='\n <div class="svu-drop-icon">\n <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/>\n <path d="M17 8l-5-5-5 5"/>\n <path d="M12 3v12"/>\n </svg>\n </div>\n <p class="svu-drop-text">Drag & drop a file here</p>\n <p class="svu-drop-subtext">or click to select</p>\n <p class="svu-drop-hint">Paste from clipboard also supported (Ctrl+V)</p>\n ';r.addEventListener("dragover",e=>{e.preventDefault(),r.classList.add("svu-dragging")}),r.addEventListener("dragleave",e=>{e.preventDefault(),r.classList.remove("svu-dragging")}),r.addEventListener("drop",t=>{t.preventDefault(),r.classList.remove("svu-dragging");const n=t.dataTransfer?.files[0];n&&this.handleFileSelect(n,e)}),r.addEventListener("click",()=>{this.selectedFile||this.openFileSelector(e)}),n.appendChild(r);const o=document.createElement("p");if(o.className="svu-max-size",o.textContent=`Max upload size: ${ve(e.maxSizeBytes)}`,n.appendChild(o),this.selectedFile){const t=document.createElement("button");t.className="svu-btn svu-btn-primary",t.textContent="Upload Securely",t.onclick=()=>this.startUpload(e),n.appendChild(t)}const a=document.createElement("div");return a.className="svu-metadata",a.innerHTML=`\n <h4>Transfer Details</h4>\n <div class="svu-metadata-grid">\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Recipient</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.branding.organizationName)}</span>\n </div>\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Vault</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.vaultName)}</span>\n </div>\n <div class="svu-metadata-item svu-full-width">\n <span class="svu-metadata-label">Vault ID</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.vaultId)}</span>\n </div>\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Encryption</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.encryption.algorithm)}</span>\n </div>\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Key Derivation</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.encryption.keyDerivation)}</span>\n </div>\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Post-Quantum</span>\n <span class="svu-metadata-value">${this.escapeHtml(e.encryption.postQuantum)}</span>\n </div>\n <div class="svu-metadata-item">\n <span class="svu-metadata-label">Forge Status</span>\n <span class="svu-metadata-value ${"active"===e.forgeStatus?"svu-status-active":""}">\n ${"active"===e.forgeStatus?"● Active":"○ Inactive"}\n </span>\n </div>\n </div>\n `,n.appendChild(a),this.setupPasteHandler(e),n}renderUploading(e){const t=document.createElement("div");t.className="svu-uploading-view";const n=me(e.ingotId.replace("ing_",""));return t.innerHTML=`\n <h2 class="svu-title">Streaming & Encrypting</h2>\n\n <div class="svu-stages">\n <div class="svu-stage svu-active">\n <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <rect x="2" y="3" width="20" height="18" rx="2"/>\n <path d="M2 9h20"/>\n <circle cx="6" cy="6" r="1" fill="currentColor"/>\n <circle cx="10" cy="6" r="1" fill="currentColor"/>\n </svg>\n <span>Your Browser</span>\n </div>\n <div class="svu-stage-arrow svu-active"></div>\n <div class="svu-stage svu-active">\n <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>\n </svg>\n <span>SparkVault</span>\n <span class="svu-stage-sub">Encrypting</span>\n </div>\n <div class="svu-stage-arrow"></div>\n <div class="svu-stage">\n <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <rect x="3" y="3" width="18" height="18" rx="2"/>\n <circle cx="12" cy="12" r="3"/>\n <path d="M12 9V6M12 18v-3M9 12H6M18 12h-3"/>\n </svg>\n <span>${this.escapeHtml(this.config?.branding.organizationName||"")}</span>\n </div>\n </div>\n\n <div class="svu-progress">\n <div class="svu-progress-bar">\n <div class="svu-progress-fill" style="width: ${e.progress}%"></div>\n </div>\n <div class="svu-progress-text">\n <span>${e.progress}%</span>\n <span>${ve(e.bytesUploaded)} / ${ve(e.file.size)}</span>\n </div>\n </div>\n\n <div class="svu-forging-info">\n <p class="svu-forging-line">Forging Ingot ID: <span class="svu-mono">${n}</span></p>\n <p class="svu-forging-line">Secure Transfer Channel: <span class="svu-mono">${e.requestId}</span></p>\n </div>\n `,t}renderCeremony(e){const t=document.createElement("div");t.className="svu-ceremony-view";const n=me(e.ingotId.replace("ing_",""));let s="";return ue.forEach((t,n)=>{const i=n<e.step,r=n===e.step;s+=`\n <div class="svu-ceremony-step ${i?"svu-complete":""} ${r?"svu-active":""}">\n <span class="svu-step-icon">\n ${i?'<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 6L9 17l-5-5"/></svg>':r?'<svg class="svu-spin" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>':""}\n </span>\n <span class="svu-step-text">${t.text}</span>\n </div>\n `}),t.innerHTML=`\n <h2 class="svu-title">Securing Your File</h2>\n\n <div class="svu-ceremony-steps">\n ${s}\n </div>\n\n <div class="svu-forging-info">\n <p class="svu-forging-line">Forging Ingot ID: <span class="svu-mono">${n}</span></p>\n <p class="svu-forging-line">Secure Transfer Channel: <span class="svu-mono">${e.requestId}</span></p>\n </div>\n `,t}renderComplete(e,t){const n=document.createElement("div");n.className="svu-complete-view",n.innerHTML=`\n <div class="svu-success-icon">\n <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>\n <path d="M22 4L12 14.01l-3-3"/>\n </svg>\n </div>\n\n <h2 class="svu-success-title">Your file has been securely sent!</h2>\n\n <div class="svu-success-details">\n <div class="svu-success-row">\n <span class="svu-success-label">Ingot ID</span>\n <span class="svu-success-value svu-mono">\n ${this.escapeHtml(e.ingotId)}\n <button class="svu-copy-btn" aria-label="Copy Ingot ID">\n <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>\n <path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/>\n </svg>\n </button>\n </span>\n </div>\n <div class="svu-success-row">\n <span class="svu-success-label">File</span>\n <span class="svu-success-value">${this.escapeHtml(e.filename)}</span>\n </div>\n <div class="svu-success-row">\n <span class="svu-success-label">Size</span>\n <span class="svu-success-value">${ve(e.sizeBytes)}</span>\n </div>\n <div class="svu-success-row">\n <span class="svu-success-label">Timestamp</span>\n <span class="svu-success-value svu-mono">${this.escapeHtml(e.uploadTime)}</span>\n </div>\n <div class="svu-success-row">\n <span class="svu-success-label">Encryption</span>\n <span class="svu-success-value">AES-256-GCM</span>\n </div>\n </div>\n\n <p class="svu-success-guidance">\n ${this.escapeHtml(t.branding.organizationName)} has been notified and can access this file\n from their SparkVault dashboard. Save the Ingot ID above for your records.\n </p>\n\n <button class="svu-btn svu-btn-secondary">\n <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">\n <path d="M1 4v6h6M23 20v-6h-6"/>\n <path d="M20.49 9A9 9 0 005.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 013.51 15"/>\n </svg>\n Upload Another File\n </button>\n `;const s=n.querySelector(".svu-copy-btn");s&&s.addEventListener("click",()=>{navigator.clipboard.writeText(e.ingotId)});const i=n.querySelector(".svu-btn-secondary");return i&&i.addEventListener("click",()=>{this.selectedFile=null,this.setState({view:"form",config:t})}),n}renderError(e){const t=document.createElement("div");t.className="svu-error-view";const n=e.httpStatus||404,s=402===n?"Service Unavailable":"Resource Not Found";return t.innerHTML=`\n <div class="svu-error-icon">\n <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">\n <circle cx="12" cy="12" r="10"/>\n <path d="M12 8v4M12 16h.01"/>\n </svg>\n </div>\n\n <h2 class="svu-error-title">${n} - ${s}</h2>\n\n <p class="svu-error-message">${this.escapeHtml(e.message)}</p>\n\n <div class="svu-error-code">\n <span class="svu-error-code-label">Code</span>\n <span class="svu-error-code-value">${this.escapeHtml(e.code)}</span>\n </div>\n `,t}handleFileSelect(e,t){e.size>t.maxSizeBytes?this.setState({view:"form",config:t,error:`File size exceeds maximum allowed (${ve(t.maxSizeBytes)})`}):(this.selectedFile=e,this.setState({view:"form",config:t}))}openFileSelector(e){this.cleanupFileInput(),this.fileInputElement=document.createElement("input"),this.fileInputElement.type="file",this.fileInputElement.style.display="none",this.fileInputElement.onchange=()=>{const t=this.fileInputElement?.files?.[0];t&&this.handleFileSelect(t,e)},document.body.appendChild(this.fileInputElement),this.fileInputElement.click()}cleanupFileInput(){this.fileInputElement&&(this.fileInputElement.remove(),this.fileInputElement=null)}setupPasteHandler(e){this.cleanupPasteHandler(),this.pasteHandler=t=>{const n=t.clipboardData?.items;if(n)for(const t of n)if("file"===t.kind){const n=t.getAsFile();if(n){this.handleFileSelect(n,e);break}}},document.addEventListener("paste",this.pasteHandler)}cleanupPasteHandler(){this.pasteHandler&&(document.removeEventListener("paste",this.pasteHandler),this.pasteHandler=null)}async startUpload(e){if(!this.selectedFile)return;const t=this.selectedFile,n=`${Date.now().toString(16)}${Math.random().toString(16).substring(2,10)}`;try{const{forgeUrl:s,ingotId:i}=await this.api.initiateUpload(e.vaultId,t.name,t.size,t.type||"application/octet-stream");this.setState({view:"uploading",file:t,ingotId:i,requestId:n,progress:0,bytesUploaded:0}),await this.uploadWithTus(t,s,i,n),await this.runCeremony(t,i,n);const r=new Date,o=`${r.getUTCFullYear()}-${String(r.getUTCMonth()+1).padStart(2,"0")}-${String(r.getUTCDate()).padStart(2,"0")} ${String(r.getUTCHours()).padStart(2,"0")}:${String(r.getUTCMinutes()).padStart(2,"0")}:${String(r.getUTCSeconds()).padStart(2,"0")} UTC`,a={ingotId:i,vaultId:e.vaultId,filename:t.name,sizeBytes:t.size,uploadTime:o};this.callbacks.onProgress?.({bytesUploaded:t.size,bytesTotal:t.size,percentage:100,phase:"complete"}),this.setState({view:"complete",result:a,config:e}),this.callbacks.onSuccess(a)}catch(e){this.handleApiError(e)}}async uploadWithTus(e,t,n,s){return new Promise((i,r)=>{const o=new XMLHttpRequest;o.timeout=6e5,o.upload.onprogress=t=>{if(t.lengthComputable){const i=Math.round(t.loaded/t.total*100);this.setState({view:"uploading",file:e,ingotId:n,requestId:s,progress:i,bytesUploaded:t.loaded}),this.callbacks.onProgress?.({bytesUploaded:t.loaded,bytesTotal:t.total,percentage:i,phase:"uploading"})}},o.onload=()=>{o.status>=200&&o.status<300?i():r(new Error(`Upload failed with status ${o.status}`))},o.onerror=()=>r(new Error("Upload failed")),o.ontimeout=()=>r(new Error("Upload timed out")),o.open("POST",t),o.setRequestHeader("Content-Type",e.type||"application/octet-stream"),o.send(e)})}async runCeremony(e,t,n){for(let s=0;s<ue.length;s++)this.setState({view:"ceremony",file:e,ingotId:t,requestId:n,step:s,complete:!1}),this.callbacks.onProgress?.({bytesUploaded:e.size,bytesTotal:e.size,percentage:100,phase:"ceremony"}),await new Promise(e=>setTimeout(e,ue[s].duration));this.setState({view:"ceremony",file:e,ingotId:t,requestId:n,step:ue.length,complete:!0}),await new Promise(e=>setTimeout(e,500))}handleApiError(e){if(e instanceof re)404===e.httpStatus?this.setState({view:"error",message:"The requested upload endpoint could not be located. This may occur if the upload link has expired, been disabled, or was entered incorrectly.",code:"NOT_FOUND",httpStatus:404}):402===e.httpStatus?this.setState({view:"error",message:"This upload endpoint has been temporarily disabled due to an account billing issue. Please contact the organization's administrator.",code:"PAYMENT_REQUIRED",httpStatus:402}):this.setState({view:"error",message:e.message,code:e.code,httpStatus:e.httpStatus}),this.callbacks.onError(e);else if(e instanceof Error)this.setState({view:"error",message:e.message,code:"UNKNOWN_ERROR"}),this.callbacks.onError(e);else{const e=new Error("An unexpected error occurred");this.setState({view:"error",message:e.message,code:"UNKNOWN_ERROR"}),this.callbacks.onError(e)}}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}}class be{constructor(e){this.renderer=null,this.attachedElements=new Map,this.config=e,this.api=new oe(e)}async upload(e){if(!e.vaultId)throw new i("vaultId is required");this.renderer&&this.renderer.close();const t=!!e.target?this.createInlineContainer(e.target):new ce,n={...e,backdropBlur:e.backdropBlur??this.config.backdropBlur};return new Promise((s,i)=>{this.renderer=new ge(t,this.api,n,{onSuccess:t=>{e.onSuccess?.(t),s(t)},onError:t=>{e.onError?.(t),i(t)},onCancel:()=>{const t=new a;e.onCancel?.(),i(t)},onProgress:e.onProgress}),this.renderer.start().catch(t=>{e.onError?.(t),i(t)})})}attach(e,t){if(!t.vaultId)throw new i("vaultId is required");let n=null;const s=async e=>{e.preventDefault();try{await this.upload({vaultId:t.vaultId,onSuccess:t.onSuccess,onError:t.onError,onCancel:t.onCancel,onProgress:t.onProgress})}catch{}};return se(()=>{document.querySelectorAll(e).forEach(e=>{e.addEventListener("click",s),this.attachedElements.set(e,()=>{e.removeEventListener("click",s)})}),n=new MutationObserver(t=>{t.forEach(t=>{t.addedNodes.forEach(t=>{t instanceof Element&&(t.matches(e)&&(t.addEventListener("click",s),this.attachedElements.set(t,()=>{t.removeEventListener("click",s)})),t.querySelectorAll(e).forEach(e=>{this.attachedElements.has(e)||(e.addEventListener("click",s),this.attachedElements.set(e,()=>{e.removeEventListener("click",s)}))}))})})}),n.observe(document.body,{childList:!0,subtree:!0})}),()=>{n?.disconnect(),this.attachedElements.forEach(e=>e()),this.attachedElements.clear()}}close(){this.renderer&&(this.renderer.close(),this.renderer=null)}createInlineContainer(e){let t;if("string"==typeof e){const n=document.querySelector(e);if(!(n&&n instanceof HTMLElement))throw new i(`Target selector "${e}" did not match any element`);t=n}else{if(!(e instanceof HTMLElement))throw new i("Target must be a CSS selector string or HTMLElement");t=e}return new pe(t)}async pop(e){return this.upload(e)}async render(e){return this.upload(e)}}class fe{constructor(e,t){this.http=t,this.uploadModule=new be(e);const n=e=>this.uploadModule.upload(e);n.attach=(e,t)=>this.uploadModule.attach(e,t),n.close=()=>this.uploadModule.close(),this.upload=n}async create(e){this.validateCreateOptions(e);const t=await this.http.post("/v1/vaults",{name:e.name,hosted_vmk:e.hostedVmk??!1});return{id:t.data.vault_id,name:t.data.name,vmk:t.data.vmk,createdAt:t.data.created_at,hostedVmk:t.data.hosted_vmk}}async unseal(e,t){if(!e)throw new i("Vault ID is required");if(!t)throw new i("VMK is required");const n=e.startsWith("vlt_")?e:`vlt_${e}`,s=await this.http.post(`/v1/vaults/${n}/unseal`,{vmk:t});return{id:s.data.vault_id,name:s.data.name,vatToken:s.data.vat_token,expiresAt:s.data.expires_at,ingotCount:s.data.ingot_count,storageBytes:s.data.storage_bytes}}async list(){return(await this.http.get("/v1/vaults")).data.vaults.map(e=>({id:e.vault_id,name:e.name,createdAt:e.created_at,ingotCount:e.ingot_count,storageBytes:e.storage_bytes,hostedVmk:e.hosted_vmk}))}async delete(e,t){const n=e.startsWith("vlt_")?e:`vlt_${e}`;await this.http.delete(`/v1/vaults/${n}`,{headers:{"X-VMK":t}})}async uploadIngot(e,t){this.validateUploadOptions(t);const n=t.name??(t.file instanceof File?t.file.name:"unnamed"),s=t.contentType??t.file.type??"application/octet-stream",i=await this.http.post(`/v1/vaults/${e.id}/ingots`,{name:n,content_type:s,size_bytes:t.file.size},{headers:{Authorization:`Bearer ${e.vatToken}`}});return{id:i.data.ingot_id,name:i.data.name,contentType:i.data.content_type,size:i.data.size_bytes,createdAt:i.data.created_at,type:i.data.ingot_type}}async downloadIngot(e,t){const n=t.startsWith("ing_")?t:`ing_${t}`;return this.http.requestRaw(`/v1/vaults/${e.id}/ingots/${n}/download`,{method:"POST",headers:{Authorization:`Bearer ${e.vatToken}`}})}async listIngots(e){return(await this.http.get(`/v1/vaults/${e.id}/ingots`,{headers:{Authorization:`Bearer ${e.vatToken}`}})).data.ingots.map(e=>({id:e.ingot_id,name:e.name,contentType:e.content_type,size:e.size_bytes,createdAt:e.created_at,type:e.ingot_type}))}async deleteIngot(e,t){const n=t.startsWith("ing_")?t:`ing_${t}`;await this.http.delete(`/v1/vaults/${e.id}/ingots/${n}`,{headers:{Authorization:`Bearer ${e.vatToken}`}})}validateCreateOptions(e){if(!e.name?.trim())throw new i("Vault name is required");if(e.name.length>255)throw new i("Vault name must be 255 characters or less")}validateUploadOptions(e){if(!e.file)throw new i("File is required");if(0===e.file.size)throw new i("File cannot be empty")}}let ke=!1;function ye(e){ke=e,e&&xe("info","Debug mode enabled")}function xe(e,t,...n){const s=`[SparkVault] ${(new Date).toISOString().split("T")[1].slice(0,-1)} ${t}`;switch(e){case"debug":ke&&console.debug(s,...n);break;case"info":ke&&console.log(s,...n);break;case"warn":ke&&console.warn(s,...n);break;case"error":console.error(s,...n)}}const we={debug:(e,...t)=>xe("debug",e,...t),info:(e,...t)=>xe("info",e,...t),warn:(e,...t)=>xe("warn",e,...t),error:(e,...t)=>xe("error",e,...t),group:e=>{ke&&console.group(`[SparkVault] ${e}`)},groupEnd:()=>{ke&&console.groupEnd()}};class Ce{constructor(e){!function(e){if(!e.accountId)throw new i("accountId is required",{field:"accountId"});if("string"!=typeof e.accountId)throw new i("accountId must be a string",{field:"accountId",received:typeof e.accountId});if(!e.accountId.startsWith("acc_"))throw new i('accountId must start with "acc_"',{field:"accountId",received:e.accountId})}(e),this.config=function(e){return{accountId:e.accountId,timeout:e.timeout??3e4,apiBaseUrl:"https://api.sparkvault.com",identityBaseUrl:"https://api.sparkvault.com/v1/apps/identity",preloadConfig:!1!==e.preloadConfig,backdropBlur:!1!==e.backdropBlur}}(e);const t=new u(this.config);this.identity=new ie(this.config),this.vaults=new fe(this.config,t)}static init(e){return new Ce(e)}static get version(){return"__VERSION__"}}if("undefined"!=typeof window){const e=function(e){if("undefined"==typeof window||"undefined"==typeof document)return null;const t=document.currentScript;if(!t)return null;const n=t.dataset.accountId;if("true"===t.dataset.debug&&ye(!0),!n)return we.debug("No data-account-id attribute, skipping auto-init"),null;we.info("Auto-initializing SDK...");try{const t=e.init({accountId:n});return we.info("SDK initialized successfully"),t}catch(e){return we.error("Failed to initialize SDK:",e),null}}(Ce);window.SparkVault=e??Ce}e.AuthenticationError=n,e.AuthorizationError=s,e.NetworkError=r,e.PopupBlockedError=l,e.SparkVault=Ce,e.SparkVaultError=t,e.TimeoutError=o,e.UserCancelledError=a,e.ValidationError=i,e.default=Ce,e.logger=we,e.setDebugMode=ye,Object.defineProperty(e,"__esModule",{value:!0})});
2
2
  //# sourceMappingURL=sparkvault.js.map